]> granicus.if.org Git - postgresql/commitdiff
Support optional FROM/IN in FETCH and MOVE
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 11 Nov 2009 19:25:42 +0000 (19:25 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
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 <ival>   opt_column event cursor_options opt_hold opt_set_data
 %type <objtype>        reindex_type drop_type comment_type
 
-%type <node>   fetch_direction limit_clause select_limit_value
+%type <node>   fetch_args limit_clause select_limit_value
                                offset_clause select_offset_value
                                select_offset_value2 opt_select_fetch_first_value
 %type <ival>   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