SPI_MODIFYTUPLE(3)

πŸ’– SPI_MODIFYTUPLE(3) πŸ’–

okay bestie, gather round, because we're talking about SPI_modifytuple β€” yes the manual page, yes it's real, yes it's iconic ✨


🌸 NAME 🌸

SPI_modifytuple β€” make a whole new row by swapping out some of the fields in a row you already have πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

HeapTuple SPI_modifytuple(Relation rel, HeapTuple row, int ncols,
                          int * colnum, Datum * values, const char * nulls)

πŸ’… DESCRIPTION πŸ’…

so basically? SPI_modifytuple builds you a brand new row by subbing in new values for the columns you picked, and it just copies the original row's columns everywhere else. it's giving "glow up but only for the columns you chose" πŸ’–

the input row is not modified. like, at all. she stays exactly as she was. no cap.

the new row gets returned in the upper executor context.

and here's the important part, bestie: this function can only be used while you're connected to SPI. if you're not? she returns NULL and sets SPI_result to SPI_ERROR_UNCONNECTED. no connection, no service, periodt πŸ’€


✨ ARGUMENTS ✨

  • Relation rel β€” literally only used as the source of the row descriptor for the row. that's it. that's her whole job. (and ngl, the original docs say passing a relation instead of a row descriptor is a misfeature β€” so, yeah, we all know, we're just not making it a thing πŸ™ˆ)
  • HeapTuple row β€” the row you wanna modify πŸŽ€
  • int ncols β€” how many columns you're changing, count 'em
  • int * colnum β€” an array of length ncols holding the numbers of the columns you want to change. and heads up: column numbers start at 1, not 0, iykyk
  • Datum * values β€” an array of length ncols with the new values for those columns you named
  • const char * nulls β€” an array of length ncols that says which of the new values are null
    • if nulls is NULL, then SPI_modifytuple just assumes none of the new values are null. easy, low effort, love that for us πŸ’…
    • otherwise, each entry in the nulls array should be ' ' if that new value is non-null, or 'n' if that new value is null. (and in that 'n' case, the actual value sitting in the matching values entry literally does not matter, so don't stress 🫢)
    • and pls note: nulls is not a text string, she's just an array. she does not need a '\0' terminator. do not come for her with string energy, that's not the vibe πŸ’€

πŸ‘‘ RETURN VALUE πŸ‘‘

you get back the new row with the modifications, allocated in the upper executor context. or, if things went sideways, NULL on error (go check SPI_result for the error indication, she'll tell you what happened πŸ”).

on error, SPI_result gets set like this:

  • SPI_ERROR_ARGUMENT β€” if rel is NULL, or if row is NULL, or if ncols is less than or equal to 0, or if colnum is NULL, or if values is NULL. basically if you handed her nothing, or negative somethings, she's not doing that 😭
  • SPI_ERROR_NOATTRIBUTE β€” if colnum contains an invalid column number (less than or equal to 0, or greater than the number of columns in row). remember: start at 1, stay in range ✨
  • SPI_ERROR_UNCONNECTED β€” if SPI is not active. no SPI, no row, that's the rule 🌈

fr fr bestie, the vibes here are simple: you in SPI? you get a row. you not in SPI? you get NULL and an error code. choose wisely 🧚

and that's the whole page, we ate, no crumbs left πŸ“

this lil masterpiece came to you courtesy of PostgreSQL 18.6, dated 2026, and honestly? iconic of them. k bye πŸ’–βœ¨πŸŽ€