From 535980aa402840ca26040f023cfab3e6ea3911fe Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 27 Aug 2003 22:13:35 +0000 Subject: [PATCH] Major cleanup of SPI chapter --- doc/src/sgml/spi.sgml | 6217 ++++++++++++++++------------------------- 1 file changed, 2432 insertions(+), 3785 deletions(-) diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index b3c65204c4..f3b11b5a1c 100644 --- a/doc/src/sgml/spi.sgml +++ b/doc/src/sgml/spi.sgml @@ -1,3821 +1,2462 @@ - - - - -Vadim -Mikheev - - -Transcribed 1998-01-16 - + + Server Programming Interface -Server Programming Interface + + SPI + - -The Server Programming Interface -(SPI) gives users the -ability to run SQL queries inside user-defined -C functions. - + + The Server Programming Interface + (SPI) gives users the ability to run + SQL commands inside user-defined + C functions. SPI is a set of + interface functions to simplify access to the parser, planner, + optimizer, and executor. SPI also does some + memory management. + - - -The available Procedural Languages (PL) give an alternate -means to build functions that can execute queries. - - + + To avoid misunderstanding we'll use the term function + when we speak of SPI interface functions and + procedure for user-defined C-functions, which may be + using SPI. + - -In fact, SPI is just a set of native interface functions -to simplify access to the Parser, Planner, Optimizer and Executor. -SPI also does some memory management. - + + Note that if during the execution of a procedure the transaction is + aborted because of an error in a command, then control will not be + returned to your procedure. Rather, all work will be rolled back + and the server will wait for the next command from the client. A + related restriction is the inability to execute + BEGIN, COMMIT, and + ROLLBACK (transaction control statements) inside + a procedure. Both of these restrictions will probably be changed in + the future. + - -To avoid misunderstanding we'll use function -to mean SPI interface functions and -procedure for user-defined C-functions -using SPI. - + + SPI functions return a nonnegative result on + success (either via a returned integer value or in the global + variable SPI_result, as described below). On + error, a negative result or NULL will be returned. + - -Procedures which use SPI are called by the -Executor. The SPI calls recursively invoke the -Executor in turn to run queries. When the Executor is invoked -recursively, it may itself call procedures which may make -SPI calls. - + + Source code files that use SPI must include the header file + executor/spi.h. + - -Note that if during execution of a query from a procedure the transaction is -aborted, then control will not be returned to your procedure. Rather, all work -will be rolled back and the server will wait for the next command from the -client. This will probably be changed in future versions. - + + + The available procedural languages provide different means to + execute SQL commands from procedures. Some of these are modelled + after SPI, so this documentation might be of use for those users as + well. + + - -A related restriction is the inability to execute BEGIN, END and ABORT -(transaction control statements). This will also be -changed in the future. - - -If successful, SPI functions return a non-negative result (either via -a returned integer value or in SPI_result global variable, as described below). -On error, a negative or NULL result will be returned. - + + Interface Functions - -Interface Functions + + + SPI_connect + - - -SPI_connect -SPI - Connection Management - - -SPI_connect - - - Connects your procedure to the SPI manager. - -SPIconnecting -SPI_connect - - - -1997-12-24 - - + + SPI_connect + connect a procedure to the SPI manager + + + SPI_connect + + + int SPI_connect(void) - + + - - -1997-12-24 - -Inputs - -None - - + + Description - - -1997-12-24 - -Outputs - - - -int - - - -Return status - - -SPI_OK_CONNECT - - - - if connected - - - - -SPI_ERROR_CONNECT - - - - if not connected - - - - - - - - - - + + SPI_connect opens a connection from a + procedure invocation to the SPI manager. You must call this + function if you want to execute commands through SPI. Some utility + SPI functions may be called from unconnected procedures. + - - -1997-12-24 - -Description - - -SPI_connect opens a connection from a procedure -invocation to the SPI manager. - You must call this function if you will need to execute queries. Some - utility SPI functions may be called from un-connected procedures. - - + If your procedure is already connected, - SPI_connect will return an - SPI_ERROR_CONNECT error. Note that this - may happen if a procedure which has called - SPI_connect directly calls another procedure - which itself calls SPI_connect. While - recursive calls to the SPI manager are permitted - when an SPI query invokes another function which - uses SPI, directly nested calls to - SPI_connect and - SPI_finish are forbidden. - - - -Usage - - - - - - -Algorithm - -SPI_connect performs the following: - Initializes the SPI internal - structures for query execution and memory management. - - - - + SPI_connect will return the error code + SPI_ERROR_CONNECT. This could happen if + a procedure that has called SPI_connect + directly calls another procedure that calls + SPI_connect. While recursive calls to the + SPI manager are permitted when an SQL command + called through SPI invokes another function that uses + SPI, directly nested calls to + SPI_connect and + SPI_finish are forbidden. + + + + + Return Value + + + + SPI_OK_CONNECT + + + on success + + + + + + SPI_ERROR_CONNECT + + + on error + + + + + + - - - - -SPI_finish -SPI - Connection Management - - -SPI_finish - - - Disconnects your procedure from the SPI manager. - -SPIdisconnecting -SPI_finish - - - -1997-12-24 - - -SPI_finish(void) - + + + SPI_finish + - - -1997-12-24 - -Inputs - -None - - + + SPI_finish + disconnect a procedure from the SPI manager + - - -1997-12-24 - -Outputs - - - -int - - - - - -SPI_OK_FINISH - if properly disconnected - - -SPI_ERROR_UNCONNECTED - if called from an un-connected procedure - - - - - - - - + SPI_finish - - -1997-12-24 - -Description - - -SPI_finish closes an existing connection to the -SPI manager. - You must call this function after completing the SPI operations needed - during your procedure's current invocation. - - - You may get the error return SPI_ERROR_UNCONNECTED if SPI_finish is - called without having a current valid connection. - There is no fundamental problem - with this; it means that nothing was done by the SPI manager. - - - -Usage - - - SPI_finish must be called as a final step by a connected procedure, - or you may get - unpredictable results! However, you do not need to worry about making -this happen if the transaction is aborted via elog(ERROR). In that case -SPI will clean itself up. + + +int SPI_finish(void) + + - - - -Algorithm - -SPI_finish performs the following: - Disconnects your procedure from the SPI manager and frees all memory - allocations made by your procedure via palloc since - the SPI_connect. - These allocations can't be used any more! See Memory management. - - - - + + Description + + + SPI_finish closes an existing connection to + the SPI manager. You must call this function after completing the + SPI operations needed during your procedure's current invocation. + You do not need to worry about making this happen, however, if you + abort the transaction via elog(ERROR). In that + case SPI will clean itself up automatically. + + + + If SPI_finish is called without having a valid + connection, it will return SPI_ERROR_UNCONNECTED. + There is no fundamental problem with this; it means that the SPI + manager has nothing to do. + + + + + Return Value + + + + SPI_OK_FINISH + + + if properly disconnected + + + + + + SPI_ERROR_UNCONNECTED + + + if called from an unconnected procedure + + + + + + - - - - -SPI_exec -SPI - Connection Management - - -SPI_exec - - - Creates an execution plan (parser+planner+optimizer) and executes a query. - -SPIexecuting -SPI_exec - - - -1997-12-24 - - -SPI_exec(query, tcount) - + + + SPI_exec + - - -1997-12-24 - -Inputs - - - - -const char * query - - - -String containing query plan - - - - - -int tcount - - - -Maximum number of tuples to return - - - - - + + SPI_exec + execute a command + - - -1997-12-24 - -Outputs - - - -int - - - - - - SPI_ERROR_UNCONNECTED if called from an un-connected procedure - - - SPI_ERROR_ARGUMENT if query is NULL or tcount < 0. - - - SPI_ERROR_UNCONNECTED if procedure is unconnected. - - - SPI_ERROR_COPY if COPY TO/FROM stdin. - - - SPI_ERROR_CURSOR if DECLARE/CLOSE CURSOR, FETCH. - - - SPI_ERROR_TRANSACTION if BEGIN/ABORT/END. - - - SPI_ERROR_OPUNKNOWN if type of query is unknown (this shouldn't occur). - - - - - If execution of your query was successful then one of the following - (non-negative) values will be returned: - - - SPI_OK_UTILITY if some utility (e.g. CREATE TABLE ...) was executed - - - SPI_OK_SELECT if SELECT (but not SELECT ... INTO!) was executed - - - SPI_OK_SELINTO if SELECT ... INTO was executed - - - SPI_OK_INSERT if INSERT (or INSERT ... SELECT) was executed - - - SPI_OK_DELETE if DELETE was executed - - - SPI_OK_UPDATE if UPDATE was executed - - - - - - - - + SPI_exec - - -1997-12-24 - -Description - - -SPI_exec creates an execution plan (parser+planner+optimizer) - and executes the query for tcount tuples. + + +int SPI_exec(const char * command, int count) + + - - - -Usage - - - This should only be called from a connected procedure. - If tcount is zero then it executes the query for all tuples returned by the - query scan. Using tcount > 0 you may restrict the number of tuples for - which the query will be executed (much like a LIMIT clause). For example, + + Description - -SPI_exec ("INSERT INTO tab SELECT * FROM tab", 5); - + + SPI_exec executes the specified SQL command + for count rows. + -will allow at most 5 tuples to be inserted into table. + + This function should only be called from a connected procedure. If + count is zero then it executes the command + for all rows that it applies to. If count + is greater than 0, then the number of rows for which the command + will be executed is restricted (much like a + LIMIT clause). For example, + +SPI_exec("INSERT INTO tab SELECT * FROM tab", 5); + + will allow at most 5 rows to be inserted into the table. + - If execution of your query was successful then a non-negative value will be returned. + + You may pass multiple commands in one string, and the command may + be rewritten by rules. SPI_exec returns the + result for the command executed last. + - - -You may pass multiple queries in one string or query string may be - re-written by RULEs. SPI_exec returns the result for the last query - executed. - - - - - The actual number of tuples for which the (last) query was executed is - returned in the global variable SPI_processed (if not SPI_OK_UTILITY). + + The actual number of rows for which the (last) command was executed + is returned in the global variable SPI_processed + (unless the return value of the function is + SPI_OK_UTILITY). If the return value of the + function is SPI_OK_SELECT then you may the use + global pointer SPITupleTable *SPI_tuptable to + access the result rows. + - If SPI_OK_SELECT is returned then you may use global - pointer SPITupleTable *SPI_tuptable to access the result tuples. - + + The structure SPITupleTable is defined + thus: + +typedef struct +{ + MemoryContext tuptabcxt; /* memory context of result table */ + uint32 alloced; /* number of alloced vals */ + uint32 free; /* number of free vals */ + TupleDesc tupdesc; /* row descriptor */ + HeapTuple *vals; /* rows */ +} SPITupleTable; + + vals is an array of pointers to rows. (The number + of valid entries is given by SPI_processed). + tupdesc is a row descriptor which you may pass to + SPI functions dealing with rows. tuptabcxt, + alloced, and free are internal + fields not intended for use by SPI callers. + - - SPI_exec may return one of the following (negative) values: - - - SPI_ERROR_ARGUMENT if query is NULL or tcount < 0. - - - SPI_ERROR_UNCONNECTED if procedure is unconnected. - - - SPI_ERROR_COPY if COPY TO/FROM stdin. - - - SPI_ERROR_CURSOR if DECLARE/CLOSE CURSOR, FETCH. - - - SPI_ERROR_TRANSACTION if BEGIN/ABORT/END. - - - SPI_ERROR_OPUNKNOWN if type of query is unknown (this shouldn't occur). - - + + SPI_finish frees all + SPITupleTables allocated during the current + procedure. You can free a particular result table earlier, if you + are done with it, by calling SPI_freetuptable. + + - - - - -Structures - - - If SPI_OK_SELECT is returned then you may use the global - pointer SPITupleTable *SPI_tuptable to access the selected tuples. - + + Arguments - - Structure SPITupleTable is defined in spi.h: - - typedef struct - { - MemoryContext tuptabcxt; /* memory context of result table */ - uint32 alloced; /* # of alloced vals */ - uint32 free; /* # of free vals */ - TupleDesc tupdesc; /* tuple descriptor */ - HeapTuple *vals; /* tuples */ - } SPITupleTable; - - + + + const char * command + + + string containing command to execute + + + - - vals is an array of pointers to tuples (the number of useful entries - is given by SPI_processed). tupdesc is - a tuple descriptor which you may pass to SPI functions dealing with - tuples. tuptabcxt, alloced, and free are internal fields not intended - for use by SPI callers. - + + int count + + + maximum number of rows to process or return + + + + + - - - Functions SPI_exec, SPI_execp and - SPI_prepare change both SPI_processed and SPI_tuptable - (just the pointer, not the contents of the structure). - Save these two global variables into local procedure variables if you need - to access the result of one SPI_exec or - SPI_execp across later calls. - - + + Return Value - - SPI_finish frees all SPITupleTables allocated during - the current procedure. You can free a particular result table earlier, - if you are done with it, by calling SPI_freetuptable. - - - + + If the execution of the command was successful then one of the + following (nonnegative) values will be returned: + + + + SPI_OK_SELECT + + + if a SELECT (but not SELECT + ... INTO) was executed + + + + + + SPI_OK_SELINTO + + + if a SELECT ... INTO was executed + + + + + + SPI_OK_DELETE + + + if a DELETE was executed + + + + + + SPI_OK_INSERT + + + if an INSERT was executed + + + + + + SPI_OK_UPDATE + + + if an UPDATE was executed + + + + + + SPI_OK_UTILITY + + + if a utility command (e.g., CREATE TABLE) + was executed + + + + + + + + On error, one of the following negative values is returned: + + + + SPI_ERROR_ARGUMENT + + + if command is NULL or + count is less than 0 + + + + + + SPI_ERROR_COPY + + + if COPY TO stdout or COPY FROM stdin + was attempted + + + + + + SPI_ERROR_CURSOR + + + if DECLARE, CLOSE, or FETCH + was attempted + + + + + + SPI_ERROR_TRANSACTION + + + if BEGIN, COMMIT, or + ROLLBACK was attempted + + + + + + SPI_ERROR_OPUNKNOWN + + + if the command type is unknown (shouldn't happen) + + + + + + SPI_ERROR_UNCONNECTED + + + if called from an unconnected procedure + + + + + + + + + Notes + + + The functions SPI_exec, + SPI_execp, and + SPI_prepare change both + SPI_processed and + SPI_tuptable (just the pointer, not the contents + of the structure). Save these two global variables into local + procedure variables if you need to access the result of + SPI_exec or SPI_execp + across later calls. + + + - - - - -SPI_prepare -SPI - Plan Preparation - - -SPI_prepare - - - Prepares a plan for a query, without executing it yet - -SPIconnecting -SPI_prepare - - - -1997-12-24 - - -SPI_prepare(query, nargs, argtypes) - + + + SPI_prepare + - - -1997-12-24 - -Inputs - - - - -const char * query - - - -Query string - - - - - -int nargs - - - -Number of input parameters ($1 ... $nargs - as in SQL-functions) - - - - - -Oid * argtypes - - - -Pointer to array of type OIDs for input parameter types - - - - - + + SPI_prepare + prepare a plan for a command, without executing it yet + - - -1997-12-24 - -Outputs - - - -void * - - - -Pointer to an execution plan (parser+planner+optimizer) - - - - - - + SPI_prepare - - -1997-12-24 - -Description - - -SPI_prepare - creates and returns an execution plan (parser+planner+optimizer) but doesn't - execute the query. Should only be called from a connected procedure. + + +void * SPI_prepare(const char * command, int nargs, Oid * argtypes) + + - - - -Usage - - - When the same or similar query is to be executed repeatedly, it may - be advantageous to perform query planning only once. - SPI_prepare converts a query string into an execution - plan that can be passed repeatedly to SPI_execp. - - - A prepared query can be generalized by writing parameters ($1, $2, etc) - in place of what would be constants in a normal query. The values of - the parameters are then specified when SPI_execp - is called. This allows the prepared query to be used over a wider - range of situations than would be possible without parameters. - - - - However, there is a disadvantage: since the planner does not know the - values that will be supplied for the parameters, it may make worse - query planning choices than it would make for a simple query with - all constants visible. - - - - If the query uses parameters, their number and data types must be - specified in the call to SPI_prepare. - - -The plan returned by SPI_prepare may be used only in current - invocation of the procedure since SPI_finish frees memory allocated for a plan. - But see SPI_saveplan to save a plan for longer. - - - If successful, a non-null pointer will be returned. Otherwise, you'll get - a NULL plan. In both cases SPI_result will be set like the value returned - by SPI_exec, except that it is set to - SPI_ERROR_ARGUMENT if query is NULL or nargs < 0 or nargs > 0 && argtypes - is NULL. + + Description - - - - - + + SPI_prepare creates and returns an execution + plan for the specified command but doesn't execute the command. + This function should only be called from a connected procedure. + + + + When the same or a similar command is to be executed repeatedly, it + may be advantageous to perform the planning only once. + SPI_prepare converts a command string into an + execution plan that can be executed repeatedly using + SPI_execp. + + + + A prepared command can be generalized by writing parameters + ($1, $2, etc.) in place of what would be + constants in a normal command. The actual values of the parameters + are then specified when SPI_execp is called. + This allows the prepared command to be used over a wider range of + situations than would be possible without parameters. + + + + The plan returned by SPI_prepare can be used + only in the current invocation of the procedure since + SPI_finish frees memory allocated for a plan. + But a plan can be saved for longer using the function + SPI_saveplan. + + + + + Arguments + + + + const char * command + + + command string + + + + + + int nargs + + + number of input parameters ($1, $2, etc.) + + + + + + Oid * argtypes + + + pointer to an array containing the OIDs of + the data types of the parameters + + + + + + + + Return Value + + + SPI_prepare returns non-null pointer to an + execution plan. On error, NULL will be returned. + In both cases, SPI_result will be set analogous + to the value returned by SPI_exec, except that + it is set to SPI_ERROR_ARGUMENT if + command is NULL, or if + nargs is less than 0, or if nargs is + greater than 0 and argtypes is NULL. + + + + + Notes + + + There is a disadvantage to using parameters: since the planner does + not know the values that will be supplied for the parameters, it + may make worse planning choices than it would make for a normal + command with all constants visible. + + + - - - - -SPI_execp -SPI - Plan Execution - - -SPI_execp - - -Executes a plan from SPI_prepare - -SPIconnecting -SPI_execp - - - -1997-12-24 - - -SPI_execp(plan, -values, -nulls, -tcount) - + + + SPI_execp + - - -1997-12-24 - -Inputs - - - - -void *plan - - - -Execution plan - - - - - -Datum *values - - - -Actual parameter values - - - - - -const char *nulls - - - -Array describing which parameters are NULLs - -n indicates NULL (values[] entry ignored) -space indicates not NULL (values[] entry is valid) - - - - - - -int tcount - - - -Number of tuples for which plan is to be executed - - - - - + + SPI_execp + executes a plan prepared by SPI_prepare + - - -1997-12-24 - -Outputs - - - -int - - - - Returns the same value as SPI_exec as well as - - - SPI_ERROR_ARGUMENT - if plan - is NULL or tcount < 0 - - - SPI_ERROR_PARAM - if values - is NULL - and plan - was prepared with some parameters. - - - - - - -SPI_tuptable - - - -initialized as in - SPI_exec if successful - - - - -SPI_processed - - - -initialized as in - SPI_exec if successful - - - - - - + SPI_execp - - -1997-12-24 - -Description - - -SPI_execp - executes a plan prepared by SPI_prepare. - tcount has the same - interpretation as in SPI_exec. - - - -Usage - - - If nulls -is NULL then - SPI_execp -assumes that all parameters (if any) are NOT NULL. + + +int SPI_execp(void * plan, Datum * values, const char * nulls, int count) + + - - - If one of the objects (a relation, function, etc.) referenced by the prepared - plan is dropped during your session (by your backend or another process) then the - results of SPI_execp for this plan will be unpredictable. - - + + Description - - - - - + + SPI_execp executes a plan prepared by + SPI_prepare. tcount + has the same interpretation as in SPI_exec. + + + + + Arguments + + + + void * plan + + + execution plan (returned by SPI_prepare) + + + + + + Datum *values + + + actual parameter values + + + + + + const char * nulls + + + An array describing which parameters are null. + n indicates a null value (entry in + values will be ignored); a space indicates a + nonnull value (entry in values is valid). + + + + If nulls is NULL then + SPI_execp assumes that no parameters are + null. + + + + + + int count + + + number of row for which plan is to be executed + + + + + + + + Return Value + + + The return value is the same as for SPI_exec + or one of the following: + + + + SPI_ERROR_ARGUMENT + + + if plan is NULL or + count is less than 0 + + + + + + SPI_ERROR_PARAM + + + if values is NULL and + plan was prepared with some parameters + + + + + + + + SPI_processed and + SPI_tuptable are set as in + SPI_exec if successful. + + + + + Notes + + + If one of the objects (a table, function, etc.) referenced by the + prepared plan is dropped during the session then the result of + SPI_execp for this plan will be unpredictable. + + + - - - - -SPI_cursor_open -SPI - Cursor Support - - -SPI_cursor_open - - -Sets up a cursor using a plan created with SPI_prepare - -SPIcursors -SPI_cursor_open - - - -2001-11-14 - - -SPI_cursor_open(name, -plan, -values, -nulls) - + + + SPI_cursor_open + - - -2001-11-14 - -Inputs - - - - -const char *name - - - -Name for portal, or NULL to let the system select a name - - - - - -void *plan - - - -Execution plan - - - - - -Datum *values - - - -Actual parameter values - - - - - -const char *nulls - - - -Array describing which parameters are NULLs - -n indicates NULL (values[] entry ignored) -space indicates not NULL (values[] entry is valid) - - - - - - + + SPI_cursor_open + set up a cursor using a plan created with SPI_prepare + - - -2001-11-14 - -Outputs - - - -Portal - - - - Pointer to Portal containing cursor, or NULL on error - - - - - - + SPI_cursor_open - - -2001-11-14 - -Description - - -SPI_cursor_open - sets up a cursor (internally, a Portal) that will execute a plan - prepared by SPI_prepare. - - + + +Portal SPI_cursor_open(const char * name, void * plan, Datum * values, const char * nulls) + + + + + Description + + + SPI_cursor_open sets up a cursor (internally, + a portal) that will execute a plan prepared by + SPI_prepare. + + + Using a cursor instead of executing the plan directly has two benefits. First, the result rows can be retrieved a few at a time, avoiding memory overrun for queries that return many rows. Second, - a Portal can outlive the current procedure (it can, in fact, live to - the end of the current transaction). Returning the portal name to - the procedure's caller provides a way of returning a rowset result. - - - -Usage - - - If nulls -is NULL then - SPI_cursor_open -assumes that all parameters (if any) are NOT NULL. - - - - - - - - - - - -SPI_cursor_find -SPI - Cursor Support - - -SPI_cursor_find - - -Finds an existing cursor (Portal) by name - -SPIcursors -SPI_cursor_find - - - -2001-11-14 - - -SPI_cursor_find(name) - - - - -2001-11-14 - -Inputs - - - - -const char *name - - - -Name of portal - - - - - - - - -2001-11-14 - -Outputs - - - -Portal - - - - Pointer to Portal with given name, or NULL if not found - - - - - - - - - -2001-11-14 - -Description - - -SPI_cursor_find - finds a pre-existing Portal by name. This is primarily useful - to resolve a cursor name returned as text by some other function. - - - - - - - - - - - - -SPI_cursor_fetch -SPI - Cursor Support - - -SPI_cursor_fetch - - -Fetches some rows from a cursor - -SPIcursors -SPI_cursor_fetch - - - -2001-11-14 - - -SPI_cursor_fetch(portal, -forward, -count) - - - - -2001-11-14 - -Inputs - - - - -Portal portal - - - -Portal containing cursor - - - - - -bool forward - - - -True for fetch forward, false for fetch backward - - - - - -int count - - - -Maximum number of rows to fetch - - - - - - - - -2001-11-14 - -Outputs - - - -SPI_tuptable - - - -initialized as in - SPI_exec if successful - - - - -SPI_processed - - - -initialized as in - SPI_exec if successful - - - - - - - - - -2001-11-14 - -Description - - -SPI_cursor_fetch - fetches some (more) rows from a cursor. This is equivalent to the - SQL command FETCH. - - - - - - - - - - - - -SPI_cursor_move -SPI - Cursor Support - - -SPI_cursor_move - - -Moves a cursor - -SPIcursors -SPI_cursor_move - - - -2001-11-14 - - -SPI_cursor_move(portal, -forward, -count) - - - - -2001-11-14 - -Inputs - - - - -Portal portal - - - -Portal containing cursor - - - - - -bool forward - - - -True for move forward, false for move backward - - - - - -int count - - - -Maximum number of rows to move - - - - - - - - -2001-11-14 - -Outputs - - - -None - - - - - - - - - - - - -2001-11-14 - -Description - - -SPI_cursor_move - skips over some number of rows in a cursor. This is equivalent to the - SQL command MOVE. - - - - - - - - - - - - -SPI_cursor_close -SPI - Cursor Support - - -SPI_cursor_close - - -Closes a cursor - -SPIcursors -SPI_cursor_close - - - -2001-11-14 - - -SPI_cursor_close(portal) - - - - -2001-11-14 - -Inputs - - - - -Portal portal - - - -Portal containing cursor - - - - - - - - -2001-11-14 - -Outputs - - - -None - - - - - - - - - - - - -2001-11-14 - -Description - - -SPI_cursor_close - closes a previously created cursor and releases its Portal storage. - - - -Usage - - - All open cursors are closed implicitly at transaction end. - SPI_cursor_close need only be invoked if - it is desirable to release resources sooner. - - - - - - - - - - - -SPI_saveplan -SPI - Plan Storage - - -SPI_saveplan - - - Saves a passed plan - -SPIconnecting -SPI_saveplan - - - -1997-12-24 - - -SPI_saveplan(plan) - - - - -1997-12-24 - -Inputs - - - - -void *query - - - -Passed plan - - - - - - - - -1997-12-24 - -Outputs - - - -void * - - - -Execution plan location. NULL if unsuccessful. - - - - -SPI_result - - - - - - SPI_ERROR_ARGUMENT if plan is NULL - - - SPI_ERROR_UNCONNECTED if procedure is un-connected - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_saveplan - stores a plan prepared by SPI_prepare in safe memory - protected from freeing by SPI_finish or the transaction manager. - - - In the current version of PostgreSQL there is no ability to - store prepared plans in the system - catalog and fetch them from there for execution. This will be implemented - in future versions. - - As an alternative, there is the ability to reuse prepared plans in the - subsequent invocations of your procedure in the current session. - Use SPI_execp to execute this saved plan. - - - -Usage - - - SPI_saveplan saves a passed plan (prepared by SPI_prepare) in memory - protected from freeing by SPI_finish and by the transaction manager and - returns a pointer to the saved plan. You may save the pointer returned in - a local variable. Always check if this pointer is NULL or not either when - preparing a plan or using an already prepared plan in SPI_execp (see below). - - - - If one of the objects (a relation, function, etc.) referenced by the prepared - plan is dropped during your session (by your backend or another process) then the - results of SPI_execp for this plan will be unpredictable. - - - - - - - - - - - - -Interface Support Functions - - -The functions described here provide convenient interfaces for extracting -information from tuple sets returned by SPI_exec and other -SPI interface functions. - - - -All functions described in this section may be used by both connected and -unconnected procedures. - - - - - - - - -SPI_fnumber -SPI - Tuple Information - - -SPI_fnumber - - -Finds the attribute number for specified attribute name - -SPIdecoding tuples -SPI_fnumber - - - -1997-12-24 - - -SPI_fnumber(tupdesc, fname) - - - - -1997-12-24 - -Inputs - - - - -TupleDesc tupdesc - - - -Input tuple description - - - - - -const char * fname - - - -Field name - - - - - - - - -1997-12-24 - -Outputs - - - - -int - - - -Attribute number - - -Valid one-based index number of attribute - - -SPI_ERROR_NOATTRIBUTE if the named attribute is not found - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_fnumber - returns the attribute number for the attribute with name in fname. - - - -Usage - - -Attribute numbers are 1 based. - - -If the given fname refers to a system attribute (eg, oid) -then the appropriate negative attribute number will be returned. -The caller should be careful to test for exact equality to -SPI_ERROR_NOATTRIBUTE to detect error; -testing for result <= 0 is not correct unless system attributes -should be rejected. - - - - - - - - - - - - -SPI_fname -SPI - Tuple Information - - -SPI_fname - - -Finds the attribute name for the specified attribute number - -SPIdecoding tuples -SPI_fname - - - -1997-12-24 - - -SPI_fname(tupdesc, fnumber) - - - - -1997-12-24 - -Inputs - - - - -TupleDesc tupdesc - - - -Input tuple description - - - - - -int fnumber - - - -Attribute number - - - - - - - - -1997-12-24 - -Outputs - - - - -char * - - - -Attribute name - - -NULL if fnumber is out of range - - -SPI_result set to -SPI_ERROR_NOATTRIBUTE on error - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_fname - returns the attribute name for the specified attribute. - - - -Usage - - -Attribute numbers are 1 based. - - - -Algorithm - - -Returns a newly-allocated copy of the attribute name. -(Use pfree() to release the copy when done with it.) - - - - - - - - - - - -SPI_getvalue -SPI - Tuple Information - - -SPI_getvalue - - -Returns the string value of the specified attribute - -SPIdecoding tuples -SPI_getvalue - - - -1997-12-24 - - -SPI_getvalue(tuple, tupdesc, fnumber) - - - - -1997-12-24 - -Inputs - - - - -HeapTuple tuple - - - -Input tuple to be examined - - - - - -TupleDesc tupdesc - - - -Input tuple description - - - - - -int fnumber - - - -Attribute number - - - - - - - - -1997-12-24 - -Outputs - - - - -char * - - - -Attribute value or NULL if - - -attribute is NULL - - -fnumber is out of range -(SPI_result set to -SPI_ERROR_NOATTRIBUTE) - - -no output function available -(SPI_result set to -SPI_ERROR_NOOUTFUNC) - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_getvalue - returns an external (string) representation of the value of the specified attribute. - - - -Usage - - -Attribute numbers are 1 based. - - - -Algorithm - - -The result is returned as a palloc'd string. -(Use pfree() to release the string when done with it.) - - - - - - - - - - - -SPI_getbinval -SPI - Tuple Information - - -SPI_getbinval - - -Returns the binary value of the specified attribute - -SPIdecoding tuples -SPI_getbinval - - - -1997-12-24 - - -SPI_getbinval(tuple, tupdesc, fnumber, isnull) - - - - -1997-12-24 - -Inputs - - - - -HeapTuple tuple - - - -Input tuple to be examined - - - - - -TupleDesc tupdesc - - - -Input tuple description - - - - - -int fnumber - - - -Attribute number - - - - - - - - -1997-12-24 - -Outputs - - - - -Datum - - - -Attribute binary value - - - - - -bool * isnull - - - -flag for null value in attribute - - - - - -SPI_result - - - - - -SPI_ERROR_NOATTRIBUTE - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_getbinval - returns the specified attribute's value in internal form (as a Datum). - - - -Usage - - -Attribute numbers are 1 based. - - - -Algorithm - - -Does not allocate new space for the datum. In the case of a pass-by- -reference data type, the Datum will be a pointer into the given tuple. - - - - - - - - - - - -SPI_gettype -SPI - Tuple Information - - -SPI_gettype - - -Returns the type name of the specified attribute - -SPIdecoding tuples -SPI_gettype - - - -1997-12-24 - - -SPI_gettype(tupdesc, fnumber) - - - - -1997-12-24 - -Inputs - - - - -TupleDesc tupdesc - - - -Input tuple description - - - - - -int fnumber - - - -Attribute number - - - - - - - - -1997-12-24 - -Outputs - - - - -char * - - - -The type name for the specified attribute number - - - - - -SPI_result - - - - - -SPI_ERROR_NOATTRIBUTE - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_gettype - returns a copy of the type name for the specified attribute, - or NULL on error. - - - -Usage - - -Attribute numbers are 1 based. - - - -Algorithm - - -Returns a newly-allocated copy of the type name. -(Use pfree() to release the copy when done with it.) - - - - - - - - - - - -SPI_gettypeid -SPI - Tuple Information - - -SPI_gettypeid - - -Returns the type OID of the specified attribute - -SPIdecoding tuples -SPI_gettypeid - - - -1997-12-24 - - -SPI_gettypeid(tupdesc, fnumber) - - - - -1997-12-24 - -Inputs - - - - -TupleDesc tupdesc - - - -Input tuple description - - - - - -int fnumber - - - -Attribute number - - - - - - - - -1997-12-24 - -Outputs - - - - -OID - - - -The type OID for the specified attribute number - - - - - -SPI_result - - - - - -SPI_ERROR_NOATTRIBUTE - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_gettypeid - returns the type OID for the specified attribute. - - - -Usage - - -Attribute numbers are 1 based. - - - - - - - - - - - - -SPI_getrelname -SPI - Tuple Information - - -SPI_getrelname - - -Returns the name of the specified relation - -SPIdecoding tuples -SPI_getrelname - - - -1997-12-24 - - -SPI_getrelname(rel) - - - - -1997-12-24 - -Inputs - - - - -Relation rel - - - -Input relation - - - - - - - - -1997-12-24 - -Outputs - - - - -char * - - - -The name of the specified relation - - - - - - - - - -1997-12-24 - -Description - - -SPI_getrelname - returns the name of the specified relation. - - - - -Algorithm - - -Returns a newly-allocated copy of the rel name. -(Use pfree() to release the copy when done with it.) - - - - - - - - -Memory Management - - -PostgreSQL allocates memory within memory -contexts, which provide a convenient method of -managing allocations made in many different places that need to live -for differing amounts of time. Destroying a context releases all the -memory that was allocated in it. Thus, it is not necessary to keep track -of individual objects to avoid memory leaks --- only a relatively small number -of contexts have to be managed. palloc and related -functions allocate memory from the current context. - - -SPI_connect creates a new memory context and makes -it current. SPI_finish restores the previous -current memory context and destroys the context created by -SPI_connect. These actions ensure that transient -memory allocations made inside your procedure are reclaimed at procedure -exit, avoiding memory leakage. - - -However, if your procedure needs to return an allocated memory object -(such as a value of a pass-by-reference data type), you can't allocate -the return object using palloc, at least not while -you are connected to SPI. If you try, the object will be deallocated -during SPI_finish, and your procedure will not -work reliably! - - -To solve this problem, use SPI_palloc to allocate -your return object. SPI_palloc allocates space -from upper Executor memory --- that is, the memory context -that was current when SPI_connect was called, -which is precisely the right context for return values of your procedure. - - -If called while not connected to SPI, SPI_palloc -acts the same as plain palloc. - - - Before a procedure connects to the SPI manager, the current memory context -is the upper Executor context, so all allocations made by the procedure via -palloc or by SPI utility functions are -made in this context. - - - After SPI_connect is called, the current context is - the procedure's private context made by SPI_connect. - All allocations made via -palloc/repalloc or by SPI utility -functions (except for SPI_copytuple, -SPI_copytupledesc, -SPI_copytupleintoslot, -SPI_modifytuple, -and SPI_palloc) are -made in this context. - - -When a procedure disconnects from the SPI manager (via -SPI_finish) the -current context is restored to the upper Executor context, and all allocations -made in the procedure memory context are freed and can't be used any more! - - - -All functions described in this section may be used by both connected and -unconnected procedures. In an unconnected procedure, they act the same -as the underlying ordinary backend functions (palloc etc). - - - - - - - - -SPI_copytuple -SPI - Tuple Copy - - -SPI_copytuple - - -Makes copy of tuple in upper Executor context - -SPIcopying tuples -SPI_copytuple - - - -1997-12-24 - - -SPI_copytuple(tuple) - - - - -1997-12-24 - -Inputs - - - - -HeapTuple tuple - - - -Input tuple to be copied - - - - - - - - -1997-12-24 - -Outputs - - - - -HeapTuple - - - -Copied tuple - - - non-NULL - if tuple - is not NULL and the copy was successful - - - NULL - only if tuple - is NULL - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_copytuple - makes a copy of tuple in upper Executor context. - - - -Usage - - -TBD - - - - - - - - - - - - -SPI_copytupledesc -SPI - Tuple Descriptor Copy - - -SPI_copytupledesc - - -Makes copy of tuple descriptor in upper Executor context - -SPIcopying tuple descriptors -SPI_copytupledesc - - - -2001-08-02 - - -SPI_copytupledesc(tupdesc) - - - - -2001-08-02 - -Inputs - - - - -TupleDesc tupdesc - - - -Input tuple descriptor to be copied - - - - - - - - -2001-08-02 - -Outputs - - - - -TupleDesc - - - -Copied tuple descriptor - - - non-NULL - if tupdesc - is not NULL and the copy was successful - - - NULL - only if tupdesc - is NULL - - - - - - - - - - - -2001-08-02 - -Description - - -SPI_copytupledesc - makes a copy of tupdesc in upper Executor context. - - - -Usage - - -TBD - - - - - - - - - - - - -SPI_copytupleintoslot -SPI - Tuple and Descriptor Copy - - -SPI_copytupleintoslot - - -Makes copy of tuple and descriptor in upper Executor context - -SPIcopying tuples -SPI_copytupleintoslot - - - -1997-12-24 - - -SPI_copytupleintoslot(tuple, tupdesc) - - - - -1997-12-24 - -Inputs - - - - -HeapTuple tuple - - - -Input tuple to be copied - - - - - -TupleDesc tupdesc - - - -Input tuple descriptor to be copied - - - - - - - - -1997-12-24 - -Outputs - - - - -TupleTableSlot * - - - -Tuple slot containing copied tuple and descriptor - - - non-NULL - if tuple - and tupdesc - are not NULL and the copy was successful - - - NULL - only if tuple - or tupdesc - is NULL - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_copytupleintoslot - makes a copy of tuple in upper Executor context, returning it in the - form of a filled-in TupleTableSlot. - - - -Usage - - -TBD - - - - - - - - - - - - -SPI_modifytuple -SPI - Tuple Modify - - -SPI_modifytuple - - -Creates a tuple by replacing selected fields of a given tuple - -SPImodifying tuples -SPI_modifytuple - - - -1997-12-24 - - -SPI_modifytuple(rel, tuple, nattrs, attnum, Values, Nulls) - - - - -1997-12-24 - -Inputs - - - - -Relation rel - - - -Used only as source of tuple descriptor for tuple. (Passing a relation -rather than a tuple descriptor is a misfeature.) - - - - - -HeapTuple tuple - - - -Input tuple to be modified - - - - - -int nattrs - - - -Number of attribute numbers in attnum array - - - - - -int * attnum - - - -Array of numbers of the attributes that are to be changed - - - - - -Datum * Values - - - -New values for the attributes specified - - - - - -const char * Nulls - - - -Which new values are NULL, if any - - - - - - - - -1997-12-24 - -Outputs - - - - -HeapTuple - - - -New tuple with modifications - - - non-NULL - if tuple - is not NULL and the modify was successful - - - NULL - only if tuple - is NULL - - - - - - - -SPI_result - - - - - - SPI_ERROR_ARGUMENT if rel is NULL or tuple is NULL or natts <= 0 or - attnum is NULL or Values is NULL. - - - SPI_ERROR_NOATTRIBUTE if there is an invalid - attribute number in attnum (attnum <= 0 or > number of - attributes in tuple) - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_modifytuple -creates a new tuple by substituting new values for selected attributes, -copying the original tuple's attributes at other positions. The input -tuple is not modified. - - - -Usage - - -If successful, a pointer to the new tuple is returned. The new tuple is -allocated in upper Executor context. - - - - - - - - - - - - -SPI_palloc -SPI - Memory Management - - -SPI_palloc - - -Allocates memory in upper Executor context - -SPIallocating space -SPI_palloc - - - -1997-12-24 - - -SPI_palloc(size) - - - - -1997-12-24 - -Inputs - - - - -Size size - - - -Octet size of storage to allocate - - - - - - - - -1997-12-24 - -Outputs - - - - -void * - - - -New storage space of specified size - - - - - - - - - -1997-12-24 - -Description - - -SPI_palloc - allocates memory in upper Executor context. - - - -Usage - - -TBD - - - - - - - - - - - - -SPI_repalloc -SPI - Memory Management - - -SPI_repalloc - - -Re-allocates memory in upper Executor context - -SPIallocating space -SPI_repalloc - - - -1997-12-24 - - -SPI_repalloc(pointer, size) - - - - -1997-12-24 - -Inputs - - - - -void * pointer - - - -Pointer to existing storage - - - - - -Size size - - - -Octet size of storage to allocate - - - - - - - - -1997-12-24 - -Outputs - - - - -void * - - - -New storage space of specified size with contents copied from existing area - - - - - - - - - -1997-12-24 - -Description - - -SPI_repalloc - re-allocates memory in upper Executor context. - - - -Usage - - -This function is no longer different from plain repalloc. -It's kept just for backward compatibility of existing code. - - - - - - - - - - - - -SPI_pfree -SPI - Memory Management - - -SPI_pfree - - -Frees memory in upper Executor context - -SPIallocating space -SPI_pfree - - - -1997-12-24 - - -SPI_pfree(pointer) - - - - -1997-12-24 - -Inputs - - - - -void * pointer - - - -Pointer to existing storage - - - - - - - - -1997-12-24 - -Outputs - - - - -None - - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_pfree - frees memory in upper Executor context. - - - -Usage - - -This function is no longer different from plain pfree. -It's kept just for backward compatibility of existing code. - - - - - - - - - - -SPI_freetuple -SPI - Memory Management - - -SPI_freetuple - - -Frees a tuple allocated in upper Executor context - -SPIallocating space -SPI_freetuple - - - -1997-12-24 - - -SPI_freetuple(pointer) - - - - -1997-12-24 - -Inputs - - - - -HeapTuple pointer - - - -Pointer to allocated tuple - - - - - - - - -1997-12-24 - -Outputs - - - - -None - - - - - - - - - - - - -1997-12-24 - -Description - - -SPI_freetuple - frees a tuple previously allocated in upper Executor context. - - - -Usage - - -This function is no longer different from plain heap_freetuple. -It's kept just for backward compatibility of existing code. - - - - - - - - - - -SPI_freetuptable -SPI - Memory Management - - -SPI_freetuptable - - -Frees a tuple set created by SPI_exec or similar function - -SPIallocating space -SPI_freetuptable - - - -2001-11-14 - - -SPI_freetuptable(tuptable) - - - - -2001-11-14 - -Inputs - - - - -SPITupleTable * tuptable - - - -Pointer to tuple table - - - - - - - - -2001-11-14 - -Outputs - - - - -None - - - - - - - - - - - - -2001-11-14 - -Description - - -SPI_freetuptable - frees a tuple set created by a prior SPI query function, such as - SPI_exec. - - - -Usage - - -This function is useful if a SPI procedure needs to execute multiple -queries and does not want to keep the results of earlier queries around -until it ends. Note that any unfreed tuple sets will be freed anyway -at SPI_finish. - - - - - - - - - - -SPI_freeplan -SPI - Memory Management - - -SPI_freeplan - - - Releases a previously saved plan - -SPIallocating space -SPI_freeplan - - - -2001-11-14 - - -SPI_freeplan(plan) - - - - -2001-11-14 - -Inputs - - - - -void *plan - - - -Passed plan - - - - - - - - -2001-11-14 - -Outputs - - - -int - - - - - - SPI_ERROR_ARGUMENT if plan is NULL - - - - - - - - - - - -2001-11-14 - -Description - - -SPI_freeplan - releases a query plan previously returned by - SPI_prepare or saved by - SPI_saveplan. - - - - - - - -Visibility of Data Changes - - -PostgreSQL data changes visibility rule: during a query execution, data -changes made by the query itself (via SQL-function, SPI-function, triggers) -are invisible to the query scan. For example, in query + a portal can outlive the current procedure (it can, in fact, live + to the end of the current transaction). Returning the portal name + to the procedure's caller provides a way of returning a row set as + result. + + + + + Arguments + + + + const char * name + + + name for portal, or NULL to let the system + select a name + + + + + + void * plan + + + execution plan (returned by SPI_prepare) + + + + + + Datum * values + + + actual parameter values + + + + + + const char *nulls + + + An array describing which parameters are null values. + n indicates a null value (entry in + values will be ignored); a space indicates a + nonnull value (entry in values is valid). If + nulls is NULL then + SPI_cursor_open assumes that no parameters + are null. + + + + + + + + Return Value + + + pointer to portal containing the cursor, or NULL + on error + + + + + + + + + SPI_cursor_find + + + + SPI_cursor_find + find an existing cursor by name + + + SPI_cursor_find + + + +Portal SPI_cursor_find(const char * name) + + + + + Description + + + SPI_cursor_find finds an existing portal by + name. This is primarily useful to resolve a cursor name returned + as text by some other function. + + + + + Arguments + + + + const char * name + + + name of the portal + + + + + + + + Return Value + + + pointer to the portal with the specified name, or + NULL if none was found + + + + + + + + + SPI_cursor_fetch + + + + SPI_cursor_fetch + fetch some rows from a cursor + + + SPI_cursor_fetch + + + +void SPI_cursor_fetch(Portal portal, bool forward, int count) + + + + + Description + + + SPI_cursor_fetch fetches some rows from a + cursor. This is equivalent to the SQL command FETCH. + + + + + Arguments + + + + Portal portal + + + portal containing the cursor + + + + + + bool forward + + + true for fetch forward, false for fetch backward + + + + + + int count + + + maximum number of rows to fetch + + + + + + + + Return Value + + + SPI_processed and + SPI_tuptable are set as in + SPI_exec if successful. + + + + + + + + + SPI_cursor_move + + + + SPI_cursor_move + move a cursor + + + SPI_cursor_move + + + +void SPI_cursor_move(Portal portal, bool forward, int count) + + + + + Description + + + SPI_cursor_move skips over some number of rows + in a cursor. This is equivalent to the SQL command + MOVE. + + + + + Arguments + + + + Portal portal + + + portal containing the cursor + + + + + + bool forward + + + true for move forward, false for move backward + + + + + + int count + + + maximum number of rows to move + + + + + + + + + + + + SPI_cursor_close + + + + SPI_cursor_close + close a cursor + + + SPI_cursor_close + + + +void SPI_cursor_close(Portal portal) + + + + + Description + + + SPI_cursor_close closes a previously created + cursor and releases its portal storage. + + + + All open cursors are closed automatically at the end of a + transaction. SPI_cursor_close need only be + invoked if it is desirable to release resources sooner. + + + + + Arguments + + + + Portal portal + + + portal containing the cursor + + + + + + + + + + + + SPI_saveplan + + + + SPI_saveplan + save a plan + + + SPI_saveplan + + + +void * SPI_saveplan(void * plan) + + + + + Description + + + SPI_saveplan saves a passed plan (prepared by + SPI_prepare) in memory protected from freeing + by SPI_finish and by the transaction manager + and returns a pointer to the saved plan. This gives you the + ability to reuse prepared plans in the subsequent invocations of + your procedure in the current session. You may save the pointer + returned in a local variable. Always check if this pointer is + NULL or not either when preparing a plan or using + an already prepared plan in SPI_execp. + + + + + Arguments + + + + void * plan + + + the plan to be saved + + + + + + + + Return Value + + + Pointer to the saved plan; NULL if unsuccessful. + On error, SPI_result is set thus: + + + + SPI_ERROR_ARGUMENT + + + if plan is NULL + + + + + + SPI_ERROR_UNCONNECTED + + + if called from an unconnected procedure + + + + + + + + + Notes + + + If one of the objects (a table, function, etc.) referenced by the + prepared plan is dropped during the session then the results of + SPI_execp for this plan will be unpredictable. + + + + + + + + Interface Support Functions + + + The functions described here provide an interface for extracting + information from result sets returned by SPI_exec and + other SPI functions. + + + + All functions described in this section may be used by both + connected and unconnected procedures. + + + + + + + SPI_fname + + + + SPI_fname + determine the column name for the specified column number + + + SPI_fname + + + +char * SPI_fname(TupleDesc rowdesc, int colnumber) + + + + + Description + + + SPI_fname returns the column name of the + specified column. (You can use pfree to + release the copy of the name when you don't need it anymore.) + + + + + Arguments + + + + TupleDesc rowdesc + + + input row description + + + + + + int colnumber + + + column number (count starts at 1) + + + + + + + + Return Value + + + The column name; NULL if + colnumber is out of range. + SPI_result set to + SPI_ERROR_NOATTRIBUTE on error. + + + + + + + + + SPI_fnumber + + + + SPI_fnumber + determine the column number for the specified column name + + + SPI_fnumber + + + +int SPI_fnumber(TupleDesc rowdesc, const char * colname) + + + + + Description + + + SPI_fnumber returns the column number for the + column with the specified name. + + + + If colname refers to a system column (e.g., + oid) then the appropriate negative column number will + be returned. The caller should be careful to test the return value + for exact equality to SPI_ERROR_NOATTRIBUTE to + detect an error; testing the result for less than or equal to 0 is + not correct unless system columns should be rejected. + + + + + Arguments + + + + TupleDesc rowdesc + + + input row description + + + + + + const char * colname + + + column name + + + + + + + + Return Value + + + Column number (count starts at 1), or + SPI_ERROR_NOATTRIBUTE if the named column was not + found. + + + + + + + + + SPI_getvalue + + + + SPI_getvalue + return the string value of the specified column + + + SPI_getvalue + + + +char * SPI_getvalue(HeapTuple row, TupleDesc rowdesc, int colnumber) + + + + + Description + + + SPI_getvalue returns the string representation + of the value of the specified column. + + + + The result is returned in memory allocated using + palloc. (You can use + pfree to release the memory when you don't + need it anymore.) + + + + + Arguments + + + + HeapTuple row + + + input row to be examined + + + + + + TupleDesc rowdesc + + + input row description + + + + + + int colnumber + + + column number (count starts at 1) + + + + + + + + Return Value + + + Column value, or NULL if the column is null, + colnumber is out of range + (SPI_result is set to + SPI_ERROR_NOATTRIBUTE), or no no output function + available (SPI_result is set to + SPI_ERROR_NOOUTFUNC). + + + + + + + + + SPI_getbinval + + + + SPI_getbinval + return the binary value of the specified column + + + SPI_getbinval + + + +Datum SPI_getbinval(HeapTuple row, TupleDesc rowdesc, int colnumber, bool * isnull) + + + + + Description + + + SPI_getbinval returns the value of the + specified column in the internal form (as type Datum). + + + + This function does not allocate new space for the datum. In the + case of a pass-by-reference data type, the return value will be a + pointer into the passed row. + + + + + Arguments + + + + HeapTuple row + + + input row to be examined + + + + + + TupleDesc rowdesc + + + input row description + + + + + + int rownumber + + + column number (count starts at 1) + + + + + + bool * isnull + + + flag for a null value in the column + + + + + + + + Return Value + + + The binary value of the column is returned. The variable pointed + to by isnull is set to true if the column is + null, else to false. + + + + SPI_result is set to + SPI_ERROR_NOATTRIBUTE on error. + + + + + + + + + SPI_gettype + + + + SPI_gettype + return the data type name of the specified column + + + SPI_gettype + + + +char * SPI_gettype(TupleDesc rowdesc, int colnumber) + + + + + Description + + + SPI_gettype returns the data type name of the + specified column. (You can use pfree to + release the copy of the name when you don't need it anymore.) + + + + + Arguments + + + + TupleDesc rowdesc + + + input row description + + + + + + int colnumber + + + column number (count starts at 1) + + + + + + + + Return Value + + + The data type name of the specified column, or + NULL on error. SPI_result is + set to SPI_ERROR_NOATTRIBUTE on error. + + + + + + + + + SPI_gettypeid + + + + SPI_gettypeid + return the data type OID of the specified column + + + SPI_gettypeid + + + +Oid SPI_gettypeid(TupleDesc rowdesc, int colnumber) + + + + + Description + + + SPI_gettypeid returns the + OID of the data type of the specified column. + + + + + Arguments + + + + TupleDesc rowdesc + + + input row description + + + + + + int colnumber + + + column number (count starts at 1) + + + + + + + + Return Value + + + The OID of the data type of the specified column + or InvalidOid on error. On error, + SPI_result is set to + SPI_ERROR_NOATTRIBUTE. + + + + + + + + + SPI_getrelname + + + + SPI_getrelname + return the name of the specified relation + + + SPI_getrelname + + + +char * SPI_getrelname(Relation rel) + + + + + Description + + + SPI_getrelname returns the name of the + specified relation. (You can use pfree to + release the copy of the name when you don't need it anymore.) + + + + + Arguments + + + + Relation rel + + + input relation + + + + + + + + Return Value + + + The name of the specified relation. + + + + + + + + Memory Management + + + PostgreSQL allocates memory within + memory contextsmemory + context, which provide a convenient method of + managing allocations made in many different places that need to + live for differing amounts of time. Destroying a context releases + all the memory that was allocated in it. Thus, it is not necessary + to keep track of individual objects to avoid memory leaks; instead + only a relatively small number of contexts have to be managed. + palloc and related functions allocate memory + from the current context. + + + + SPI_connect creates a new memory context and + makes it current. SPI_finish restores the + previous current memory context and destroys the context created by + SPI_connect. These actions ensure that + transient memory allocations made inside your procedure are + reclaimed at procedure exit, avoiding memory leakage. + + + + However, if your procedure needs to return an object in allocated + memory (such as a value of a pass-by-reference data type), you + cannot allocate that memory using palloc, at + least not while you are connected to SPI. If you try, the object + will be deallocated by SPI_finish, and your + procedure will not work reliably. To solve this problem, use + SPI_palloc to allocate memory for your return + object. SPI_palloc allocates memory in the + upper executor context, that is, the memory context + that was current when SPI_connect was called, + which is precisely the right context for return a value from your + procedure. + + + + If SPI_palloc is called while the procedure is + not connected to SPI, then it acts the same as a normal + palloc. Before a procedure connects to the + SPI manager, the current memory context is the upper executor + context, so all allocations made by the procedure via + palloc or by SPI utility functions are made in + this context. + + + + When SPI_connect is called, the private + context of the procedure, which is created by + SPI_connect, is made the current context. All + allocations made by palloc, + repalloc, or SPI utility functions (except for + SPI_copytuple, + SPI_copytupledesc, + SPI_copytupleintoslot, + SPI_modifytuple, and + SPI_palloc) are made in this context. When a + procedure disconnects from the SPI manager (via + SPI_finish) the current context is restored to + the upper executor context, and all allocations made in the + procedure memory context are freed and cannot be used any more. + + + + All functions described in this section may be used by both + connected and unconnected procedures. In an unconnected procedure, + they act the same as the underlying ordinary server functions + (palloc, etc.). + + + + + + + SPI_palloc + + + + SPI_palloc + allocate memory in the upper executor context + + + SPI_palloc + + + +void * SPI_palloc(Size size) + + + + + Description + + + SPI_palloc allocates memory in the upper + executor context. + + + + + Arguments + + + + Size size + + + size in bytes of storage to allocate + + + + + + + + Return Value + + + pointer to new storage space of the specified size + + + + + + + + + SPI_repalloc + + + + SPI_repalloc + reallocate memory in the upper executor context + + + SPI_repalloc + + + +void * SPI_repalloc(void * pointer, Size size) + + + + + Description + + + SPI_repalloc changes the size of a memory + segment previously allocated using SPI_palloc. + + + + This function is no longer different from plain + repalloc. It's kept just for backward + compatibility of existing code. + + + + + Arguments + + + + void * pointer + + + pointer to existing storage to change + + + + + + Size size + + + size in bytes of storage to allocate + + + + + + + + Return Value + + + pointer to new storage space of specified size with the contents + copied from the existing area + + + + + + + + + SPI_pfree + + + + SPI_pfree + free memory in the upper executor context + + + SPI_pfree + + + +void SPI_pfree(void * pointer) + + + + + Description + + + SPI_pfree frees memory previously allocated + using SPI_palloc or + SPI_repalloc. + + + + This function is no longer different from plain + pfree. It's kept just for backward + compatibility of existing code. + + + + + Arguments + + + + void * pointer + + + pointer to existing storage to free + + + + + + + + + + + + SPI_copytuple + + + + SPI_copytuple + make a copy of a row in the upper executor context + + + SPI_copytuple + + + +HeapTuple SPI_copytuple(HeapTuple row) + + + + + Description + + + SPI_copytuple makes a copy of a row in the + upper executor context. + + + + + Arguments + + + + HeapTuple row + + + row to be copied + + + + + + + + Return Value + + + the copied row; NULL only if + tuple is NULL + + + + + + + + + SPI_copytupledesc + + + + SPI_copytupledesc + make a copy of a row descriptor in the upper executor context + + + SPI_copytupledesc + + + +TupleDesc SPI_copytupledesc(TupleDesc tupdesc) + + + + + Description + + + SPI_copytupledesc makes a copy of a row + descriptor in the upper executor context. + + + + + Arguments + + + + TupleDesc tupdesc + + + row descriptor to be copied + + + + + + + + Return Value + + + the copied row descriptor; NULL only if + tupdesc is NULL + + + + + + + + + SPI_copytupleintoslot + + + + SPI_copytupleintoslot + make a copy of a row and descriptor in the upper executor context + + + SPI_copytupleintoslot + + + +TupleTableSlot * SPI_copytupleintoslot(HeapTuple row, TupleDesc rowdesc) + + + + + Description + + + SPI_copytupleintoslot makes a copy of a row in + the upper executor context, returning it in the form of a filled-in + TupleTableSlot structure. + + + + + Arguments + + + + HeapTuple row + + + row to be copied + + + + + + TupleDesc rowdesc + + + row descriptor to be copied + + + + + + + + Return Value + + + TupleTableSlot containing the copied row and + descriptor; NULL only if + row or rowdesc are + NULL + + + + + + + + + SPI_modifytuple + + + + SPI_modifytuple + create a row by replacing selected fields of a given row + + + SPI_modifytuple + + + +HeapTuple SPI_modifytuple(Relation rel, HeapTuple row, ncols, colnum, Datum * values, const char * nulls) + + + + + Description + + + SPI_modifytuple creates a new row by + substituting new values for selected columns, copying the original + row's columns at other positions. The input row is not modified. + + + + + Arguments + + + + Relation rel + + + Used only as the source of the row descriptor for the row. + (Passing a relation rather than a row descriptor is a + misfeature.) + + + + + + HeapTuple row + + + row to be modified + + + + + + int ncols + + + number of column numbers in the array + colnum + + + + + + int * colnum + + + array of the numbers of the columns that are to be changed + (count starts at 1) + + + + + + Datum * values + + + new values for the specified columns + + + + + + const char * Nulls + + + which new values are null, if any (see SPI_execp for the format) + + + + + + + + Return Value + + + new row with modifications, allocated in the upper executor + context; NULL only if row + is NULL + + + + On error, SPI_result is set as follows: + + + 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. + + + + + + SPI_ERROR_NOATTRIBUTE + + + if colnum contains an invalid column number (less + than or equal to 0 or greater than the number of column in + row) + + + + + + + + + + + + + SPI_freetuple + + + + SPI_freetuple + frees a row allocated in the upper executor context + + + SPI_freetuple + + + +void SPI_freetuple(HeapTuple row) + + + + + Description + + + SPI_freetuple frees a row previously allocated + in the upper executor context. + + + + This function is no longer different from plain + heap_freetuple. It's kept just for backward + compatibility of existing code. + + + + + Arguments + + + + HeapTuple row + + + row to free + + + + + + + + + + + + SPI_freetuptable + + + + SPI_freetuptable + free a row set created by SPI_exec or a similar function + + + SPI_freetuptable + + + +void SPI_freetuptable(SPITupleTable * tuptable) + + + + + Description + + + SPI_freetuptable frees a row set created by a + prior SPI command execution function, such as + SPI_exec. Therefore, this function is usually called + with the global variable SPI_tupletable as + argument. + + + + This function is useful if a SPI procedure needs to execute + multiple commands and does not want to keep the results of earlier + commands around until it ends. Note that any unfreed row sets will + be freed anyway at SPI_finish. + + + + + Arguments + + + + SPITupleTable * tuptable + + + pointer to row set to free + + + + + + + + + + + + SPI_freeplan + + + + SPI_freeplan + free a previously saved plan + + + SPI_freeplan + + + +int SPI_freeplan(void *plan) + + + + + Description + + + SPI_freeplan releases a command execution plan + previously returned by SPI_prepare or saved by + SPI_saveplan. + + + + + Arguments + + + + void * plan + + + pointer to plan to free + + + + + + + + Return Value + + + SPI_ERROR_ARGUMENT if plan + is NULL. + + + + + + + + Visibility of Data Changes + + + The following two rules govern the visibility of data changes in + functions that use SPI (or any other C function): + + + + + During the execution of an SQL command, any data changes made by + the command (or by function called by the command, including + trigger functions) are invisible to the command. For + example, in command - INSERT INTO a SELECT * FROM a +INSERT INTO a SELECT * FROM a; - tuples inserted are invisible for SELECT's scan. In effect, this -duplicates the database table within itself (subject to unique index -rules, of course) without recursing. - + the inserted rows are invisible to the SELECT + part. + + - - Changes made by query Q are visible to queries that are started after -query Q, no matter whether they are started inside Q (during the execution -of Q) or after Q is done. - - + + + Changes made by a command C are visible to all commands that are + started after C, no matter whether they are started inside C + (during the execution of C) or after C is done. + + + + - -Examples + + The next section contains an example that illustrates the + application of these rules. + + - - This example of SPI usage demonstrates the visibility rule. - There are more complex examples in src/test/regress/regress.c and -in contrib/spi. - + + Examples - - This is a very simple example of SPI usage. The procedure execq accepts -an SQL-query in its first argument and tcount in its second, executes the -query using SPI_exec and returns the number of tuples for which the query -executed: + + This section contains a very simple example of SPI usage. The + procedure execq takes an SQL command as its + first argument and a row count as its second, executes the command + using SPI_exec and returns the number of rows + that were processed by the command. You can find more complex + examples for SPI in the source tree in + src/test/regress/regress.c and in + contrib/spi. + - -#include "executor/spi.h" /* this is what you need to work with SPI */ + +#include "executor/spi.h" int execq(text *sql, int cnt); int execq(text *sql, int cnt) { - char *query; + char *command; int ret; int proc; - /* Convert given TEXT object to a C string */ - query = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(sql))); + /* Convert given text object to a C string */ + command = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(sql))); SPI_connect(); - ret = SPI_exec(query, cnt); + ret = SPI_exec(command, cnt); proc = SPI_processed; /* - * If this is SELECT and some tuple(s) fetched - - * returns tuples to the caller via elog (INFO). + * If this is a SELECT and some rows were fetched, + * then the rows are printed via elog(INFO). */ - if ( ret == SPI_OK_SELECT && SPI_processed > 0 ) + if (ret == SPI_OK_SELECT && SPI_processed > 0) { TupleDesc tupdesc = SPI_tuptable->tupdesc; SPITupleTable *tuptable = SPI_tuptable; char buf[8192]; - int i,j; + int i, j; for (j = 0; j < proc; j++) { HeapTuple tuple = tuptable->vals[j]; for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++) - snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf)," %s%s", + snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s", SPI_getvalue(tuple, tupdesc, i), (i == tupdesc->natts) ? " " : " |"); elog (INFO, "EXECQ: %s", buf); @@ -3823,99 +2464,105 @@ execq(text *sql, int cnt) } SPI_finish(); - - pfree(query); + pfree(command); return (proc); } - - + - - Now, compile and create the function: + + (This function uses call convention version 0, to make the example + easier to understand. In real applications you should user the new + version 1 interface.) + - -CREATE FUNCTION execq (text, integer) RETURNS integer - AS '...path_to_so' + + This is how you declare the function after having compiled it into + a shared library: + + +CREATE FUNCTION execq(text, integer) RETURNS integer + AS 'filename' LANGUAGE C; - + + - -vac=> SELECT execq('CREATE TABLE a (x INTEGER)', 0); -execq ------ - 0 + + Here is a sample session: + + +=> SELECT execq('CREATE TABLE a (x integer)', 0); + execq +------- + 0 (1 row) -vac=> INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)',0)); +=> INSERT INTO a VALUES (execq('INSERT INTO a VALUES (0)', 0)); INSERT 167631 1 -vac=> SELECT execq('SELECT * FROM a',0); -INFO: EXECQ: 0 <<< inserted by execq +=> SELECT execq('SELECT * FROM a', 0); +INFO: EXECQ: 0 -- inserted by execq +INFO: EXECQ: 1 -- returned by execq and inserted by upper INSERT -INFO: EXECQ: 1 <<< value returned by execq and inserted by upper INSERT - -execq ------ - 2 + execq +------- + 2 (1 row) -vac=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a',1); -execq ------ - 1 +=> SELECT execq('INSERT INTO a SELECT x + 2 FROM a', 1); + execq +------- + 1 (1 row) -vac=> SELECT execq('SELECT * FROM a', 10); -INFO: EXECQ: 0 +=> SELECT execq('SELECT * FROM a', 10); +INFO: EXECQ: 0 +INFO: EXECQ: 1 +INFO: EXECQ: 2 -- 0 + 2, only one row inserted - as specified -INFO: EXECQ: 1 - -INFO: EXECQ: 2 <<< 0 + 2, only one tuple inserted - as specified - -execq ------ - 3 <<< 10 is max value only, 3 is real # of tuples + execq +------- + 3 -- 10 is the max value only, 3 is the real number of rows (1 row) -vac=> DELETE FROM a; +=> DELETE FROM a; DELETE 3 -vac=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); +=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); INSERT 167712 1 -vac=> SELECT * FROM a; -x -- -1 <<< no tuples in a (0) + 1 +=> SELECT * FROM a; + x +--- + 1 -- no rows in a (0) + 1 (1 row) -vac=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); -INFO: EXECQ: 0 +=> INSERT INTO a VALUES (execq('SELECT * FROM a', 0) + 1); +INFO: EXECQ: 0 INSERT 167713 1 -vac=> SELECT * FROM a; -x -- -1 -2 <<< there was single tuple in a + 1 +=> SELECT * FROM a; + x +--- + 1 + 2 -- there was one row in a + 1 (2 rows) --- This demonstrates data changes visibility rule: +-- This demonstrates the data changes visibility rule: -vac=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a; -INFO: EXECQ: 1 -INFO: EXECQ: 2 -INFO: EXECQ: 1 -INFO: EXECQ: 2 -INFO: EXECQ: 2 +=> INSERT INTO a SELECT execq('SELECT * FROM a', 0) * x FROM a; +INFO: EXECQ: 1 +INFO: EXECQ: 2 +INFO: EXECQ: 1 +INFO: EXECQ: 2 +INFO: EXECQ: 2 INSERT 0 2 -vac=> SELECT * FROM a; -x -- -1 -2 -2 <<< 2 tuples * 1 (x in first tuple) -6 <<< 3 tuples (2 + 1 just inserted) * 2 (x in second tuple) -(4 rows) ^^^^^^^^ - tuples visible to execq() in different invocations - - - - +=> SELECT * FROM a; + x +--- + 1 + 2 + 2 -- 2 rows * 1 (x in first row) + 6 -- 3 rows (2 + 1 just inserted) * 2 (x in second row) +(4 rows) ^^^^^^ + rows visible to execq() in different invocations + + + +