From f9e2c7fae85c05c14d515fe06440b88f0054e837 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Fri, 16 Jul 1999 22:29:42 +0000 Subject: [PATCH] Allow bare column names to be subscripted as arrays. This 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 | 324 +++++++++----------------------------- 1 file changed, 75 insertions(+), 249 deletions(-) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 5e048a737fe..b4e089fb07a 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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 <str> join_outer %type <ival> join_type -%type <node> position_expr %type <list> extract_list, position_list %type <list> substr_list, substr_from, substr_for, trim_list %type <list> opt_interval @@ -232,10 +231,11 @@ Oid param_type(int t); /* used in parse_expr.c */ %type <ielem> index_elem, func_index %type <range> table_expr %type <relexp> relation_expr -%type <target> res_target_el, res_target_el2 +%type <target> target_el, update_target_el %type <paramno> ParamNo -%type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric +%type <typnam> Typename, opt_type, SimpleTypename, + Generic, Numeric, Character, Datetime %type <str> generic, numeric, character, datetime %type <str> extract_arg %type <str> 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; -- GitLab