Support optional FROM/IN in FETCH and MOVE
authorAlvaro Herrera
Wed, 11 Nov 2009 19:25:42 +0000 (19:25 +0000)
committerAlvaro Herrera
Wed, 11 Nov 2009 19:25:42 +0000 (19:25 +0000)
The main motivation for this is that it's required for Informix compatibility
in ECPG.

This patch makes the ECPG and core grammars a bit closer to one another for
these productions.

Author: Zoltan Boszormenyi

src/backend/parser/gram.y
src/interfaces/ecpg/preproc/ecpg.addons
src/interfaces/ecpg/test/expected/compat_informix-test_informix.c
src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr

index 4325e4d0eda5467a3178567f18701b4668fe7c1a..38d9764b551ab60144e08529dc824951bb628dd6 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.690 2009/11/09 18:38:48 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.691 2009/11/11 19:25:40 alvherre Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -332,7 +332,7 @@ static TypeName *TableFuncTypeName(List *columns);
 %type    opt_column event cursor_options opt_hold opt_set_data
 %type     reindex_type drop_type comment_type
 
-%type    fetch_direction limit_clause select_limit_value
+%type    fetch_args limit_clause select_limit_value
                offset_clause select_offset_value
                select_offset_value2 opt_select_fetch_first_value
 %type    row_or_rows first_or_next
@@ -4180,142 +4180,144 @@ comment_text:
  *
  *****************************************************************************/
 
-FetchStmt: FETCH fetch_direction from_in name
+FetchStmt: FETCH fetch_args
                {
                    FetchStmt *n = (FetchStmt *) $2;
-                   n->portalname = $4;
-                   n->ismove = FALSE;
-                   $$ = (Node *)n;
-               }
-           | FETCH name
-               {
-                   FetchStmt *n = makeNode(FetchStmt);
-                   n->direction = FETCH_FORWARD;
-                   n->howMany = 1;
-                   n->portalname = $2;
                    n->ismove = FALSE;
                    $$ = (Node *)n;
                }
-           | MOVE fetch_direction from_in name
+           | MOVE fetch_args
                {
                    FetchStmt *n = (FetchStmt *) $2;
-                   n->portalname = $4;
                    n->ismove = TRUE;
                    $$ = (Node *)n;
                }
-           | MOVE name
+       ;
+
+fetch_args:    name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $1;
                    n->direction = FETCH_FORWARD;
                    n->howMany = 1;
-                   n->portalname = $2;
-                   n->ismove = TRUE;
                    $$ = (Node *)n;
                }
-       ;
-
-fetch_direction:
-           /*EMPTY*/
+           | from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $2;
                    n->direction = FETCH_FORWARD;
                    n->howMany = 1;
                    $$ = (Node *)n;
                }
-           | NEXT
+           | NEXT opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_FORWARD;
                    n->howMany = 1;
                    $$ = (Node *)n;
                }
-           | PRIOR
+           | PRIOR opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_BACKWARD;
                    n->howMany = 1;
                    $$ = (Node *)n;
                }
-           | FIRST_P
+           | FIRST_P opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_ABSOLUTE;
                    n->howMany = 1;
                    $$ = (Node *)n;
                }
-           | LAST_P
+           | LAST_P opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_ABSOLUTE;
                    n->howMany = -1;
                    $$ = (Node *)n;
                }
-           | ABSOLUTE_P SignedIconst
+           | ABSOLUTE_P SignedIconst opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $4;
                    n->direction = FETCH_ABSOLUTE;
                    n->howMany = $2;
                    $$ = (Node *)n;
                }
-           | RELATIVE_P SignedIconst
+           | RELATIVE_P SignedIconst opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $4;
                    n->direction = FETCH_RELATIVE;
                    n->howMany = $2;
                    $$ = (Node *)n;
                }
-           | SignedIconst
+           | SignedIconst opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_FORWARD;
                    n->howMany = $1;
                    $$ = (Node *)n;
                }
-           | ALL
+           | ALL opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_FORWARD;
                    n->howMany = FETCH_ALL;
                    $$ = (Node *)n;
                }
-           | FORWARD
+           | FORWARD opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_FORWARD;
                    n->howMany = 1;
                    $$ = (Node *)n;
                }
-           | FORWARD SignedIconst
+           | FORWARD SignedIconst opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $4;
                    n->direction = FETCH_FORWARD;
                    n->howMany = $2;
                    $$ = (Node *)n;
                }
-           | FORWARD ALL
+           | FORWARD ALL opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $4;
                    n->direction = FETCH_FORWARD;
                    n->howMany = FETCH_ALL;
                    $$ = (Node *)n;
                }
-           | BACKWARD
+           | BACKWARD opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $3;
                    n->direction = FETCH_BACKWARD;
                    n->howMany = 1;
                    $$ = (Node *)n;
                }
-           | BACKWARD SignedIconst
+           | BACKWARD SignedIconst opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $4;
                    n->direction = FETCH_BACKWARD;
                    n->howMany = $2;
                    $$ = (Node *)n;
                }
-           | BACKWARD ALL
+           | BACKWARD ALL opt_from_in name
                {
                    FetchStmt *n = makeNode(FetchStmt);
+                   n->portalname = $4;
                    n->direction = FETCH_BACKWARD;
                    n->howMany = FETCH_ALL;
                    $$ = (Node *)n;
@@ -4326,6 +4328,10 @@ from_in: FROM                                    {}
            | IN_P                                  {}
        ;
 
+opt_from_in:   from_in                             {}
+           | /* EMPTY */                           {}
+       ;
+
 
 /*****************************************************************************
  *
index 755061617002d8dc8e26c1b21fcf8bda13272099..9ef3d19100961024d3bb2d41c8fff3de679f10a6 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.6 2009/11/05 23:24:27 tgl Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.7 2009/11/11 19:25:40 alvherre Exp $ */
 
 ECPG: stmtClosePortalStmt block
    {
@@ -206,16 +206,38 @@ ECPG: ConstraintAttributeSpecConstraintTimeSpecConstraintDeferrabilitySpec addon
            if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
                mmerror(PARSE_ERROR, ET_ERROR, "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
 ECPG: var_valueNumericOnly addon
-ECPG: fetch_directionSignedIconst addon
        if ($1[0] == '$')
        {
            free($1);
            $1 = make_str("$0");
        }
-ECPG: fetch_directionABSOLUTE_PSignedIconst addon
-ECPG: fetch_directionRELATIVE_PSignedIconst addon
-ECPG: fetch_directionFORWARDSignedIconst addon
-ECPG: fetch_directionBACKWARDSignedIconst addon
+ECPG: fetch_argsname addon
+       add_additional_variables($1, false);
+ECPG: fetch_argsfrom_inname addon
+       add_additional_variables($2, false);
+ECPG: fetch_argsNEXTopt_from_inname addon
+ECPG: fetch_argsPRIORopt_from_inname addon
+ECPG: fetch_argsFIRST_Popt_from_inname addon
+ECPG: fetch_argsLAST_Popt_from_inname addon
+ECPG: fetch_argsALLopt_from_inname addon
+ECPG: fetch_argsFORWARDopt_from_inname addon
+ECPG: fetch_argsBACKWARDopt_from_inname addon
+       add_additional_variables($3, false);
+ECPG: fetch_argsSignedIconstopt_from_inname addon
+       add_additional_variables($3, false);
+       if ($1[0] == '$')
+       {
+           free($1);
+           $1 = make_str("$0");
+       }
+ECPG: fetch_argsFORWARDALLopt_from_inname addon
+ECPG: fetch_argsBACKWARDALLopt_from_inname addon
+       add_additional_variables($4, false);
+ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_inname addon
+ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_inname addon
+ECPG: fetch_argsFORWARDSignedIconstopt_from_inname addon
+ECPG: fetch_argsBACKWARDSignedIconstopt_from_inname addon
+       add_additional_variables($4, false);
        if ($2[0] == '$')
        {
            free($2);
@@ -336,47 +358,11 @@ ECPG: VariableShowStmtSHOWALL block
        mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
        $$ = EMPTY;
    }
-ECPG: FetchStmtFETCHfetch_directionfrom_inname block 
-   {
-       add_additional_variables($4, false);
-       $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
-   }
-ECPG: FetchStmtFETCHname block
+ECPG: FetchStmtMOVEfetch_args rule
+   | FETCH fetch_args ecpg_into
    {
-       add_additional_variables($2, false);
-       $$ = cat_str(2, make_str("fetch"), $2);
+       $$ = cat2_str(make_str("fetch"), $2);
    }
-ECPG: FetchStmtMOVEname rule
-   | FETCH fetch_direction from_in name ecpg_into
-       {
-           add_additional_variables($4, false);
-           $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
-       }
-   | FETCH fetch_direction name ecpg_into
-       {
-           add_additional_variables($3, false);
-           $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
-       }
-   | FETCH from_in name ecpg_into
-       {
-           add_additional_variables($3, false);
-           $$ = cat_str(3, make_str("fetch"), $2, $3);
-       }
-   | FETCH name ecpg_into
-       {
-           add_additional_variables($2, false);
-           $$ = cat2_str(make_str("fetch"), $2);
-       }
-   | FETCH fetch_direction name
-       {
-           add_additional_variables($3, false);
-           $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
-       }
-   | FETCH from_in name
-       {
-           add_additional_variables($3, false);
-           $$ = cat_str(3, make_str("fetch"), $2, $3);
-       }
 ECPG: select_limitLIMITselect_limit_value','select_offset_value block
         {
                 mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");
index 3d48a3a273b1503f7e7989834a035a14612576a5..0dc8c7f08add567e962d1efdf90d9f20fe4f5aaf 100644 (file)
@@ -158,7 +158,7 @@ if (sqlca.sqlcode < 0) dosqlprint ( );}
 
    while (1)
    {
-       { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch forward from c", ECPGt_EOIT, 
+       { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch forward c", ECPGt_EOIT, 
    ECPGt_int,&(i),(long)1,(long)1,sizeof(int), 
    ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
    ECPGt_decimal,&(j),(long)1,(long)1,sizeof(decimal), 
index 89e9483ffb96c6d20076c1cf51e45c3625fbb515..d678788640cd5eccee5773ab3d213325bea575f0 100644 (file)
@@ -63,7 +63,7 @@ DETAIL:  Key (i)=(7) already exists.
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_execute on line 95: OK: DECLARE CURSOR
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 57: query: fetch forward from c; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 57: query: fetch forward c; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_execute on line 57: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
@@ -75,7 +75,7 @@ DETAIL:  Key (i)=(7) already exists.
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_get_data on line 57: RESULT: test    offset: -1; array: yes
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 57: query: fetch forward from c; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 57: query: fetch forward c; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_execute on line 57: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000
@@ -87,7 +87,7 @@ DETAIL:  Key (i)=(7) already exists.
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_get_data on line 57: RESULT: a       offset: -1; array: yes
 [NO_PID]: sqlca: code: 0, state: 00000
-[NO_PID]: ecpg_execute on line 57: query: fetch forward from c; with 0 parameter(s) on connection regress1
+[NO_PID]: ecpg_execute on line 57: query: fetch forward c; with 0 parameter(s) on connection regress1
 [NO_PID]: sqlca: code: 0, state: 00000
 [NO_PID]: ecpg_execute on line 57: using PQexec
 [NO_PID]: sqlca: code: 0, state: 00000