diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 194 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 4 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 6 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 1 |
4 files changed, 153 insertions, 52 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 357ab93fb65..95e256883bb 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -490,7 +490,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <list> rowsfrom_item rowsfrom_list opt_col_def_list %type <boolean> opt_ordinality %type <list> ExclusionConstraintList ExclusionConstraintElem -%type <list> func_arg_list +%type <list> func_arg_list func_arg_list_opt %type <node> func_arg_expr %type <list> row explicit_row implicit_row type_list array_expr_list %type <node> case_expr case_arg when_clause case_default @@ -12969,6 +12969,7 @@ a_expr: c_expr { $$ = $1; } { $$ = (Node *) makeFuncCall(SystemFuncName("timezone"), list_make2($5, $1), + COERCE_SQL_SYNTAX, @2); } /* @@ -13032,6 +13033,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("like_escape"), list_make2($3, $5), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_LIKE, "~~", $1, (Node *) n, @2); @@ -13045,6 +13047,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("like_escape"), list_make2($4, $6), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_LIKE, "!~~", $1, (Node *) n, @2); @@ -13058,6 +13061,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("like_escape"), list_make2($3, $5), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_ILIKE, "~~*", $1, (Node *) n, @2); @@ -13071,6 +13075,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("like_escape"), list_make2($4, $6), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_ILIKE, "!~~*", $1, (Node *) n, @2); @@ -13080,6 +13085,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("similar_to_escape"), list_make1($4), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_SIMILAR, "~", $1, (Node *) n, @2); @@ -13088,6 +13094,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("similar_to_escape"), list_make2($4, $6), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_SIMILAR, "~", $1, (Node *) n, @2); @@ -13096,6 +13103,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("similar_to_escape"), list_make1($5), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_SIMILAR, "!~", $1, (Node *) n, @2); @@ -13104,6 +13112,7 @@ a_expr: c_expr { $$ = $1; } { FuncCall *n = makeFuncCall(SystemFuncName("similar_to_escape"), list_make2($5, $7), + COERCE_EXPLICIT_CALL, @2); $$ = (Node *) makeSimpleA_Expr(AEXPR_SIMILAR, "!~", $1, (Node *) n, @2); @@ -13164,6 +13173,7 @@ a_expr: c_expr { $$ = $1; } parser_errposition(@3))); $$ = (Node *) makeFuncCall(SystemFuncName("overlaps"), list_concat($1, $3), + COERCE_SQL_SYNTAX, @2); } | a_expr IS TRUE_P %prec IS @@ -13351,19 +13361,33 @@ a_expr: c_expr { $$ = $1; } } | a_expr IS NORMALIZED %prec IS { - $$ = (Node *) makeFuncCall(SystemFuncName("is_normalized"), list_make1($1), @2); + $$ = (Node *) makeFuncCall(SystemFuncName("is_normalized"), + list_make1($1), + COERCE_SQL_SYNTAX, + @2); } | a_expr IS unicode_normal_form NORMALIZED %prec IS { - $$ = (Node *) makeFuncCall(SystemFuncName("is_normalized"), list_make2($1, makeStringConst($3, @3)), @2); + $$ = (Node *) makeFuncCall(SystemFuncName("is_normalized"), + list_make2($1, makeStringConst($3, @3)), + COERCE_SQL_SYNTAX, + @2); } | a_expr IS NOT NORMALIZED %prec IS { - $$ = makeNotExpr((Node *) makeFuncCall(SystemFuncName("is_normalized"), list_make1($1), @2), @2); + $$ = makeNotExpr((Node *) makeFuncCall(SystemFuncName("is_normalized"), + list_make1($1), + COERCE_SQL_SYNTAX, + @2), + @2); } | a_expr IS NOT unicode_normal_form NORMALIZED %prec IS { - $$ = makeNotExpr((Node *) makeFuncCall(SystemFuncName("is_normalized"), list_make2($1, makeStringConst($4, @4)), @2), @2); + $$ = makeNotExpr((Node *) makeFuncCall(SystemFuncName("is_normalized"), + list_make2($1, makeStringConst($4, @4)), + COERCE_SQL_SYNTAX, + @2), + @2); } | DEFAULT { @@ -13613,31 +13637,41 @@ c_expr: columnref { $$ = $1; } func_application: func_name '(' ')' { - $$ = (Node *) makeFuncCall($1, NIL, @1); + $$ = (Node *) makeFuncCall($1, NIL, + COERCE_EXPLICIT_CALL, + @1); } | func_name '(' func_arg_list opt_sort_clause ')' { - FuncCall *n = makeFuncCall($1, $3, @1); + FuncCall *n = makeFuncCall($1, $3, + COERCE_EXPLICIT_CALL, + @1); n->agg_order = $4; $$ = (Node *)n; } | func_name '(' VARIADIC func_arg_expr opt_sort_clause ')' { - FuncCall *n = makeFuncCall($1, list_make1($4), @1); + FuncCall *n = makeFuncCall($1, list_make1($4), + COERCE_EXPLICIT_CALL, + @1); n->func_variadic = true; n->agg_order = $5; $$ = (Node *)n; } | func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')' { - FuncCall *n = makeFuncCall($1, lappend($3, $6), @1); + FuncCall *n = makeFuncCall($1, lappend($3, $6), + COERCE_EXPLICIT_CALL, + @1); n->func_variadic = true; n->agg_order = $7; $$ = (Node *)n; } | func_name '(' ALL func_arg_list opt_sort_clause ')' { - FuncCall *n = makeFuncCall($1, $4, @1); + FuncCall *n = makeFuncCall($1, $4, + COERCE_EXPLICIT_CALL, + @1); n->agg_order = $5; /* Ideally we'd mark the FuncCall node to indicate * "must be an aggregate", but there's no provision @@ -13647,7 +13681,9 @@ func_application: func_name '(' ')' } | func_name '(' DISTINCT func_arg_list opt_sort_clause ')' { - FuncCall *n = makeFuncCall($1, $4, @1); + FuncCall *n = makeFuncCall($1, $4, + COERCE_EXPLICIT_CALL, + @1); n->agg_order = $5; n->agg_distinct = true; $$ = (Node *)n; @@ -13664,7 +13700,9 @@ func_application: func_name '(' ')' * so that later processing can detect what the argument * really was. */ - FuncCall *n = makeFuncCall($1, NIL, @1); + FuncCall *n = makeFuncCall($1, NIL, + COERCE_EXPLICIT_CALL, + @1); n->agg_star = true; $$ = (Node *)n; } @@ -13738,6 +13776,7 @@ func_expr_common_subexpr: { $$ = (Node *) makeFuncCall(SystemFuncName("pg_collation_for"), list_make1($4), + COERCE_SQL_SYNTAX, @1); } | CURRENT_DATE @@ -13804,31 +13843,77 @@ func_expr_common_subexpr: { $$ = makeTypeCast($3, $5, @1); } | EXTRACT '(' extract_list ')' { - $$ = (Node *) makeFuncCall(SystemFuncName("date_part"), $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("date_part"), + $3, + COERCE_SQL_SYNTAX, + @1); } | NORMALIZE '(' a_expr ')' { - $$ = (Node *) makeFuncCall(SystemFuncName("normalize"), list_make1($3), @1); + $$ = (Node *) makeFuncCall(SystemFuncName("normalize"), + list_make1($3), + COERCE_SQL_SYNTAX, + @1); } | NORMALIZE '(' a_expr ',' unicode_normal_form ')' { - $$ = (Node *) makeFuncCall(SystemFuncName("normalize"), list_make2($3, makeStringConst($5, @5)), @1); + $$ = (Node *) makeFuncCall(SystemFuncName("normalize"), + list_make2($3, makeStringConst($5, @5)), + COERCE_SQL_SYNTAX, + @1); } | OVERLAY '(' overlay_list ')' { - $$ = (Node *) makeFuncCall(SystemFuncName("overlay"), $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("overlay"), + $3, + COERCE_SQL_SYNTAX, + @1); + } + | OVERLAY '(' func_arg_list_opt ')' + { + /* + * allow functions named overlay() to be called without + * special syntax + */ + $$ = (Node *) makeFuncCall(list_make1(makeString("overlay")), + $3, + COERCE_EXPLICIT_CALL, + @1); } | POSITION '(' position_list ')' { - /* position(A in B) is converted to position(B, A) */ - $$ = (Node *) makeFuncCall(SystemFuncName("position"), $3, @1); + /* + * position(A in B) is converted to position(B, A) + * + * We deliberately don't offer a "plain syntax" option + * for position(), because the reversal of the arguments + * creates too much risk of confusion. + */ + $$ = (Node *) makeFuncCall(SystemFuncName("position"), + $3, + COERCE_SQL_SYNTAX, + @1); } | SUBSTRING '(' substr_list ')' { /* substring(A from B for C) is converted to * substring(A, B, C) - thomas 2000-11-28 */ - $$ = (Node *) makeFuncCall(SystemFuncName("substring"), $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("substring"), + $3, + COERCE_SQL_SYNTAX, + @1); + } + | SUBSTRING '(' func_arg_list_opt ')' + { + /* + * allow functions named substring() to be called without + * special syntax + */ + $$ = (Node *) makeFuncCall(list_make1(makeString("substring")), + $3, + COERCE_EXPLICIT_CALL, + @1); } | TREAT '(' a_expr AS Typename ')' { @@ -13841,28 +13926,41 @@ func_expr_common_subexpr: * Convert SystemTypeName() to SystemFuncName() even though * at the moment they result in the same thing. */ - $$ = (Node *) makeFuncCall(SystemFuncName(((Value *)llast($5->names))->val.str), - list_make1($3), - @1); + $$ = (Node *) makeFuncCall(SystemFuncName(((Value *) llast($5->names))->val.str), + list_make1($3), + COERCE_EXPLICIT_CALL, + @1); } | TRIM '(' BOTH trim_list ')' { /* various trim expressions are defined in SQL * - thomas 1997-07-19 */ - $$ = (Node *) makeFuncCall(SystemFuncName("btrim"), $4, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("btrim"), + $4, + COERCE_SQL_SYNTAX, + @1); } | TRIM '(' LEADING trim_list ')' { - $$ = (Node *) makeFuncCall(SystemFuncName("ltrim"), $4, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("ltrim"), + $4, + COERCE_SQL_SYNTAX, + @1); } | TRIM '(' TRAILING trim_list ')' { - $$ = (Node *) makeFuncCall(SystemFuncName("rtrim"), $4, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("rtrim"), + $4, + COERCE_SQL_SYNTAX, + @1); } | TRIM '(' trim_list ')' { - $$ = (Node *) makeFuncCall(SystemFuncName("btrim"), $3, @1); + $$ = (Node *) makeFuncCall(SystemFuncName("btrim"), + $3, + COERCE_SQL_SYNTAX, + @1); } | NULLIF '(' a_expr ',' a_expr ')' { @@ -13915,7 +14013,10 @@ func_expr_common_subexpr: { /* xmlexists(A PASSING [BY REF] B [BY REF]) is * converted to xmlexists(A, B)*/ - $$ = (Node *) makeFuncCall(SystemFuncName("xmlexists"), list_make2($3, $4), @1); + $$ = (Node *) makeFuncCall(SystemFuncName("xmlexists"), + list_make2($3, $4), + COERCE_SQL_SYNTAX, + @1); } | XMLFOREST '(' xml_attribute_list ')' { @@ -14399,6 +14500,10 @@ func_arg_expr: a_expr } ; +func_arg_list_opt: func_arg_list { $$ = $1; } + | /*EMPTY*/ { $$ = NIL; } + ; + type_list: Typename { $$ = list_make1($1); } | type_list ',' Typename { $$ = lappend($1, $3); } ; @@ -14427,7 +14532,6 @@ extract_list: { $$ = list_make2(makeStringConst($1, @1), $3); } - | /*EMPTY*/ { $$ = NIL; } ; /* Allow delimited string Sconst in extract_arg as an SQL extension. @@ -14445,10 +14549,10 @@ extract_arg: ; unicode_normal_form: - NFC { $$ = "nfc"; } - | NFD { $$ = "nfd"; } - | NFKC { $$ = "nfkc"; } - | NFKD { $$ = "nfkd"; } + NFC { $$ = "NFC"; } + | NFD { $$ = "NFD"; } + | NFKC { $$ = "NFKC"; } + | NFKD { $$ = "NFKD"; } ; /* OVERLAY() arguments */ @@ -14468,29 +14572,24 @@ overlay_list: /* position_list uses b_expr not a_expr to avoid conflict with general IN */ position_list: b_expr IN_P b_expr { $$ = list_make2($3, $1); } - | /*EMPTY*/ { $$ = NIL; } ; /* * SUBSTRING() arguments * * Note that SQL:1999 has both - * * text FROM int FOR int - * * and - * * text FROM pattern FOR escape * * In the parser we map them both to a call to the substring() function and * rely on type resolution to pick the right one. * * In SQL:2003, the second variant was changed to - * * text SIMILAR pattern ESCAPE escape - * * We could in theory map that to a different function internally, but - * since we still support the SQL:1999 version, we don't. + * since we still support the SQL:1999 version, we don't. However, + * ruleutils.c will reverse-list the call in the newer style. */ substr_list: a_expr FROM a_expr FOR a_expr @@ -14504,6 +14603,13 @@ substr_list: } | a_expr FROM a_expr { + /* + * Because we aren't restricting data types here, this + * syntax can end up resolving to textregexsubstr(). + * We've historically allowed that to happen, so continue + * to accept it. However, ruleutils.c will reverse-list + * such a call in regular function call syntax. + */ $$ = list_make2($1, $3); } | a_expr FOR a_expr @@ -14527,16 +14633,6 @@ substr_list: { $$ = list_make3($1, $3, $5); } - /* - * We also want to support generic substring functions that - * accept the usual generic list of arguments. - */ - | expr_list - { - $$ = $1; - } - | /*EMPTY*/ - { $$ = NIL; } ; trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); } diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 7460e611604..ea4a1f5aeb9 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -541,10 +541,11 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) list_length(fc->args) > 1 && fc->agg_order == NIL && fc->agg_filter == NULL && + fc->over == NULL && !fc->agg_star && !fc->agg_distinct && !fc->func_variadic && - fc->over == NULL && + fc->funcformat == COERCE_EXPLICIT_CALL && coldeflist == NIL) { ListCell *lc; @@ -558,6 +559,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) newfc = makeFuncCall(SystemFuncName("unnest"), list_make1(arg), + COERCE_EXPLICIT_CALL, fc->location); newfexpr = transformExpr(pstate, (Node *) newfc, diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index a7a31704fb4..8b4e3ca5e11 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -91,11 +91,12 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, bool is_column = (fn == NULL); List *agg_order = (fn ? fn->agg_order : NIL); Expr *agg_filter = NULL; + WindowDef *over = (fn ? fn->over : NULL); bool agg_within_group = (fn ? fn->agg_within_group : false); bool agg_star = (fn ? fn->agg_star : false); bool agg_distinct = (fn ? fn->agg_distinct : false); bool func_variadic = (fn ? fn->func_variadic : false); - WindowDef *over = (fn ? fn->over : NULL); + CoercionForm funcformat = (fn ? fn->funcformat : COERCE_EXPLICIT_CALL); bool could_be_projection; Oid rettype; Oid funcid; @@ -221,6 +222,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, agg_order == NIL && agg_filter == NULL && !agg_star && !agg_distinct && over == NULL && !func_variadic && argnames == NIL && + funcformat == COERCE_EXPLICIT_CALL && list_length(funcname) == 1 && (actual_arg_types[0] == RECORDOID || ISCOMPLEX(actual_arg_types[0]))); @@ -742,7 +744,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, funcexpr->funcresulttype = rettype; funcexpr->funcretset = retset; funcexpr->funcvariadic = func_variadic; - funcexpr->funcformat = COERCE_EXPLICIT_CALL; + funcexpr->funcformat = funcformat; /* funccollid and inputcollid will be set by parse_collate.c */ funcexpr->args = fargs; funcexpr->location = location; diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 015b0538e33..254c0f65c2b 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -604,6 +604,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) castnode->location = -1; funccallnode = makeFuncCall(SystemFuncName("nextval"), list_make1(castnode), + COERCE_EXPLICIT_CALL, -1); constraint = makeNode(Constraint); constraint->contype = CONSTR_DEFAULT; |