*** ./doc/src/sgml/spi.sgml.orig 2007-01-14 12:37:19.000000000 +0100 --- ./doc/src/sgml/spi.sgml 2007-01-14 13:42:29.000000000 +0100 *************** *** 1344,1349 **** --- 1344,1481 ---- + + + SPI_cursor_open_with_options + + + + SPI_cursor_open_with_options + set up a cursor using a plan created with SPI_prepare + + + SPI_cursor_open_with_options + + + + Portal SPI_cursor_open_with_options(const char * name, void * plan, + Datum * values, const char * nulls, + bool read_only, int cursorOptions) + + + + + Description + + + SPI_cursor_open_with_options sets up a cursor (internally, + a portal) that will execute a plan prepared by + SPI_prepare. The parameters have the same + meanings as the corresponding parameters to + SPI_execute_plan. This function allows directly set cursor's + options. + + + + 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 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 + + + An array of actual parameter values. Must have same length as the + plan's number of arguments. + + + + + + const char * nulls + + + An array describing which parameters are null. Must have same length as + the plan's number of arguments. + 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. + + + + + + bool read_only + + + true for read-only execution + + + + + + int cursorOptions + + This option allow to set cursor's options. It's one or combination of + CURSOR_OPT_BINARY, + CURSOR_OPT_SCROLL, + CURSOR_OPT_NO_SCROLL, + CURSOR_OPT_INSENSITIVE, or + CURSOR_OPT_HOLD. + + + + + + + + + Return Value + + + pointer to portal containing the cursor, or NULL + on error + + + + + + SPI_cursor_find *************** *** 1472,1477 **** --- 1604,1685 ---- + + + SPI_scroll_cursor_fetch + + + + SPI_scroll_cursor_fetch + fetch some rows from a scrollable cursor + + + SPI_scroll_cursor_fetch + + + + void SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count) + + + + + Description + + + SPI_scroll_cursor_fetch fetches some rows from a + cursor. This is equivalent to the SQL command FETCH. + + + + + Arguments + + + + Portal portal + + + portal containing the cursor + + + + + + FetchDirection forward + + + It's one from FETCH_FORWARD, + FETCH_BACKWARD, + FETCH_ABSOLUTE or + FETCH_RELATIVE values. Please, look to SQL command FETCH. + + + + + + long count + + + maximum number of rows to fetch. + + + + + + + + Return Value + + + SPI_processed and + SPI_tuptable are set as in + SPI_execute if successful. + + + + + + SPI_cursor_move *************** *** 1517,1523 **** bool forward ! true for move forward, false for move backward --- 1725,1798 ---- bool forward ! true for fetch forward, false for fetch backward ! ! ! ! ! ! long count ! ! ! maximum number of rows to move ! ! ! ! ! ! ! ! ! ! ! ! SPI_scroll_cursor_move ! ! ! ! SPI_scroll_cursor_move ! move a scrollable cursor ! ! ! SPI_scroll_cursor_move ! ! ! ! void SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count) ! ! ! ! ! Description ! ! ! SPI_scroll_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 ! ! ! ! ! ! FetchDirection forward ! ! ! It's one from FETCH_FORWARD, ! FETCH_BACKWARD, ! FETCH_ABSOLUTE or ! FETCH_RELATIVE values. Please, look to SQL command FETCH. *** ./src/backend/executor/spi.c.orig 2007-01-14 09:54:37.000000000 +0100 --- ./src/backend/executor/spi.c 2007-01-14 10:13:21.000000000 +0100 *************** *** 45,51 **** static void _SPI_error_callback(void *arg); ! static void _SPI_cursor_operation(Portal portal, bool forward, long count, DestReceiver *dest); static _SPI_plan *_SPI_copy_plan(_SPI_plan *plan, int location); --- 45,55 ---- static void _SPI_error_callback(void *arg); ! static Portal _SPI_cursor_open(const char *name, void *plan, ! Datum *Values, const char *Nulls, ! bool read_only, int *cursorOptions); ! ! static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest); static _SPI_plan *_SPI_copy_plan(_SPI_plan *plan, int location); *************** *** 825,835 **** --- 829,865 ---- * * Open a prepared SPI plan as a portal */ + Portal SPI_cursor_open(const char *name, void *plan, Datum *Values, const char *Nulls, bool read_only) { + return _SPI_cursor_open(name, plan, Values, Nulls, read_only, NULL); + + } + + + /* + * SPI_cursor_open() + * + * Open a prepared SPI plan as a portal. Allow set cursor's options. + */ + + Portal + SPI_cursor_open_with_options(const char *name, void *plan, + Datum *Values, const char *Nulls, + bool read_only, int cursorOptions) + { + return _SPI_cursor_open(name, plan, Values, Nulls, read_only, &cursorOptions); + } + + + static Portal + _SPI_cursor_open(const char *name, void *plan, + Datum *Values, const char *Nulls, + bool read_only, int *cursorOptions) + { _SPI_plan *spiplan = (_SPI_plan *) plan; List *qtlist; List *ptlist; *************** *** 944,955 **** /* * Set up options for portal. */ ! portal->cursorOptions &= ~(CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL); ! if (list_length(ptlist) == 1 && ! ExecSupportsBackwardScan((Plan *) linitial(ptlist))) ! portal->cursorOptions |= CURSOR_OPT_SCROLL; else ! portal->cursorOptions |= CURSOR_OPT_NO_SCROLL; /* * Set up the snapshot to use. (PortalStart will do CopySnapshot, so we --- 974,992 ---- /* * Set up options for portal. */ ! ! if (!cursorOptions) ! { ! /* if cursorOption are NULL, allow SCROLL if backward scan is possible */ ! portal->cursorOptions &= ~(CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL); ! if (list_length(ptlist) == 1 && ! ExecSupportsBackwardScan((Plan *) linitial(ptlist))) ! portal->cursorOptions |= CURSOR_OPT_SCROLL; ! else ! portal->cursorOptions |= CURSOR_OPT_NO_SCROLL; ! } else ! portal->cursorOptions = *cursorOptions; /* * Set up the snapshot to use. (PortalStart will do CopySnapshot, so we *************** *** 988,993 **** --- 1025,1057 ---- /* + * SPI_scroll_cursor_fetch() + * + * Fetch rows in a scrollable cursor + */ + void + SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count) + { + _SPI_cursor_operation(portal, direction, count, + CreateDestReceiver(DestSPI, NULL)); + /* we know that the DestSPI receiver doesn't need a destroy call */ + } + + + /* + * SPI_scroll_cursor_move() + * + * Move in a scarollable cursor + */ + void + SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count) + { + _SPI_cursor_operation(portal, direction, count, None_Receiver); + } + + + + /* * SPI_cursor_fetch() * * Fetch rows in a cursor *************** *** 995,1001 **** void SPI_cursor_fetch(Portal portal, bool forward, long count) { ! _SPI_cursor_operation(portal, forward, count, CreateDestReceiver(DestSPI, NULL)); /* we know that the DestSPI receiver doesn't need a destroy call */ } --- 1059,1065 ---- void SPI_cursor_fetch(Portal portal, bool forward, long count) { ! _SPI_cursor_operation(portal, forward ? FETCH_FORWARD : FETCH_BACKWARD, count, CreateDestReceiver(DestSPI, NULL)); /* we know that the DestSPI receiver doesn't need a destroy call */ } *************** *** 1009,1015 **** void SPI_cursor_move(Portal portal, bool forward, long count) { ! _SPI_cursor_operation(portal, forward, count, None_Receiver); } --- 1073,1079 ---- void SPI_cursor_move(Portal portal, bool forward, long count) { ! _SPI_cursor_operation(portal, forward ? FETCH_FORWARD : FETCH_BACKWARD, count, None_Receiver); } *************** *** 1663,1669 **** * Do a FETCH or MOVE in a cursor */ static void ! _SPI_cursor_operation(Portal portal, bool forward, long count, DestReceiver *dest) { long nfetched; --- 1727,1733 ---- * Do a FETCH or MOVE in a cursor */ static void ! _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest) { long nfetched; *************** *** 1684,1690 **** /* Run the cursor */ nfetched = PortalRunFetch(portal, ! forward ? FETCH_FORWARD : FETCH_BACKWARD, count, dest); --- 1748,1754 ---- /* Run the cursor */ nfetched = PortalRunFetch(portal, ! direction, count, dest); *** ./src/include/executor/spi.h.orig 2007-01-14 09:24:00.000000000 +0100 --- ./src/include/executor/spi.h 2007-01-14 09:36:43.000000000 +0100 *************** *** 25,30 **** --- 25,31 ---- #include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "executor/executor.h" + #include "nodes/parsenodes.h" #include "nodes/execnodes.h" #include "nodes/params.h" #include "nodes/plannodes.h" *************** *** 125,133 **** --- 126,138 ---- extern Portal SPI_cursor_open(const char *name, void *plan, Datum *Values, const char *Nulls, bool read_only); + extern Portal SPI_cursor_open_with_options(const char *name, void *plan, + Datum *values, const char *Nulls, bool read_only, int cursorOptions); extern Portal SPI_cursor_find(const char *name); extern void SPI_cursor_fetch(Portal portal, bool forward, long count); extern void SPI_cursor_move(Portal portal, bool forward, long count); + extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count); + extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count); extern void SPI_cursor_close(Portal portal); extern void AtEOXact_SPI(bool isCommit);