Allow bare column names to be subscripted as arrays. This
authorTom Lane
Fri, 16 Jul 1999 22:29:42 +0000 (22:29 +0000)
committerTom Lane
Fri, 16 Jul 1999 22:29:42 +0000 (22:29 +0000)
creates a reduce/reduce conflict, which I resolved by changing the
'AexprConst -> Typename Sconst' rule to 'AexprConst -> SimpleTypename Sconst'.
In other words, a subscripted type declaration can't be used in that
syntax any longer.  This seems a small price to pay for not having to
qualify subscripted columns anymore.
Other cleanups: rename res_target_list to update_target_list, and remove
productions for variants that are not legal in an UPDATE target list;
rename res_target_list2 to plain target_list; delete position_expr
in favor of using b_expr in that production; merge opt_indirection
into attr nonterminal, since there are no places where an unsubscripted
attr is wanted; fix typos in Param support; change case_arg so that
an arbitrary a_expr is allowed, not only a column name.

src/backend/parser/gram.y

index 5e048a737fe7792ad5d059bf6806e62f50a73b1b..b4e089fb07afe1f1b310f5c275e02baa207c48e4 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.91 1999/07/16 04:59:29 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.92 1999/07/16 22:29:42 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -169,8 +169,8 @@ Oid param_type(int t); /* used in parse_expr.c */
        oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti,
        opt_column_list, columnList, opt_va_list, va_list,
        sort_clause, sortby_list, index_params, index_list, name_list,
-       from_clause, from_expr, table_list, opt_array_bounds, nest_array_bounds,
-       expr_list, attrs, res_target_list, res_target_list2,
+       from_clause, from_expr, table_list, opt_array_bounds,
+       expr_list, attrs, target_list, update_target_list,
        def_list, opt_indirection, group_clause, TriggerFuncArgs,
        opt_select_limit
 
@@ -189,7 +189,6 @@ Oid param_type(int t); /* used in parse_expr.c */
 %type         join_outer
 %type    join_type
 
-%type    position_expr
 %type    extract_list, position_list
 %type    substr_list, substr_from, substr_for, trim_list
 %type    opt_interval
@@ -232,10 +231,11 @@ Oid   param_type(int t); /* used in parse_expr.c */
 %type   index_elem, func_index
 %type   table_expr
 %type  relation_expr
-%type  res_target_el, res_target_el2
+%type  target_el, update_target_el
 %type  ParamNo
 
-%type  Typename, opt_type, Array, Generic, Character, Datetime, Numeric
+%type  Typename, opt_type, SimpleTypename,
+               Generic, Numeric, Character, Datetime
 %type         generic, numeric, character, datetime
 %type         extract_arg
 %type         opt_charset, opt_collate
@@ -687,6 +687,10 @@ ClosePortalStmt:  CLOSE opt_id
                }
        ;
 
+opt_id:  ColId                                 { $$ = $1; }
+       | /*EMPTY*/                             { $$ = NULL; }
+       ;
+
 
 /*****************************************************************************
  *
@@ -2476,7 +2480,7 @@ InsertStmt:  INSERT INTO relation_name  insert_rest
                }
        ;
 
-insert_rest:  VALUES '(' res_target_list2 ')'
+insert_rest:  VALUES '(' target_list ')'
                {
                    $$ = makeNode(InsertStmt);
                    $$->cols = NULL;
@@ -2519,7 +2523,7 @@ insert_rest:  VALUES '(' res_target_list2 ')'
                    $$->intersectClause = n->intersectClause;
                    $$->forUpdate = n->forUpdate;
                }
-       | '(' columnList ')' VALUES '(' res_target_list2 ')'
+       | '(' columnList ')' VALUES '(' target_list ')'
                {
                    $$ = makeNode(InsertStmt);
                    $$->cols = $2;
@@ -2621,7 +2625,7 @@ opt_lmode:    SHARE               { $$ = TRUE; }
  *****************************************************************************/
 
 UpdateStmt:  UPDATE relation_name
-             SET res_target_list
+             SET update_target_list
              from_clause
              where_clause
                {
@@ -2804,7 +2808,7 @@ select_clause: '(' select_clause ')'
            }
        ; 
 
-SubSelect: SELECT opt_unique res_target_list2
+SubSelect: SELECT opt_unique target_list
             result from_clause where_clause
             group_clause having_clause
                {
@@ -3183,17 +3187,9 @@ relation_expr:   relation_name
                    $$->inh = TRUE;
                }
 
-opt_array_bounds:  '[' ']' nest_array_bounds
+opt_array_bounds:  '[' ']' opt_array_bounds
                {  $$ = lcons(makeInteger(-1), $3); }
-       | '[' Iconst ']' nest_array_bounds
-               {  $$ = lcons(makeInteger($2), $4); }
-       | /*EMPTY*/
-               {  $$ = NIL; }
-       ;
-
-nest_array_bounds: '[' ']' nest_array_bounds
-               {  $$ = lcons(makeInteger(-1), $3); }
-       | '[' Iconst ']' nest_array_bounds
+       | '[' Iconst ']' opt_array_bounds
                {  $$ = lcons(makeInteger($2), $4); }
        | /*EMPTY*/
                {  $$ = NIL; }
@@ -3210,7 +3206,7 @@ nest_array_bounds:    '[' ']' nest_array_bounds
  *
  *****************************************************************************/
 
-Typename:  Array opt_array_bounds
+Typename:  SimpleTypename opt_array_bounds
                {
                    $$ = $1;
                    $$->arrayBounds = $2;
@@ -3232,17 +3228,17 @@ Typename:  Array opt_array_bounds
                    else
                        $$->setof = FALSE;
                }
-       | SETOF Array
+       | SETOF SimpleTypename
                {
                    $$ = $2;
                    $$->setof = TRUE;
                }
        ;
 
-Array:  Generic
-       | Datetime
+SimpleTypename:  Generic
        | Numeric
        | Character
+       | Datetime
        ;
 
 Generic:  generic
@@ -3254,7 +3250,7 @@ Generic:  generic
        ;
 
 generic:  IDENT                                    { $$ = $1; }
-       | TYPE_P                                { $$ = xlateSqlType("type"); }
+       | TYPE_P                                { $$ = "type"; }
        ;
 
 /* SQL92 numeric data types
@@ -3615,21 +3611,18 @@ sub_type:  ANY                              { $$ = ANY_SUBLINK; }
  * All operations/expressions are allowed in a BETWEEN clause
  *  if surrounded by parens.
  */
-a_expr:  attr opt_indirection
-               {
-                   $1->indirection = $2;
-                   $$ = (Node *)$1;
-               }
+a_expr:  attr
+               {   $$ = (Node *) $1;  }
        | row_expr
                {   $$ = $1;  }
        | AexprConst
                {   $$ = $1;  }
-       | ColId
+       | ColId opt_indirection
                {
                    /* could be a column name or a relation_name */
                    Ident *n = makeNode(Ident);
                    n->name = $1;
-                   n->indirection = NULL;
+                   n->indirection = $2;
                    $$ = (Node *)n;
                }
        | '-' a_expr %prec UMINUS
@@ -3679,7 +3672,7 @@ a_expr:  attr opt_indirection
                    /* AexprConst can be either A_Const or ParamNo */
                    if (nodeTag($1) == T_A_Const) {
                        ((A_Const *)$1)->typename = $3;
-                   } else if (nodeTag($1) == T_Param) {
+                   } else if (nodeTag($1) == T_ParamNo) {
                        ((ParamNo *)$1)->typename = $3;
                    /* otherwise, try to transform to a function call */
                    } else {
@@ -3695,7 +3688,7 @@ a_expr:  attr opt_indirection
                    /* AexprConst can be either A_Const or ParamNo */
                    if (nodeTag($3) == T_A_Const) {
                        ((A_Const *)$3)->typename = $5;
-                   } else if (nodeTag($5) == T_Param) {
+                   } else if (nodeTag($3) == T_ParamNo) {
                        ((ParamNo *)$3)->typename = $5;
                    /* otherwise, try to transform to a function call */
                    } else {
@@ -4282,21 +4275,19 @@ a_expr:  attr opt_indirection
 /* Restricted expressions
  * b_expr is a subset of the complete expression syntax
  *  defined by a_expr. b_expr is used in BETWEEN clauses
- *  to eliminate parser ambiguities stemming from the AND keyword.
+ *  to eliminate parser ambiguities stemming from the AND keyword,
+ *  and also in POSITION clauses where the IN keyword gives trouble.
  */
-b_expr:  attr opt_indirection
-               {
-                   $1->indirection = $2;
-                   $$ = (Node *)$1;
-               }
+b_expr:  attr
+               {   $$ = (Node *) $1;  }
        | AexprConst
                {   $$ = $1;  }
-       | ColId
+       | ColId opt_indirection
                {
                    /* could be a column name or a relation_name */
                    Ident *n = makeNode(Ident);
                    n->name = $1;
-                   n->indirection = NULL;
+                   n->indirection = $2;
                    $$ = (Node *)n;
                }
        | '-' b_expr %prec UMINUS
@@ -4317,10 +4308,10 @@ b_expr:  attr opt_indirection
                {   $$ = makeA_Expr(OP, "/", $1, $3); }
        | b_expr '%' b_expr
                {   $$ = makeA_Expr(OP, "%", $1, $3); }
-       | b_expr '^' b_expr
-               {   $$ = makeA_Expr(OP, "^", $1, $3); }
        | b_expr '*' b_expr
                {   $$ = makeA_Expr(OP, "*", $1, $3); }
+       | b_expr '^' b_expr
+               {   $$ = makeA_Expr(OP, "^", $1, $3); }
        | ':' b_expr
                {   $$ = makeA_Expr(OP, ":", NULL, $2); }
        | ';' b_expr
@@ -4333,7 +4324,7 @@ b_expr:  attr opt_indirection
                    /* AexprConst can be either A_Const or ParamNo */
                    if (nodeTag($1) == T_A_Const) {
                        ((A_Const *)$1)->typename = $3;
-                   } else if (nodeTag($1) == T_Param) {
+                   } else if (nodeTag($1) == T_ParamNo) {
                        ((ParamNo *)$1)->typename = $3;
                    /* otherwise, try to transform to a function call */
                    } else {
@@ -4349,7 +4340,7 @@ b_expr:  attr opt_indirection
                    /* AexprConst can be either A_Const or ParamNo */
                    if (nodeTag($3) == T_A_Const) {
                        ((A_Const *)$3)->typename = $5;
-                   } else if (nodeTag($3) == T_Param) {
+                   } else if (nodeTag($3) == T_ParamNo) {
                        ((ParamNo *)$3)->typename = $5;
                    /* otherwise, try to transform to a function call */
                    } else {
@@ -4571,140 +4562,14 @@ extract_arg:  datetime                     { $$ = $1; }
        | TIMEZONE_MINUTE                   { $$ = "tz_minute"; }
        ;
 
-position_list:  position_expr IN position_expr
+/* position_list uses b_expr not a_expr to avoid conflict with general IN */
+
+position_list:  b_expr IN b_expr
                {   $$ = makeList($3, $1, -1); }
        | /*EMPTY*/
                {   $$ = NIL; }
        ;
 
-position_expr:  attr opt_indirection
-               {
-                   $1->indirection = $2;
-                   $$ = (Node *)$1;
-               }
-       | AexprConst
-               {   $$ = $1;  }
-       | '-' position_expr %prec UMINUS
-               {   $$ = makeA_Expr(OP, "-", NULL, $2); }
-       | position_expr '+' position_expr
-               {   $$ = makeA_Expr(OP, "+", $1, $3); }
-       | position_expr '-' position_expr
-               {   $$ = makeA_Expr(OP, "-", $1, $3); }
-       | position_expr '/' position_expr
-               {   $$ = makeA_Expr(OP, "/", $1, $3); }
-       | position_expr '%' position_expr
-               {   $$ = makeA_Expr(OP, "%", $1, $3); }
-       | position_expr '*' position_expr
-               {   $$ = makeA_Expr(OP, "*", $1, $3); }
-       | '|' position_expr
-               {   $$ = makeA_Expr(OP, "|", NULL, $2); }
-       | position_expr TYPECAST Typename
-               {
-                   $$ = (Node *)$1;
-                   /* AexprConst can be either A_Const or ParamNo */
-                   if (nodeTag($1) == T_A_Const) {
-                       ((A_Const *)$1)->typename = $3;
-                   } else if (nodeTag($1) == T_Param) {
-                       ((ParamNo *)$1)->typename = $3;
-                   /* otherwise, try to transform to a function call */
-                   } else {
-                       FuncCall *n = makeNode(FuncCall);
-                       n->funcname = $3->name;
-                       n->args = lcons($1,NIL);
-                       $$ = (Node *)n;
-                   }
-               }
-       | CAST '(' position_expr AS Typename ')'
-               {
-                   $$ = (Node *)$3;
-                   /* AexprConst can be either A_Const or ParamNo */
-                   if (nodeTag($3) == T_A_Const) {
-                       ((A_Const *)$3)->typename = $5;
-                   } else if (nodeTag($3) == T_Param) {
-                       ((ParamNo *)$3)->typename = $5;
-                   /* otherwise, try to transform to a function call */
-                   } else {
-                       FuncCall *n = makeNode(FuncCall);
-                       n->funcname = $5->name;
-                       n->args = lcons($3,NIL);
-                       $$ = (Node *)n;
-                   }
-               }
-       | '(' position_expr ')'
-               {   $$ = $2; }
-       | position_expr Op position_expr
-               {   $$ = makeA_Expr(OP, $2, $1, $3); }
-       | Op position_expr
-               {   $$ = makeA_Expr(OP, $1, NULL, $2); }
-       | position_expr Op
-               {   $$ = makeA_Expr(OP, $2, $1, NULL); }
-       | ColId
-               {
-                   /* could be a column name or a relation_name */
-                   Ident *n = makeNode(Ident);
-                   n->name = $1;
-                   n->indirection = NULL;
-                   $$ = (Node *)n;
-               }
-       | func_name '(' ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = $1;
-                   n->args = NIL;
-                   $$ = (Node *)n;
-               }
-       | func_name '(' expr_list ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = $1;
-                   n->args = $3;
-                   $$ = (Node *)n;
-               }
-       | POSITION '(' position_list ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = "strpos";
-                   n->args = $3;
-                   $$ = (Node *)n;
-               }
-       | SUBSTRING '(' substr_list ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = "substr";
-                   n->args = $3;
-                   $$ = (Node *)n;
-               }
-       /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
-       | TRIM '(' BOTH trim_list ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = "btrim";
-                   n->args = $4;
-                   $$ = (Node *)n;
-               }
-       | TRIM '(' LEADING trim_list ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = "ltrim";
-                   n->args = $4;
-                   $$ = (Node *)n;
-               }
-       | TRIM '(' TRAILING trim_list ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = "rtrim";
-                   n->args = $4;
-                   $$ = (Node *)n;
-               }
-       | TRIM '(' trim_list ')'
-               {
-                   FuncCall *n = makeNode(FuncCall);
-                   n->funcname = "btrim";
-                   n->args = $3;
-                   $$ = (Node *)n;
-               }
-       ;
-
 substr_list:  expr_list substr_from substr_for
                {
                    $$ = nconc(nconc($1,$2),$3);
@@ -4846,38 +4711,27 @@ case_default:  ELSE a_expr_or_null              { $$ = $2; }
        | /*EMPTY*/                             { $$ = NULL; }
        ;
 
-case_arg:  attr opt_indirection
-               {
-                   $1->indirection = $2;
-                   $$ = (Node *)$1;
-               }
-       | ColId
-               {
-                   /* could be a column name or a relation_name */
-                   Ident *n = makeNode(Ident);
-                   n->name = $1;
-                   n->indirection = NULL;
-                   $$ = (Node *)n;
-               }
+case_arg:  a_expr
+               {   $$ = $1; }
        | /*EMPTY*/
                {   $$ = NULL; }
        ;
 
-attr:  relation_name '.' attrs
+attr:  relation_name '.' attrs opt_indirection
                {
                    $$ = makeNode(Attr);
                    $$->relname = $1;
                    $$->paramNo = NULL;
                    $$->attrs = $3;
-                   $$->indirection = NULL;
+                   $$->indirection = $4;
                }
-       | ParamNo '.' attrs
+       | ParamNo '.' attrs opt_indirection
                {
                    $$ = makeNode(Attr);
                    $$->relname = NULL;
                    $$->paramNo = $1;
                    $$->attrs = $3;
-                   $$->indirection = NULL;
+                   $$->indirection = $4;
                }
        ;
 
@@ -4896,66 +4750,16 @@ attrs:    attr_name
  *
  *****************************************************************************/
 
-res_target_list:  res_target_list ',' res_target_el
-               {   $$ = lappend($1,$3);  }
-       | res_target_el
-               {   $$ = lcons($1, NIL);  }
-       | '*'
-               {
-                   ResTarget *rt = makeNode(ResTarget);
-                   Attr *att = makeNode(Attr);
-                   att->relname = "*";
-                   att->paramNo = NULL;
-                   att->attrs = NULL;
-                   att->indirection = NIL;
-                   rt->name = NULL;
-                   rt->indirection = NULL;
-                   rt->val = (Node *)att;
-                   $$ = lcons(rt, NIL);
-               }
-       ;
-
-res_target_el:  ColId opt_indirection '=' a_expr_or_null
-               {
-                   $$ = makeNode(ResTarget);
-                   $$->name = $1;
-                   $$->indirection = $2;
-                   $$->val = (Node *)$4;
-               }
-       | attr opt_indirection
-               {
-                   $$ = makeNode(ResTarget);
-                   $$->name = NULL;
-                   $$->indirection = $2;
-                   $$->val = (Node *)$1;
-               }
-       | relation_name '.' '*'
-               {
-                   Attr *att = makeNode(Attr);
-                   att->relname = $1;
-                   att->paramNo = NULL;
-                   att->attrs = lcons(makeString("*"), NIL);
-                   att->indirection = NIL;
-                   $$ = makeNode(ResTarget);
-                   $$->name = NULL;
-                   $$->indirection = NULL;
-                   $$->val = (Node *)att;
-               }
-       ;
+/* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */
 
-/*
-** target list for select.
-** should get rid of the other but is still needed by the defunct select into
-** and update (uses a subset)
-*/
-res_target_list2:  res_target_list2 ',' res_target_el2
+target_list:  target_list ',' target_el
                {   $$ = lappend($1, $3);  }
-       | res_target_el2
+       | target_el
                {   $$ = lcons($1, NIL);  }
        ;
 
 /* AS is not optional because shift/red conflict with unary ops */
-res_target_el2:  a_expr_or_null AS ColLabel
+target_el:  a_expr_or_null AS ColLabel
                {
                    $$ = makeNode(ResTarget);
                    $$->name = $3;
@@ -4995,10 +4799,29 @@ res_target_el2:  a_expr_or_null AS ColLabel
                }
        ;
 
-opt_id:  ColId                                 { $$ = $1; }
-       | /*EMPTY*/                             { $$ = NULL; }
+/* Target list as found in UPDATE table SET ... */
+
+update_target_list:  update_target_list ',' update_target_el
+               {   $$ = lappend($1,$3);  }
+       | update_target_el
+               {   $$ = lcons($1, NIL);  }
+       ;
+
+update_target_el:  ColId opt_indirection '=' a_expr_or_null
+               {
+                   $$ = makeNode(ResTarget);
+                   $$->name = $1;
+                   $$->indirection = $2;
+                   $$->val = (Node *)$4;
+               }
        ;
 
+/*****************************************************************************
+ *
+ * Names and constants
+ *
+ *****************************************************************************/
+
 relation_name: SpecialRuleRelation
                {
                    $$ = $1;
@@ -5056,7 +4879,10 @@ AexprConst:  Iconst
                    n->val.val.str = $1;
                    $$ = (Node *)n;
                }
-       | Typename Sconst
+       /* this rule formerly used Typename, but that causes reduce conflicts
+        * with subscripted column names ...
+        */
+       | SimpleTypename Sconst
                {
                    A_Const *n = makeNode(A_Const);
                    n->typename = $1;