From 061168d38f1e9e34234e2b6a3df582f98cbc1645 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 8 Jan 2003 00:22:27 +0000 Subject: [PATCH] Code review for FETCH/MOVE 0 changes. Improve documentation, do the right thing with the destination when FETCH 0 can't return a row, don't try to stuff LONG_MAX into an int value. --- doc/src/sgml/ref/fetch.sgml | 66 +++++++++++++++++------ doc/src/sgml/ref/move.sgml | 18 +++---- doc/src/sgml/release.sgml | 3 +- src/backend/commands/portalcmds.c | 88 +++++++++++++++++-------------- src/backend/parser/gram.y | 12 ++--- 5 files changed, 113 insertions(+), 74 deletions(-) diff --git a/doc/src/sgml/ref/fetch.sgml b/doc/src/sgml/ref/fetch.sgml index b08ad4a191..b67b7ef3c7 100644 --- a/doc/src/sgml/ref/fetch.sgml +++ b/doc/src/sgml/ref/fetch.sgml @@ -1,5 +1,5 @@ @@ -22,7 +22,7 @@ PostgreSQL documentation FETCH [ direction ] [ count ] { IN | FROM } cursor -FETCH [ FORWARD | BACKWARD | RELATIVE ] [ # | ALL | NEXT | PRIOR ] +FETCH [ FORWARD | BACKWARD | RELATIVE ] [ # | ALL | LAST | NEXT | PRIOR ] { IN | FROM } cursor @@ -40,7 +40,7 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ #direction - selector + direction defines the fetch direction. It can be one of the following: @@ -50,7 +50,7 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ # fetch next row(s). This is the default - if selector is omitted. + if direction is omitted. @@ -87,9 +87,9 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ ## - A signed integer that specifies how many rows to fetch. + A signed integer constant that specifies how many rows to fetch. Note that a negative integer is equivalent to changing the sense of - FORWARD and BACKWARD. Zero re-fetches the current row. + FORWARD and BACKWARD. Zero re-fetches the current row, if any. @@ -105,6 +105,17 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ # + + + LAST + + + + Same as ALL, but conforms to SQL92 syntax. + + + + NEXT @@ -151,7 +162,8 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ # - FETCH returns the results of the query defined by the specified cursor. + FETCH returns rows from the result of the query defined + by the specified cursor. The following messages will be returned if the query fails: @@ -200,10 +212,33 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE If the number of rows remaining in the cursor is less than #, then only those available are fetched. - Substituting the keyword ALL in place of a number will + Substituting the keyword ALL or LAST in place of a number will cause all remaining rows in the cursor to be retrieved. - Instances may be fetched in both FORWARD and BACKWARD + Rows may be fetched in both FORWARD and BACKWARD directions. The default direction is FORWARD. + + + + The cursor position can be before the first row of the query result, or on + any particular row of the result, or after the last row of the result. + When created, a cursor is positioned before the first row. After fetching + some rows, the cursor is positioned on the last row retrieved. A new + FETCH always steps one row in the specified direction + (if possible) before beginning to return rows. If the + FETCH requests more rows than available, the cursor is + left positioned after the last row of the query result (or before the first + row, in the case of a backward fetch). This will always be the case after + FETCH ALL. + + + + + A zero row count requests fetching the current row without moving the + cursor --- that is, re-fetching the most recently fetched row. + This will succeed unless the cursor is positioned before the + first row or after the last row; in which case, no row is returned. + + @@ -213,7 +248,6 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE FORWARD -1 is the same as BACKWARD 1. - @@ -224,11 +258,9 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE - Note that the FORWARD and BACKWARD keywords are + Note that the FORWARD, BACKWARD, and ALL keywords are PostgreSQL extensions. - The SQL92 syntax is also supported, specified - in the second form of the command. See below for details - on compatibility issues. + See below for details on compatibility issues. @@ -246,11 +278,11 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE + + is used to define a cursor. Use - to change cursor position. - - will define a cursor. + to change cursor position without retrieving data. Refer to , , diff --git a/doc/src/sgml/ref/move.sgml b/doc/src/sgml/ref/move.sgml index 5d4f1c8309..5b6f2671af 100644 --- a/doc/src/sgml/ref/move.sgml +++ b/doc/src/sgml/ref/move.sgml @@ -1,5 +1,5 @@ @@ -13,7 +13,7 @@ PostgreSQL documentation MOVE - position a cursor on a specified row of a table + reposition a cursor @@ -21,9 +21,7 @@ PostgreSQL documentation 1999-07-20 -MOVE [ direction ] - {count | LAST } - { IN | FROM } cursor +MOVE [ direction ] [ count ] { IN | FROM } cursor @@ -35,12 +33,10 @@ MOVE [ direction ] Description - MOVE allows a user to move the cursor position a - specified number of rows. - MOVE works like the FETCH command, - but only positions the cursor and does not return rows. - LAST moves to the end - of the cursor. + MOVE allows the user to move the cursor position a + specified number of rows, or all the way to the end or start of the query. + MOVE works exactly like the FETCH + command, except it only repositions the cursor and does not return rows. Refer to diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index 2f3295cab8..55007a7d62 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -1,5 +1,5 @@ @@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without worries about funny characters. --> estate; - if (portal->atStart == false && portal->atEnd == false) - on_row = true; - MemoryContextSwitchTo(oldcontext); + on_row = (portal->atStart == false && portal->atEnd == false); if (dest == None) { @@ -122,26 +119,25 @@ PerformPortalFetch(char *name, } else { - /* If we are not on a row, FETCH 0 returns nothing */ - if (!on_row) - return; - - /* Since we are sitting on a row, return the row */ - /* Back up so we can reread the row */ - PerformPortalFetch(name, false /* backward */, 1, - None, /* throw away output */ - NULL /* do not modify the command tag */); - - /* Set up to fetch one row */ - count = 1; - forward = true; + /* + * If we are sitting on a row, back up one so we can re-fetch it. + * If we are not sitting on a row, we still have to start up and + * shut down the executor so that the destination is initialized + * and shut down correctly; so keep going. Further down in the + * routine, count == 0 means we will retrieve no row. + */ + if (on_row) + { + PerformPortalFetch(name, false /* backward */, 1L, + None, /* throw away output */ + NULL /* do not modify the command tag */); + /* Set up to fetch one row forward */ + count = 1; + forward = true; + } } } - /* Internally, zero count processes all portal rows */ - if (count == LONG_MAX) - count = 0; - /* * switch into the portal context */ @@ -185,31 +181,45 @@ PerformPortalFetch(char *name, */ if (forward) { - if (portal->atEnd) + if (portal->atEnd || count == 0) direction = NoMovementScanDirection; else direction = ForwardScanDirection; - ExecutorRun(queryDesc, direction, (long) count); + /* In the executor, zero count processes all portal rows */ + if (count == INT_MAX) + count = 0; - if (estate->es_processed > 0) - portal->atStart = false; /* OK to back up now */ - if (count <= 0 || (int) estate->es_processed < count) - portal->atEnd = true; /* we retrieved 'em all */ + ExecutorRun(queryDesc, direction, count); + + if (direction != NoMovementScanDirection) + { + if (estate->es_processed > 0) + portal->atStart = false; /* OK to back up now */ + if (count <= 0 || (long) estate->es_processed < count) + portal->atEnd = true; /* we retrieved 'em all */ + } } else { - if (portal->atStart) + if (portal->atStart || count == 0) direction = NoMovementScanDirection; else direction = BackwardScanDirection; - ExecutorRun(queryDesc, direction, (long) count); + /* In the executor, zero count processes all portal rows */ + if (count == INT_MAX) + count = 0; - if (estate->es_processed > 0) - portal->atEnd = false; /* OK to go forward now */ - if (count <= 0 || (int) estate->es_processed < count) - portal->atStart = true; /* we retrieved 'em all */ + ExecutorRun(queryDesc, direction, count); + + if (direction != NoMovementScanDirection) + { + if (estate->es_processed > 0) + portal->atEnd = false; /* OK to go forward now */ + if (count <= 0 || (long) estate->es_processed < count) + portal->atStart = true; /* we retrieved 'em all */ + } } /* Return command status if wanted */ diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 921099b792..1809d51546 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.390 2003/01/06 00:31:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.391 2003/01/08 00:22:27 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2594,7 +2594,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name if ($3 < 0) { $3 = -$3; - $2 = (($2 == FORWARD)? BACKWARD: FORWARD); + $2 = (($2 == FORWARD) ? BACKWARD : FORWARD); } n->direction = $2; n->howMany = $3; @@ -2652,7 +2652,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name if ($3 < 0) { $3 = -$3; - $2 = (($2 == FORWARD) ? BACKWARD: FORWARD); + $2 = (($2 == FORWARD) ? BACKWARD : FORWARD); } n->direction = $2; n->howMany = $3; @@ -2720,8 +2720,8 @@ direction: FORWARD { $$ = FORWARD; } fetch_how_many: Iconst { $$ = $1; } | '-' Iconst { $$ = - $2; } - | ALL { $$ = LONG_MAX; } - | LAST { $$ = LONG_MAX; } + | ALL { $$ = INT_MAX; } + | LAST { $$ = INT_MAX; } | NEXT { $$ = 1; } | PRIOR { $$ = -1; } ; @@ -7115,8 +7115,8 @@ unreserved_keyword: | INVOKER | ISOLATION | KEY - | LANGUAGE | LANCOMPILER + | LANGUAGE | LAST | LEVEL | LISTEN