SPI_CURSOR_OPEN(3)
π SPI_CURSOR_OPEN(3) β ok bestie, let's talk cursors
Hey so this is the SPI_CURSOR_OPEN(3) page from the PostgreSQL 16.15 Documentation, and honestly? It's a good one. Let's go.
β¨ NAME β¨
SPI_cursor_open β sets up a cursor using a statement you already made with SPI_prepare. That's it. That's the whole vibe.
π SYNOPSIS π
Portal SPI_cursor_open(const char * name, SPIPlanPtr plan,
Datum * values, const char * nulls,
bool read_only)
πΈ DESCRIPTION πΈ
Okay so SPI_cursor_open sets up a cursor (internally, a portal β that's the secret name, iykyk) that will execute a statement prepared by SPI_prepare. All the parameters mean exactly the same thing as the corresponding parameters to SPI_execute_plan. Same energy, different function.
So why would you use a cursor instead of just executing the statement directly? Two reasons, and they're both lowkey iconic:
- The result rows can be retrieved a few at a time, which avoids memory overrun for queries that return many rows. Like, your query said "here's a million rows" and your RAM said "bestie no". The cursor fixes that.
- A portal can outlive the current C function β it can, in fact, live to the end of the current transaction. So returning the portal name to the C function's caller gives you a whole way of returning a row set as a result. Main character portal behaviour, fr fr.
And a little detail that matters: the passed-in parameter data will be copied into the cursor's portal, so you can free it while the cursor still exists. No dangling, no drama. π
π¦ ARGUMENTS π¦
const char * nameβ the name for the portal, orNULLto let the system pick a name for you. Let the system choose, honestly, it's giving delegating queen.SPIPlanPtr planβ the prepared statement (the thingSPI_preparereturned to you).Datum * valuesβ an array of actual parameter values. Must have the same length as the statement's number of arguments. No, you can't skip one. Yes, it has to match. βconst char * nullsβ an array describing which parameters are null. Also must have the same length as the statement's number of arguments. Matching set, periodt.
If nulls is NULL then SPI_cursor_open assumes that no parameters are null. Otherwise, each entry of the nulls array should be ' ' if the corresponding parameter value is non-null, or 'n' if the corresponding parameter value is null. (In that latter case, the actual value in the corresponding values entry doesn't matter β it's null, bestie, the value is in its flop era and we ignore it.) Note that nulls is not a text string, just an array: it does not need a '\0' terminator. Please don't add one, it's not that kind of array. π
bool read_onlyβtruefor read-only execution. Simple as that. π«Ά
π RETURN VALUE π
Pointer to the portal containing the cursor. π
β οΈ Heads up: there is no error return convention. Any error will be reported viaelog. So if something goes wrong, you're not getting aNULLback β you're getting an elog in your face. Plan accordingly. π
π§ sign-off π§
That's the page, bestie β brought to you by PostgreSQL 16.15, dated 2026. Go forth and open some cursors responsibly. πβ¨
π¦ where this page comes from
- opensuse-leap 16.0: postgresql16-docs 16.15-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