SPI_EXECUTE_EXTENDED(3)

✨ NAME ✨

SPI_execute_extended β€” bestie, it runs a command, but the parameters come from outside the command text πŸ’…


🌸 SYNOPSIS 🌸

int SPI_execute_extended(const char *command,
                         const SPIExecuteOptions * options)

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so SPI_execute_extended executes a command that might include references to externally supplied parameters. The command text points at a parameter by writing $n, and the options->params object (if you actually pass one) hands over the values and the type info for each of those lil $n symbols. You can also stack a bunch of other execution options into the options struct, so like, it's a whole vibe buffet ✨

The options->params object should normally mark each parameter with the PARAM_FLAG_CONST flag, because a one-shot plan is always used for the query. no cap, always. 🫢

And if options->dest is not NULL? Then result tuples get passed straight to that object as the executor generates them, instead of being accumulated into SPI_tuptable. Using a caller-supplied DestReceiver object is particularly helpful for queries that might generate many tuples, since the data can be processed on-the-fly instead of piling up in memory. it's giving efficiency, it's giving main character energy πŸ”₯


πŸ’– ARGUMENTS πŸ’–

  • const char * command β€” the command string, literally the thing you want run πŸŽ€
  • const SPIExecuteOptions * options β€” a struct containing optional arguments, aka the little bag of settings
🚨 IMPORTANT BESTIE ALERT 🚨 Callers should always zero out the entire options struct, and then fill in whichever fields they want to set. This is how you keep your code forward compatible β€” any fields that get added to the struct in the future will be defined to behave backwards-compatibly if they are zero. so zero it first, fr fr. don't skip this. πŸ™ˆ

the currently available options fields are… πŸ’…

  • ParamListInfo params β€” data structure containing query parameter types and values; NULL if none ⭐
  • bool read_only β€” true for read-only execution 🌈
  • bool allow_nonatomic β€” true allows non-atomic execution of CALL and DO statements (but heads up, this field is ignored unless the SPI_OPT_NONATOMIC flag was passed to SPI_connect_ext) 😭
  • bool must_return_tuples β€” if true, raise error if the query is not of a kind that returns tuples (and to be clear, this does not forbid the case where it happens to return zero tuples β€” zero tuples is still a valid tuple-returning query, okurrr) πŸ’€
  • uint64 tcount β€” maximum number of rows to return, or 0 for no limit πŸ‘‘
  • DestReceiver * dest β€” DestReceiver object that will receive any tuples emitted by the query; if NULL, result tuples are accumulated into a SPI_tuptable structure, as in SPI_execute πŸŽ€
  • ResourceOwner owner β€” This field is present for consistency with SPI_execute_plan_extended, but it is ignored, since the plan used by SPI_execute_extended is never saved. it's literally just there for the vibes ✨

πŸŽ€ RETURN VALUE πŸŽ€

The return value is the same as for SPI_execute. (yes, that's the whole tea β˜•)

When options->dest is NULL, SPI_processed and SPI_tuptable are set as in SPI_execute. 🌸

When options->dest is not NULL, SPI_processed is set to zero and SPI_tuptable is set to NULL. So if a tuple count is required, the caller's DestReceiver object must calculate it. that's on you bestie, the function is not doing it for you πŸ’…πŸ˜­


and that's the whole page!! brought to you by PostgreSQL 18.6, documented back in 2026 β€” mwah, love that for us πŸ«Άβœ¨πŸ’–