Re: [HACKERS] MOVE strangeness - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: [HACKERS] MOVE strangeness
Date
Msg-id 200212271403.gBRE3Ki04490@candle.pha.pa.us
Whole thread Raw
Responses Re: [HACKERS] MOVE strangeness
List pgsql-patches
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Sorry, I am not understanding.  If he does:
> > ...
> > here, isn't he sitting at the start of the fourth row, no?
>
> No.  He is sitting *on* the third row.  If he now does FETCH 1, he will
> advance to and return the fourth row; on the other hand, if he does
> FETCH -1, he will back up to and return the second row.
>
> The cursor must be considered to be positioned on its current row, not
> between rows, or the SQL-defined operations UPDATE WHERE CURRENT OF and
> DELETE WHERE CURRENT OF don't make any sense.  (We don't support those
> yet, but we should someday.)
>
> BTW, looking at Date and the SQL spec, I now realize that the recently
> made change to convert FETCH 0 into a no-op is wrong; per spec, FETCH
> RELATIVE 0 means "re-fetch the current row, if any".  By analogy, MOVE 0
> should probably return "MOVE 1" if you are on a real row, "MOVE 0" if
> you are not, corresponding to the number of rows you'd have gotten from
> FETCH 0.  Ugly, but ...

OK, patch attached.  The patch also makes the cursor offset a long from
the parser into the executor.  The tuple counter is already a long in
the executor.

    test=> CREATE TABLE test (x int);
    insert into testCREATE TABLE
    test=> INSERT INTO test VALUES (1);
    INSERT 149758 1
    test=> BEGIN;
    BEGIN
    test=> DECLARE  xx CURSOR FOR SELECT * FROM test;
    DECLARE CURSOR
    test=> MOVE 0 FROM xx;
    MOVE 0
    test=> FETCH 1 FROM xx;
     x
    ---
     1
    (1 row)

    test=> MOVE 0 FROM xx;
    MOVE 1
    test=> FETCH 0 FROM xx;
     x
    ---
     1
    (1 row)

    test=> FETCH 1 FROM xx;
     x
    ---
    (0 rows)

    test=> MOVE 0 FROM xx;
    MOVE 0

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/commands/portalcmds.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/commands/portalcmds.c,v
retrieving revision 1.6
diff -c -c -r1.6 portalcmds.c
*** src/backend/commands/portalcmds.c    15 Dec 2002 16:17:42 -0000    1.6
--- src/backend/commands/portalcmds.c    27 Dec 2002 13:52:37 -0000
***************
*** 65,71 ****
  void
  PerformPortalFetch(char *name,
                     bool forward,
!                    int count,
                     CommandDest dest,
                     char *completionTag)
  {
--- 65,71 ----
  void
  PerformPortalFetch(char *name,
                     bool forward,
!                    long count,
                     CommandDest dest,
                     char *completionTag)
  {
***************
*** 100,113 ****
          return;
      }

!     /* If zero count, we are done */
      if (count == 0)
!         return;

      /* Internally, zero count processes all portal rows */
!     if (count == INT_MAX)
          count = 0;
!
      /*
       * switch into the portal context
       */
--- 100,147 ----
          return;
      }

!     /* If zero count, handle specially */
      if (count == 0)
!     {
!         bool on_row = false;
!
!         /* Are we sitting on a row? */
!         oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
!         queryDesc = PortalGetQueryDesc(portal);
!         estate = queryDesc->estate;
!         if (portal->atStart == false && portal->atEnd == false)
!             on_row = true;
!         MemoryContextSwitchTo(oldcontext);
!
!         if (dest == None)
!         {
!             /* MOVE 0 returns 0/1 based on if FETCH 0 would return a row */
!             if (completionTag && on_row)
!                 strcpy(completionTag, "MOVE 1");
!             return;
!         }
!         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;
!         }
!     }

      /* Internally, zero count processes all portal rows */
!     if (count == LONG_MAX)
          count = 0;
!
      /*
       * switch into the portal context
       */
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/parser/gram.y,v
retrieving revision 2.388
diff -c -c -r2.388 gram.y
*** src/backend/parser/gram.y    12 Dec 2002 20:35:13 -0000    2.388
--- src/backend/parser/gram.y    27 Dec 2002 13:52:55 -0000
***************
*** 2731,2738 ****
  fetch_how_many:
              Iconst                                    { $$ = $1; }
              | '-' Iconst                            { $$ = - $2; }
!             | ALL                                    { $$ = INT_MAX; }
!             | LAST                                    { $$ = INT_MAX; }
              | NEXT                                    { $$ = 1; }
              | PRIOR                                    { $$ = -1; }
          ;
--- 2731,2738 ----
  fetch_how_many:
              Iconst                                    { $$ = $1; }
              | '-' Iconst                            { $$ = - $2; }
!             | ALL                                    { $$ = LONG_MAX; }
!             | LAST                                    { $$ = LONG_MAX; }
              | NEXT                                    { $$ = 1; }
              | PRIOR                                    { $$ = -1; }
          ;
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/utility.c,v
retrieving revision 1.185
diff -c -c -r1.185 utility.c
*** src/backend/tcop/utility.c    6 Dec 2002 05:00:31 -0000    1.185
--- src/backend/tcop/utility.c    27 Dec 2002 13:53:01 -0000
***************
*** 257,263 ****
                  FetchStmt  *stmt = (FetchStmt *) parsetree;
                  char       *portalName = stmt->portalname;
                  bool        forward;
!                 int            count;

                  forward = (bool) (stmt->direction == FORWARD);

--- 257,263 ----
                  FetchStmt  *stmt = (FetchStmt *) parsetree;
                  char       *portalName = stmt->portalname;
                  bool        forward;
!                 long        count;

                  forward = (bool) (stmt->direction == FORWARD);

Index: src/include/commands/portalcmds.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/commands/portalcmds.h,v
retrieving revision 1.3
diff -c -c -r1.3 portalcmds.h
*** src/include/commands/portalcmds.h    13 Nov 2002 00:44:09 -0000    1.3
--- src/include/commands/portalcmds.h    27 Dec 2002 13:53:05 -0000
***************
*** 25,31 ****
   *        BadArg if forward invalid.
   *        "ERROR" if portal not found.
   */
! extern void PerformPortalFetch(char *name, bool forward, int count,
                     CommandDest dest, char *completionTag);

  /*
--- 25,31 ----
   *        BadArg if forward invalid.
   *        "ERROR" if portal not found.
   */
! extern void PerformPortalFetch(char *name, bool forward, long count,
                     CommandDest dest, char *completionTag);

  /*
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/nodes/parsenodes.h,v
retrieving revision 1.223
diff -c -c -r1.223 parsenodes.h
*** src/include/nodes/parsenodes.h    12 Dec 2002 20:35:16 -0000    1.223
--- src/include/nodes/parsenodes.h    27 Dec 2002 13:53:11 -0000
***************
*** 1198,1204 ****
  {
      NodeTag        type;
      int            direction;        /* FORWARD or BACKWARD */
!     int            howMany;        /* amount to fetch */
      char       *portalname;        /* name of portal (cursor) */
      bool        ismove;            /* TRUE if MOVE */
  } FetchStmt;
--- 1198,1204 ----
  {
      NodeTag        type;
      int            direction;        /* FORWARD or BACKWARD */
!     long        howMany;        /* amount to fetch */
      char       *portalname;        /* name of portal (cursor) */
      bool        ismove;            /* TRUE if MOVE */
  } FetchStmt;

pgsql-patches by date:

Previous
From: Nic Ferrier
Date:
Subject: jdbc driver patch: refcursor types, cursor based querys.
Next
From: Bruce Momjian
Date:
Subject: Re: max_fsm_pages increased to 1000 by default