-
-
-Vadim
-Mikheev
-
-
-Transcribed 1998-01-16
-
-
-
Server Programming Interface
-
-The Server Programming Interface
-ability to run
SQL queries inside user-defined
-
-
-
-The available Procedural Languages (
PL) give an alternate
-means to build functions that can execute queries.
-
-
-
-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.
-
-
-To avoid misunderstanding we'll use function
-to mean
SPI interface functions and
-procedure for user-defined C-functions
-
-
-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
-
-
-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.
-
-
-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
-
-
-
-SPI_connect
-SPI - Connection Management
-
-
-SPI_connect
-
-
- Connects your procedure to the SPI manager.
-
-
-
-
-1997-12-24
-
-
+
+
Server Programming Interface
+
+
+
+
+ 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.
+
+
+ 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
+
+
+ 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.
+
+
+
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.
+
+
+ Source code files that use SPI must include the header file
+ executor/spi.h.
+
+
+
+ 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.
+
+
+
+
+
+
Interface Functions
+
+
+
+ SPI_connect
+
+
+
+ SPI_connect
+ connect a procedure to the SPI manager
+
+
+
+
+
int SPI_connect(void)
-
-
-
-
-1997-12-24
-
-
Inputs
-
-
-
-
-
-
-1997-12-24
-
-
Outputs
-
-
-
-int
-
-
-Return status
-
-
-SPI_OK_CONNECT
-
-
- if connected
-
-
-
-
-SPI_ERROR_CONNECT
-
-
- if not connected
-
-
-
-
-
-
-
-
-
-
-
-
-
-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_finish
-SPI - Connection Management
-
-
-SPI_finish
-
-
- Disconnects your procedure from the SPI manager.
-
-
-
-
-1997-12-24
-
-
-SPI_finish(void)
-
-
-
-
-1997-12-24
-
-
Inputs
-
-
-
-
-
-
-1997-12-24
-
-
Outputs
-
-
-
-int
-
-
-
-
-SPI_OK_FINISH
- if properly disconnected
-
-
-SPI_ERROR_UNCONNECTED
- if called from an un-connected procedure
-
-
-
-
-
-
-
-
-
-
-
-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.
-
-
-
-
-
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.
-
-
-
-
-
-
-
-
-
-
-
-SPI_exec
-SPI - Connection Management
-
-
-SPI_exec
-
-
- Creates an execution plan (parser+planner+optimizer) and executes a query.
-
-
-
-
-1997-12-24
-
-
-SPI_exec(query, tcount)
-
-
-
-
-1997-12-24
-
-
Inputs
-
-
-
-
-const char * query
-
-
-String containing query plan
-
-
-
-
-
-int tcount
-
-
-Maximum number of tuples to return
-
-
-
-
-
-
-
-
-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
-
-
-
-
-
-
-
-
-
-
-
-1997-12-24
-
-
Description
-
-SPI_exec creates an execution plan (parser+planner+optimizer)
- and executes the query for tcount tuples.
-
-
-
-
-
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,
-
-SPI_exec ("INSERT INTO tab SELECT * FROM tab", 5);
-
-
-will allow at most 5 tuples to be inserted into table.
-
- If execution of your query was successful then a non-negative value will be returned.
-
-
-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).
-
- If SPI_OK_SELECT is returned then you may use global
- pointer SPITupleTable *SPI_tuptable to access the result tuples.
-
-
- 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).
-
-
-
-
-
-
-
-
Structures
-
- If SPI_OK_SELECT is returned then you may use the global
- pointer SPITupleTable *SPI_tuptable to access the selected tuples.
-
-
- 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;
-
-
-
- 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.
-
-
-
- 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.
-
-
-
- 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.
-
-
-
-
-
-
-
-
-
-
-SPI_prepare
-SPI - Plan Preparation
-
-
-SPI_prepare
-
-
- Prepares a plan for a query, without executing it yet
-
-
-
-
-1997-12-24
-
-
-SPI_prepare(query, nargs, argtypes)
-
-
-
-
-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
-
-
-
-
-
-
-
-
-1997-12-24
-
-
Outputs
-
-
-
-void *
-
-
-Pointer to an execution plan (parser+planner+optimizer)
-
-
-
-
-
-
-
-
-
-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.
-
-
-
-
-
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.
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-SPI_execp
-SPI - Plan Execution
-
-
-SPI_execp
-
-
-Executes a plan from SPI_prepare
-
-
-
-
-1997-12-24
-
-
-SPI_execp(plan,
-values,
-nulls,
-tcount)
-
-
-
-
-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
-
-
-
-
-
-
-
-
-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
-
-
-
-
-
-
-
-
-
-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.
-
-
- 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_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.
+
-
-
-SPI_cursor_open
-SPI - Cursor Support
-
-
-SPI_cursor_open
-
-
-Sets up a cursor using a plan created with SPI_prepare
-
-
-
-
-2001-11-14
-
-
-SPI_cursor_open(name,
-plan,
-values,
-nulls)
-
-
-
-
-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)
-
-
-
-
-
-
-
-
-
-2001-11-14
-
-
Outputs
-
-
-
-Portal
-
-
- Pointer to Portal containing cursor, or NULL on error
-
-
-
-
-
-
-
-
-
-2001-11-14
-
-
Description
-
-SPI_cursor_open
- sets up a cursor (internally, a Portal) that will execute a plan
- prepared by SPI_prepare.
-
+ If your procedure is already connected,
+ 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_finish
+ disconnect a procedure from the SPI manager
+
+
+
+
+
+int SPI_finish(void)
+
+
+
+
+
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_exec
+ execute a command
+
+
+
+
+
+int SPI_exec(const char *
command, int
count)
+
+
+
+
+
Description
+
+ SPI_exec executes the specified SQL command
+
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+ 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_finish frees all
+ SPITupleTable>s allocated during the current
+ procedure. You can free a particular result table earlier, if you
+ are done with it, by calling SPI_freetuptable.
+
+
+
+
+
Arguments
+
+
+
+
+ string containing command to execute
+
+
+
+
+
+
+ maximum number of rows to process or return
+
+
+
+
+
+
+
+
Return Value
+
+ 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
+
+
+
+
+
+
+ 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_prepare
+ prepare a plan for a command, without executing it yet
+
+
+
+
+
+void * SPI_prepare(const char *
command, int
nargs, Oid *
argtypes)
+
+
+
+
+
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
+
+
+
+
+ command string
+
+
+
+
+
+
+ number of input parameters ($1>, $2>, etc.)
+
+
+
+
+
+
+ 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
+
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_execp
+ executes a plan prepared by SPI_prepare
+
+
+
+
+
+int SPI_execp(void *
plan, Datum *
values, const char *
nulls, int
count)
+
+
+
+
+
Description
+
+ SPI_execp executes a plan prepared by
+ has the same interpretation as in SPI_exec.
+
+
+
+
+
Arguments
+
+
+
+
+ execution plan (returned by SPI_prepare)
+
+
+
+
+
+
+ actual parameter values
+
+
+
+
+
+
+ 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).
+
+
+ SPI_execp assumes that no parameters are
+ null.
+
+
+
+
+
+
+ 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
+
+
+
+
+
+
+ SPI_ERROR_PARAM
+
+
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_open
+ set up a cursor using a plan created with 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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-1997-12-24
-
-
-SPI_gettypeid(tupdesc, fnumber)
-
-
-
-
-1997-12-24
-
-
Inputs
-
-
-
-
-TupleDesc tupdesc
-
-
-Input tuple description
-
-
-
-
-
-int fnumber
-
-
-Attribute number
-
-
-
-
-
-
-
-
-1997-12-24
-
-
Outputs
-
-
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
-
-
-
-
-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
+
+
+
+
+ name for portal, or NULL to let the system
+ select a name
+
+
+
+
+
+
+ execution plan (returned by SPI_prepare)
+
+
+
+
+
+
+ actual parameter values
+
+
+
+
+
+
+ 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
+ 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
+
+
+
+
+
+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
+
+
+
+
+ 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
+
+
+
+
+
+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 containing the cursor
+
+
+
+
+
+
+ true for fetch forward, false for fetch backward
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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 containing the cursor
+
+
+
+
+
+
+ true for move forward, false for move backward
+
+
+
+
+
+
+ maximum number of rows to move
+
+
+
+
+
+
+
+
+
+
+
+ SPI_cursor_close
+
+
+
+ SPI_cursor_close
+ close a cursor
+
+
+
+
+
+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 containing the cursor
+
+
+
+
+
+
+
+
+
+
+
+ SPI_saveplan
+
+
+
+ SPI_saveplan
+ save a plan
+
+
+
+
+
+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
+
+
+
+
+ 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
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ input row description
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ input row description
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ input row to be examined
+
+
+
+
+
+
+ input row description
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ input row to be examined
+
+
+
+
+
+
+ input row description
+
+
+
+
+
+
+ column number (count starts at 1)
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ input row description
+
+
+
+
+
+
+ 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
+
+
+
+
+
+Oid SPI_gettypeid(TupleDesc
rowdesc, int
colnumber)
+
+
+
+
+
Description
+
+ SPI_gettypeid returns the
+
OID of the data type of the specified column.
+
+
+
+
+
Arguments
+
+
+
+
+ input row description
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ input relation
+
+
+
+
+
+
+
+
Return Value
+
+ The name of the specified relation.
+
+
+
+
+
+
+
+
Memory Management
+
+
PostgreSQL allocates memory within
+ 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
+
+
+
+
+
+void * SPI_palloc(Size
size)
+
+
+
+
+
Description
+
+ SPI_palloc allocates memory in the upper
+ executor context.
+
+
+
+
+
Arguments
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ pointer to existing storage to change
+
+
+
+
+
+
+ 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
+
+
+
+
+
+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
+
+
+
+
+ pointer to existing storage to free
+
+
+
+
+
+
+
+
+
+
+
+ SPI_copytuple
+
+
+
+ SPI_copytuple
+ make a copy of a row in the upper executor context
+
+
+
+
+
+HeapTuple SPI_copytuple(HeapTuple
row)
+
+
+
+
+
Description
+
+ SPI_copytuple makes a copy of a row in the
+ upper executor context.
+
+
+
+
+
Arguments
+
+
+
+
+ row to be copied
+
+
+
+
+
+
+
+
Return Value
+
+ the copied row; NULL only if
+
+
+
+
+
+
+
+
+ SPI_copytupledesc
+
+
+
+ SPI_copytupledesc
+ make a copy of a row descriptor in the upper executor context
+
+
+
+
+
+TupleDesc SPI_copytupledesc(TupleDesc
tupdesc)
+
+
+
+
+
Description
+
+ SPI_copytupledesc makes a copy of a row
+ descriptor in the upper executor context.
+
+
+
+
+
Arguments
+
+
+
+
+ row descriptor to be copied
+
+
+
+
+
+
+
+
Return Value
+
+ the copied row descriptor; NULL only if
+
+
+
+
+
+
+
+
+ SPI_copytupleintoslot
+
+
+
+ SPI_copytupleintoslot
+ make a copy of a row and descriptor in the upper executor context
+
+
+
+
+
+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
+
+
+
+
+ row to be copied
+
+
+
+
+
+
+ row descriptor to be copied
+
+
+
+
+
+
+
+
Return Value
+
+ TupleTableSlot containing the copied row and
+ descriptor; NULL only if
+ NULL
+
+
+
+
+
+
+
+
+ SPI_modifytuple
+
+
+
+ SPI_modifytuple
+ create a row by replacing selected fields of a given row
+
+
+
+
+
+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
+
+
+
+
+ Used only as the source of the row descriptor for the row.
+ (Passing a relation rather than a row descriptor is a
+ misfeature.)
+
+
+
+
+
+
+ row to be modified
+
+
+
+
+
+
+ number of column numbers in the array
+
+
+
+
+
+
+ array of the numbers of the columns that are to be changed
+ (count starts at 1)
+
+
+
+
+
+
+ new values for the specified columns
+
+
+
+
+
+
+ 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
+
+
+
+
+
+
+
+
+
+
+
+
+ SPI_freetuple
+
+
+
+ SPI_freetuple
+ frees a row allocated in the upper executor context
+
+
+
+
+
+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
+
+
+
+
+ row to free
+
+
+
+
+
+
+
+
+
+
+
+ SPI_freetuptable
+
+
+
+ SPI_freetuptable
+ free a row set created by SPI_exec> or a similar function
+
+
+
+
+
+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
+
+
+
+
+
+int SPI_freeplan(void *
plan)
+
+
+
+
+
Description
+
+ SPI_freeplan releases a command execution plan
+ previously returned by SPI_prepare or saved by
+ SPI_saveplan.
+
+
+
+
+
Arguments
+
+
+
+
+ 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.
-
-
- 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.
-
-
-
-
-
Examples
-
- This example of SPI usage demonstrates the visibility rule.
- There are more complex examples in src/test/regress/regress.c and
-in contrib/spi.
-
-
- 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:
-
-#include "executor/spi.h" /* this is what you need to work with SPI */
+ the inserted rows are invisible to the SELECT
+ part.
+
+
+
+
+ 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.
+
+
+
+
+
+ The next section contains an example that illustrates the
+ application of these rules.
+
+
+
+
+
Examples
+
+ 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"
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);
}
SPI_finish();
-
- pfree(query);
+ pfree(command);
return (proc);
}
-
-
+
+
+ (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.)
+
- Now, compile and create the function:
+ This is how you declare the function after having compiled it into
+ a shared library:
-<ProgramListing>
-CREATE FUNCTION execq (text, integer) RETURNS integer
- AS '...path_to_so'
+<programlisting>
+CREATE FUNCTION execq(text, integer) RETURNS integer
+ AS 'filename'
LANGUAGE C;
-
+
+
+
+ Here is a sample session:
-<ProgramListing>
-vac=> SELECT execq('CREATE TABLE a (x INTEGER)', 0);
-execq
------
- 0
+<programlisting>
+=> 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
-
-INFO: EXECQ: 1 <<< value returned by execq and inserted by upper INSERT
+=> SELECT execq('SELECT * FROM a', 0);
+INFO: EXECQ: 0 -- inserted by execq
+INFO: EXECQ: 1 -- 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
-ProgramListing>
-ara>
-ect1>
-Chapter>
+=> 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
+programlisting>
+ ara>
+ ect1>
+chapter>