*** ./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);