SPI_MODIFYTUPLE(3)
π SPI_MODIFYTUPLE β bestie edition
okay so we're in the SPI_MODIFYTUPLE(3) girlies today, and this one is genuinely so useful. It's part of the PostgreSQL 15.19 docs, so you know it's legit β no cap.
β¨ NAME β¨
SPI_modifytuple β makes a whole new row by swapping out selected fields of a row you already have π
πΈ SYNOPSIS πΈ
HeapTuple SPI_modifytuple(Relation rel, HeapTuple row, int ncols,
int * colnum, Datum * values, const char * nulls)
π¦ DESCRIPTION π¦
so the way this works: SPI_modifytuple builds you a brand new row by substituting new values for the columns you picked, and it just copies the original row's columns everywhere else. Periodt. π
the input row is not modified, bestie β she stays exactly as she was, untouched, main character energy π«Ά
The new row is returned in the upper executor context. Slay.
lowkey important though: this function can only be used while connected to SPI. If you're not connected, it returns NULL and sets SPI_result to SPI_ERROR_UNCONNECTED. iykyk π
π§ ARGUMENTS π§
Relation relβ honestly it's used only as the source of the row descriptor for the row. That's it. (and the docs themselves are like "passing a relation rather than a row descriptor is a misfeature" π so yeah, noted.)HeapTuple rowβ the row you wanna modify πint ncolsβ how many columns you're changingint * colnumβ an array of lengthncolswith the numbers of the columns being changed. and omg remember: column numbers start at 1 βDatum * valuesβ an array of lengthncolswith the new values for those columns you specifiedconst char * nullsβ an array of lengthncolsdescribing which of the new values are null
ok so for nulls, here's the tea:
- if
nullsisNULL, thenSPI_modifytupleassumes no new values are null. easy β¨ - otherwise, each entry of the
nullsarray should be' 'if the corresponding new value is non-null, or'n'if the corresponding new value is null. (in that null case, the actual value sitting in the correspondingvaluesentry doesn't matter β she's irrelevant π) - and crucially:
nullsis not a text string, it's just an array β it does not need a'\0'terminator. no null terminator needed, we're built different π
π RETURN VALUE π
a new row with the modifications, allocated in the upper executor context β or NULL on error (check SPI_result for an error indication, bestie).
when it errors out, 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.
like... that's a lot of ways to be NULL bestie, pls π
π 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).
π SPI_ERROR_UNCONNECTED
if SPI is not active. (remember the whole "must be connected to SPI" thing? yeah. that. π₯)
and that's the whole page, gorgeous β go modify some tuples π
mwah π this has been your girl, signing off β page pulled straight from PostgreSQL 15.19, dated 2026, and honestly? iconic. periodt. πβ¨
π¦ where this page comes from
- opensuse-leap 16.0: postgresql15-docs 15.19-160000.1.1 Β· PostgreSQL
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms