Commit 6261c750 authored by Tom Lane's avatar Tom Lane

Implement SQL92-compatible FIRST, LAST, ABSOLUTE n, RELATIVE n options

for FETCH and MOVE.
parent e4704001
This diff is collapsed.
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/move.sgml,v 1.19 2003/03/10 03:53:49 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/move.sgml,v 1.20 2003/03/11 19:40:22 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -21,7 +21,7 @@ PostgreSQL documentation ...@@ -21,7 +21,7 @@ PostgreSQL documentation
<date>1999-07-20</date> <date>1999-07-20</date>
</refsynopsisdivinfo> </refsynopsisdivinfo>
<synopsis> <synopsis>
MOVE [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable class="PARAMETER">count</replaceable> ] { IN | FROM } <replaceable class="PARAMETER">cursor</replaceable> MOVE [ <replaceable class="PARAMETER">direction</replaceable> { FROM | IN } ] <replaceable class="PARAMETER">cursor</replaceable>
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -33,9 +33,7 @@ MOVE [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable c ...@@ -33,9 +33,7 @@ MOVE [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable c
Description Description
</title> </title>
<para> <para>
<command>MOVE</command> allows the user to move the cursor position a <command>MOVE</command> repositions a cursor without retrieving any data.
specified number of rows, or to the beginning or end of the cursor.
<command>MOVE ALL</command> moves to the end of the cursor.
<command>MOVE</command> works exactly like the <command>FETCH</command> <command>MOVE</command> works exactly like the <command>FETCH</command>
command, except it only repositions the cursor and does not return rows. command, except it only repositions the cursor and does not return rows.
</para> </para>
...@@ -54,8 +52,9 @@ MOVE [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable c ...@@ -54,8 +52,9 @@ MOVE [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable c
</title> </title>
<para> <para>
<command>MOVE</command> is a <productname>PostgreSQL</productname> The count returned in <command>MOVE</command>'s status string is the
language extension. count of the number of rows that would have been returned by the
equivalent <command>FETCH</command> command.
</para> </para>
<para> <para>
...@@ -119,9 +118,6 @@ COMMIT WORK; ...@@ -119,9 +118,6 @@ COMMIT WORK;
</title> </title>
<para> <para>
There is no <acronym>SQL92</acronym> <command>MOVE</command> statement. There is no <acronym>SQL92</acronym> <command>MOVE</command> statement.
Instead, <acronym>SQL92</acronym> allows
one to <command>FETCH</command> rows from an absolute cursor position,
implicitly moving the cursor to the correct position.
</para> </para>
</refsect2> </refsect2>
</refsect1> </refsect1>
......
This diff is collapsed.
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.201 2003/03/10 03:53:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.202 2003/03/11 19:40:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -287,6 +287,42 @@ ExecutorEnd(QueryDesc *queryDesc) ...@@ -287,6 +287,42 @@ ExecutorEnd(QueryDesc *queryDesc)
queryDesc->planstate = NULL; queryDesc->planstate = NULL;
} }
/* ----------------------------------------------------------------
* ExecutorRewind
*
* This routine may be called on an open queryDesc to rewind it
* to the start.
* ----------------------------------------------------------------
*/
void
ExecutorRewind(QueryDesc *queryDesc)
{
EState *estate;
MemoryContext oldcontext;
/* sanity checks */
Assert(queryDesc != NULL);
estate = queryDesc->estate;
Assert(estate != NULL);
/* It's probably not sensible to rescan updating queries */
Assert(queryDesc->operation == CMD_SELECT);
/*
* Switch into per-query memory context
*/
oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
/*
* rescan plan
*/
ExecReScan(queryDesc->planstate, NULL);
MemoryContextSwitchTo(oldcontext);
}
/* /*
* ExecCheckRTPerms * ExecCheckRTPerms
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.87 2003/03/10 03:53:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.88 2003/03/11 19:40:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1349,8 +1349,11 @@ _SPI_cursor_operation(Portal portal, bool forward, int count, ...@@ -1349,8 +1349,11 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
_SPI_current->tuptable = NULL; _SPI_current->tuptable = NULL;
/* Run the cursor */ /* Run the cursor */
_SPI_current->processed = DoPortalFetch(portal, forward, (long) count, _SPI_current->processed =
dest); DoPortalFetch(portal,
forward ? FETCH_FORWARD : FETCH_BACKWARD,
(long) count,
dest);
if (dest == SPI && _SPI_checktuples()) if (dest == SPI && _SPI_checktuples())
elog(FATAL, "SPI_fetch: # of processed tuples check failed"); elog(FATAL, "SPI_fetch: # of processed tuples check failed");
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.405 2003/03/10 03:53:50 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.406 2003/03/11 19:40:23 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -191,7 +191,7 @@ static void doNegateFloat(Value *v); ...@@ -191,7 +191,7 @@ static void doNegateFloat(Value *v);
%type <range> qualified_name OptConstrFromTable %type <range> qualified_name OptConstrFromTable
%type <str> opt_id all_Op MathOp opt_name SpecialRuleRelation %type <str> all_Op MathOp opt_name SpecialRuleRelation
%type <str> iso_level opt_encoding %type <str> iso_level opt_encoding
%type <node> grantee %type <node> grantee
...@@ -248,12 +248,10 @@ static void doNegateFloat(Value *v); ...@@ -248,12 +248,10 @@ static void doNegateFloat(Value *v);
%type <boolean> copy_from %type <boolean> copy_from
%type <ival> direction reindex_type drop_type %type <ival> reindex_type drop_type fetch_count
opt_column event comment_type cursor_options opt_column event comment_type cursor_options
%type <ival> fetch_how_many %type <node> fetch_direction select_limit_value select_offset_value
%type <node> select_limit_value select_offset_value
%type <list> OptSeqList %type <list> OptSeqList
%type <defelt> OptSeqElem %type <defelt> OptSeqElem
...@@ -345,7 +343,7 @@ static void doNegateFloat(Value *v); ...@@ -345,7 +343,7 @@ static void doNegateFloat(Value *v);
EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT
EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
FALSE_P FETCH FLOAT_P FOR FORCE FOREIGN FORWARD FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
FREEZE FROM FULL FUNCTION FREEZE FROM FULL FUNCTION
GLOBAL GRANT GROUP_P GLOBAL GRANT GROUP_P
...@@ -361,7 +359,7 @@ static void doNegateFloat(Value *v); ...@@ -361,7 +359,7 @@ static void doNegateFloat(Value *v);
KEY KEY
LANCOMPILER LANGUAGE LEADING LEFT LEVEL LIKE LIMIT LANCOMPILER LANGUAGE LAST_P LEADING LEFT LEVEL LIKE LIMIT
LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
LOCK_P LOCK_P
...@@ -1239,16 +1237,15 @@ opt_drop_behavior: ...@@ -1239,16 +1237,15 @@ opt_drop_behavior:
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY : * QUERY :
* close <optname> * close <portalname>
* *
*****************************************************************************/ *****************************************************************************/
ClosePortalStmt: ClosePortalStmt:
CLOSE opt_id CLOSE name
{ {
ClosePortalStmt *n = makeNode(ClosePortalStmt); ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = $2; n->portalname = $2;
...@@ -1256,10 +1253,6 @@ ClosePortalStmt: ...@@ -1256,10 +1253,6 @@ ClosePortalStmt:
} }
; ;
opt_id: ColId { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -2583,151 +2576,159 @@ comment_text: ...@@ -2583,151 +2576,159 @@ comment_text:
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
* fetch/move [forward | backward] [ # | all ] [ in <portalname> ] * fetch/move
* fetch [ forward | backward | absolute | relative ]
* [ # | all | next | prior ] [ [ in | from ] <portalname> ]
* *
*****************************************************************************/ *****************************************************************************/
FetchStmt: FETCH direction fetch_how_many from_in name FetchStmt: FETCH fetch_direction from_in name
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = (FetchStmt *) $2;
if ($3 < 0) n->portalname = $4;
{
$3 = -$3;
$2 = (($2 == FETCH_FORWARD) ? FETCH_BACKWARD : FETCH_FORWARD);
}
n->direction = $2;
n->howMany = $3;
n->portalname = $5;
n->ismove = FALSE; n->ismove = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| FETCH fetch_how_many from_in name | FETCH name
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
if ($2 < 0) n->direction = FETCH_FORWARD;
{ n->howMany = 1;
n->howMany = -$2; n->portalname = $2;
n->direction = FETCH_BACKWARD;
}
else
{
n->direction = FETCH_FORWARD;
n->howMany = $2;
}
n->portalname = $4;
n->ismove = FALSE; n->ismove = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| FETCH direction from_in name | MOVE fetch_direction from_in name
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = (FetchStmt *) $2;
n->direction = $2;
n->howMany = 1;
n->portalname = $4; n->portalname = $4;
n->ismove = FALSE; n->ismove = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| FETCH from_in name | MOVE name
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD; n->direction = FETCH_FORWARD;
n->howMany = 1; n->howMany = 1;
n->portalname = $3; n->portalname = $2;
n->ismove = FALSE; n->ismove = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| FETCH name ;
fetch_direction:
/*EMPTY*/
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD; n->direction = FETCH_FORWARD;
n->howMany = 1; n->howMany = 1;
n->portalname = $2;
n->ismove = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| MOVE direction fetch_how_many from_in name | NEXT
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
if ($3 < 0) n->direction = FETCH_FORWARD;
{ n->howMany = 1;
$3 = -$3;
$2 = (($2 == FETCH_FORWARD) ? FETCH_BACKWARD : FETCH_FORWARD);
}
n->direction = $2;
n->howMany = $3;
n->portalname = $5;
n->ismove = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| MOVE fetch_how_many from_in name | PRIOR
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
if ($2 < 0) n->direction = FETCH_BACKWARD;
{ n->howMany = 1;
n->howMany = -$2;
n->direction = FETCH_BACKWARD;
}
else
{
n->direction = FETCH_FORWARD;
n->howMany = $2;
}
n->portalname = $4;
n->ismove = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| MOVE direction from_in name | FIRST_P
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = $2; n->direction = FETCH_ABSOLUTE;
n->howMany = 1; n->howMany = 1;
n->portalname = $4;
n->ismove = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| MOVE from_in name | LAST_P
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_ABSOLUTE;
n->howMany = -1;
$$ = (Node *)n;
}
| ABSOLUTE fetch_count
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_ABSOLUTE;
n->howMany = $2;
$$ = (Node *)n;
}
| RELATIVE fetch_count
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_RELATIVE;
n->howMany = $2;
$$ = (Node *)n;
}
| fetch_count
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD;
n->howMany = $1;
$$ = (Node *)n;
}
| ALL
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
| FORWARD
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD; n->direction = FETCH_FORWARD;
n->howMany = 1; n->howMany = 1;
n->portalname = $3;
n->ismove = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| MOVE name | FORWARD fetch_count
{ {
FetchStmt *n = makeNode(FetchStmt); FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD; n->direction = FETCH_FORWARD;
n->howMany = $2;
$$ = (Node *)n;
}
| FORWARD ALL
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_FORWARD;
n->howMany = FETCH_ALL;
$$ = (Node *)n;
}
| BACKWARD
{
FetchStmt *n = makeNode(FetchStmt);
n->direction = FETCH_BACKWARD;
n->howMany = 1; n->howMany = 1;
n->portalname = $2;
n->ismove = TRUE;
$$ = (Node *)n; $$ = (Node *)n;
} }
; | BACKWARD fetch_count
{
direction: FORWARD { $$ = FETCH_FORWARD; } FetchStmt *n = makeNode(FetchStmt);
| BACKWARD { $$ = FETCH_BACKWARD; } n->direction = FETCH_BACKWARD;
| RELATIVE { $$ = FETCH_FORWARD; } n->howMany = $2;
| ABSOLUTE $$ = (Node *)n;
}
| BACKWARD ALL
{ {
elog(NOTICE, FetchStmt *n = makeNode(FetchStmt);
"FETCH / ABSOLUTE not supported, using RELATIVE"); n->direction = FETCH_BACKWARD;
$$ = FETCH_FORWARD; n->howMany = FETCH_ALL;
$$ = (Node *)n;
} }
; ;
fetch_how_many: fetch_count:
Iconst { $$ = $1; } Iconst { $$ = $1; }
| '-' Iconst { $$ = - $2; } | '-' Iconst { $$ = - $2; }
| ALL { $$ = INT_MAX; }
| NEXT { $$ = 1; }
| PRIOR { $$ = -1; }
; ;
from_in: IN_P {} from_in: FROM {}
| FROM {} | IN_P {}
; ;
...@@ -7093,6 +7094,7 @@ unreserved_keyword: ...@@ -7093,6 +7094,7 @@ unreserved_keyword:
| EXPLAIN | EXPLAIN
| EXTERNAL | EXTERNAL
| FETCH | FETCH
| FIRST_P
| FORCE | FORCE
| FORWARD | FORWARD
| FUNCTION | FUNCTION
...@@ -7115,6 +7117,7 @@ unreserved_keyword: ...@@ -7115,6 +7117,7 @@ unreserved_keyword:
| KEY | KEY
| LANCOMPILER | LANCOMPILER
| LANGUAGE | LANGUAGE
| LAST_P
| LEVEL | LEVEL
| LISTEN | LISTEN
| LOAD | LOAD
...@@ -7170,9 +7173,9 @@ unreserved_keyword: ...@@ -7170,9 +7173,9 @@ unreserved_keyword:
| SCROLL | SCROLL
| SECOND_P | SECOND_P
| SECURITY | SECURITY
| SESSION
| SEQUENCE | SEQUENCE
| SERIALIZABLE | SERIALIZABLE
| SESSION
| SET | SET
| SHARE | SHARE
| SHOW | SHOW
...@@ -7211,8 +7214,8 @@ unreserved_keyword: ...@@ -7211,8 +7214,8 @@ unreserved_keyword:
| VOLATILE | VOLATILE
| WITH | WITH
| WITHOUT | WITHOUT
| WRITE
| WORK | WORK
| WRITE
| YEAR_P | YEAR_P
| ZONE | ZONE
; ;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.134 2003/02/10 04:44:46 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.135 2003/03/11 19:40:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -128,6 +128,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -128,6 +128,7 @@ static const ScanKeyword ScanKeywords[] = {
{"extract", EXTRACT}, {"extract", EXTRACT},
{"false", FALSE_P}, {"false", FALSE_P},
{"fetch", FETCH}, {"fetch", FETCH},
{"first", FIRST_P},
{"float", FLOAT_P}, {"float", FLOAT_P},
{"for", FOR}, {"for", FOR},
{"force", FORCE}, {"force", FORCE},
...@@ -171,6 +172,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -171,6 +172,7 @@ static const ScanKeyword ScanKeywords[] = {
{"key", KEY}, {"key", KEY},
{"lancompiler", LANCOMPILER}, {"lancompiler", LANCOMPILER},
{"language", LANGUAGE}, {"language", LANGUAGE},
{"last", LAST_P},
{"leading", LEADING}, {"leading", LEADING},
{"left", LEFT}, {"left", LEFT},
{"level", LEVEL}, {"level", LEVEL},
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.194 2003/03/10 03:53:51 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.195 2003/03/11 19:40:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -321,15 +321,8 @@ ProcessUtility(Node *parsetree, ...@@ -321,15 +321,8 @@ ProcessUtility(Node *parsetree,
break; break;
case T_FetchStmt: case T_FetchStmt:
{ PerformPortalFetch((FetchStmt *) parsetree, dest,
FetchStmt *stmt = (FetchStmt *) parsetree; completionTag);
PerformPortalFetch(stmt->portalname,
stmt->direction == FETCH_FORWARD,
stmt->howMany,
(stmt->ismove) ? None : dest,
completionTag);
}
break; break;
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.52 2003/03/10 03:53:51 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.53 2003/03/11 19:40:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -167,10 +167,12 @@ PortalSetQuery(Portal portal, ...@@ -167,10 +167,12 @@ PortalSetQuery(Portal portal,
AssertArg(PortalIsValid(portal)); AssertArg(PortalIsValid(portal));
portal->queryDesc = queryDesc; portal->queryDesc = queryDesc;
portal->backwardOK = ExecSupportsBackwardScan(queryDesc->plantree);
portal->atStart = true; /* Allow fetch forward only, to start */
portal->atEnd = false;
portal->cleanup = cleanup; portal->cleanup = cleanup;
portal->backwardOK = ExecSupportsBackwardScan(queryDesc->plantree);
portal->atStart = true;
portal->atEnd = false; /* allow fetches */
portal->portalPos = 0;
portal->posOverflow = false;
} }
/* /*
...@@ -211,10 +213,12 @@ CreatePortal(const char *name) ...@@ -211,10 +213,12 @@ CreatePortal(const char *name)
/* initialize portal query */ /* initialize portal query */
portal->queryDesc = NULL; portal->queryDesc = NULL;
portal->backwardOK = false;
portal->atStart = true; /* disallow fetches until query is set */
portal->atEnd = true;
portal->cleanup = NULL; portal->cleanup = NULL;
portal->backwardOK = false;
portal->atStart = true;
portal->atEnd = true; /* disallow fetches until query is set */
portal->portalPos = 0;
portal->posOverflow = false;
/* put portal in table */ /* put portal in table */
PortalHashTableInsert(portal); PortalHashTableInsert(portal);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: portalcmds.h,v 1.5 2003/03/10 03:53:51 tgl Exp $ * $Id: portalcmds.h,v 1.6 2003/03/11 19:40:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -19,10 +19,12 @@ ...@@ -19,10 +19,12 @@
extern void PerformCursorOpen(DeclareCursorStmt *stmt, CommandDest dest); extern void PerformCursorOpen(DeclareCursorStmt *stmt, CommandDest dest);
extern void PerformPortalFetch(char *name, bool forward, long count, extern void PerformPortalFetch(FetchStmt *stmt, CommandDest dest,
CommandDest dest, char *completionTag); char *completionTag);
extern long DoPortalFetch(Portal portal, bool forward, long count, extern long DoPortalFetch(Portal portal,
FetchDirection fdirection,
long count,
CommandDest dest); CommandDest dest);
extern void PerformPortalClose(char *name); extern void PerformPortalClose(char *name);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: executor.h,v 1.90 2003/03/10 03:53:51 tgl Exp $ * $Id: executor.h,v 1.91 2003/03/11 19:40:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -86,6 +86,7 @@ extern void ExecutorStart(QueryDesc *queryDesc); ...@@ -86,6 +86,7 @@ extern void ExecutorStart(QueryDesc *queryDesc);
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction, long count); ScanDirection direction, long count);
extern void ExecutorEnd(QueryDesc *queryDesc); extern void ExecutorEnd(QueryDesc *queryDesc);
extern void ExecutorRewind(QueryDesc *queryDesc);
extern void ExecCheckRTPerms(List *rangeTable, CmdType operation); extern void ExecCheckRTPerms(List *rangeTable, CmdType operation);
extern void ExecEndPlan(PlanState *planstate, EState *estate); extern void ExecEndPlan(PlanState *planstate, EState *estate);
extern void ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo, extern void ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.232 2003/03/10 03:53:51 tgl Exp $ * $Id: parsenodes.h,v 1.233 2003/03/11 19:40:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1228,16 +1228,21 @@ typedef struct ClosePortalStmt ...@@ -1228,16 +1228,21 @@ typedef struct ClosePortalStmt
*/ */
typedef enum FetchDirection typedef enum FetchDirection
{ {
/* for these, howMany is how many rows to fetch; FETCH_ALL means ALL */
FETCH_FORWARD, FETCH_FORWARD,
FETCH_BACKWARD FETCH_BACKWARD,
/* ABSOLUTE someday? */ /* for these, howMany indicates a position; only one row is fetched */
FETCH_ABSOLUTE,
FETCH_RELATIVE
} FetchDirection; } FetchDirection;
#define FETCH_ALL LONG_MAX
typedef struct FetchStmt typedef struct FetchStmt
{ {
NodeTag type; NodeTag type;
FetchDirection direction; /* see above */ FetchDirection direction; /* see above */
long howMany; /* number of rows */ long howMany; /* number of rows, or position argument */
char *portalname; /* name of portal (cursor) */ char *portalname; /* name of portal (cursor) */
bool ismove; /* TRUE if MOVE */ bool ismove; /* TRUE if MOVE */
} FetchStmt; } FetchStmt;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: portal.h,v 1.38 2003/03/10 03:53:52 tgl Exp $ * $Id: portal.h,v 1.39 2003/03/11 19:40:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,10 +27,21 @@ typedef struct PortalData ...@@ -27,10 +27,21 @@ typedef struct PortalData
char *name; /* Portal's name */ char *name; /* Portal's name */
MemoryContext heap; /* subsidiary memory */ MemoryContext heap; /* subsidiary memory */
QueryDesc *queryDesc; /* Info about query associated with portal */ QueryDesc *queryDesc; /* Info about query associated with portal */
bool backwardOK; /* is fetch backwards allowed at all? */
bool atStart; /* T => fetch backwards is not allowed now */
bool atEnd; /* T => fetch forwards is not allowed now */
void (*cleanup) (Portal); /* Cleanup routine (optional) */ void (*cleanup) (Portal); /* Cleanup routine (optional) */
bool backwardOK; /* is fetch backwards allowed? */
/*
* atStart, atEnd and portalPos indicate the current cursor position.
* portalPos is zero before the first row, N after fetching N'th row of
* query. After we run off the end, portalPos = # of rows in query, and
* atEnd is true. If portalPos overflows, set posOverflow (this causes
* us to stop relying on its value for navigation). Note that atStart
* implies portalPos == 0, but not the reverse (portalPos could have
* overflowed).
*/
bool atStart;
bool atEnd;
bool posOverflow;
long portalPos;
} PortalData; } PortalData;
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment