From 4971d2a32209118ebbdc6611341b89901e340902 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 26 Jan 2018 12:25:44 -0500 Subject: [PATCH] Remove the obsolete WITH clause of CREATE FUNCTION. This clause was superseded by SQL-standard syntax back in 7.3. We've kept it around for backwards-compatibility purposes ever since; but 15 years seems like long enough for that, especially seeing that there are undocumented weirdnesses in how it interacts with the SQL-standard syntax for specifying the same options. Michael Paquier, per an observation by Daniel Gustafsson; some small cosmetic adjustments to nearby code by me. Discussion: https://postgr.es/m/20180115022748.GB1724@paquier.xyz --- doc/src/sgml/ref/create_function.sgml | 36 --------- src/backend/commands/functioncmds.c | 109 +++++++------------------- src/backend/nodes/copyfuncs.c | 5 +- src/backend/nodes/equalfuncs.c | 3 +- src/backend/parser/gram.y | 14 ++-- src/include/nodes/parsenodes.h | 3 +- 6 files changed, 38 insertions(+), 132 deletions(-) diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml index fd229d1193..c0adb8cf1e 100644 --- a/doc/src/sgml/ref/create_function.sgml +++ b/doc/src/sgml/ref/create_function.sgml @@ -37,7 +37,6 @@ CREATE [ OR REPLACE ] FUNCTION | AS 'definition' | AS 'obj_file', 'link_symbol' } ... - [ WITH ( attribute [, ...] ) ] @@ -560,41 +559,6 @@ CREATE [ OR REPLACE ] FUNCTION - - attribute - - - - The historical way to specify optional pieces of information - about the function. The following attributes can appear here: - - - - isStrict - - - Equivalent to STRICT or RETURNS NULL ON NULL INPUT. - - - - - - isCachable - - isCachable is an obsolete equivalent of - IMMUTABLE; it's still accepted for - backwards-compatibility reasons. - - - - - - - Attribute names are not case-sensitive. - - - - diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index df87dfeb54..a483714766 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -637,21 +637,21 @@ update_proconfig_value(ArrayType *a, List *set_items) * attributes. */ static void -compute_attributes_sql_style(ParseState *pstate, - bool is_procedure, - List *options, - List **as, - char **language, - Node **transform, - bool *windowfunc_p, - char *volatility_p, - bool *strict_p, - bool *security_definer, - bool *leakproof_p, - ArrayType **proconfig, - float4 *procost, - float4 *prorows, - char *parallel_p) +compute_function_attributes(ParseState *pstate, + bool is_procedure, + List *options, + List **as, + char **language, + Node **transform, + bool *windowfunc_p, + char *volatility_p, + bool *strict_p, + bool *security_definer, + bool *leakproof_p, + ArrayType **proconfig, + float4 *procost, + float4 *prorows, + char *parallel_p) { ListCell *option; DefElem *as_item = NULL; @@ -789,59 +789,6 @@ compute_attributes_sql_style(ParseState *pstate, } -/*------------- - * Interpret the parameters *parameters and return their contents via - * *isStrict_p and *volatility_p. - * - * These parameters supply optional information about a function. - * All have defaults if not specified. Parameters: - * - * * isStrict means the function should not be called when any NULL - * inputs are present; instead a NULL result value should be assumed. - * - * * volatility tells the optimizer whether the function's result can - * be assumed to be repeatable over multiple evaluations. - *------------ - */ -static void -compute_attributes_with_style(ParseState *pstate, bool is_procedure, List *parameters, bool *isStrict_p, char *volatility_p) -{ - ListCell *pl; - - foreach(pl, parameters) - { - DefElem *param = (DefElem *) lfirst(pl); - - if (pg_strcasecmp(param->defname, "isstrict") == 0) - { - if (is_procedure) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("invalid attribute in procedure definition"), - parser_errposition(pstate, param->location))); - *isStrict_p = defGetBoolean(param); - } - else if (pg_strcasecmp(param->defname, "iscachable") == 0) - { - /* obsolete spelling of isImmutable */ - if (is_procedure) - ereport(ERROR, - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("invalid attribute in procedure definition"), - parser_errposition(pstate, param->location))); - if (defGetBoolean(param)) - *volatility_p = PROVOLATILE_IMMUTABLE; - } - else - ereport(WARNING, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unrecognized function attribute \"%s\" ignored", - param->defname), - parser_errposition(pstate, param->location))); - } -} - - /* * For a dynamically linked C language object, the form of the clause is * @@ -909,7 +856,7 @@ interpret_AS_clause(Oid languageOid, const char *languageName, /* * CreateFunction - * Execute a CREATE FUNCTION utility statement. + * Execute a CREATE FUNCTION (or CREATE PROCEDURE) utility statement. */ ObjectAddress CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) @@ -957,7 +904,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) aclcheck_error(aclresult, OBJECT_SCHEMA, get_namespace_name(namespaceId)); - /* default attributes */ + /* Set default attributes */ isWindowFunc = false; isStrict = false; security = false; @@ -968,14 +915,14 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) prorows = -1; /* indicates not set */ parallel = PROPARALLEL_UNSAFE; - /* override attributes from explicit list */ - compute_attributes_sql_style(pstate, - stmt->is_procedure, - stmt->options, - &as_clause, &language, &transformDefElem, - &isWindowFunc, &volatility, - &isStrict, &security, &isLeakProof, - &proconfig, &procost, &prorows, ¶llel); + /* Extract non-default attributes from stmt->options list */ + compute_function_attributes(pstate, + stmt->is_procedure, + stmt->options, + &as_clause, &language, &transformDefElem, + &isWindowFunc, &volatility, + &isStrict, &security, &isLeakProof, + &proconfig, &procost, &prorows, ¶llel); /* Look up the language and validate permissions */ languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language)); @@ -1107,8 +1054,6 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) trftypes = NULL; } - compute_attributes_with_style(pstate, stmt->is_procedure, stmt->withClause, &isStrict, &volatility); - interpret_AS_clause(languageOid, language, funcname, as_clause, &prosrc_str, &probin_str); @@ -2269,7 +2214,7 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic) FuncExpr *fexpr; int nargs; int i; - AclResult aclresult; + AclResult aclresult; FmgrInfo flinfo; FunctionCallInfoData fcinfo; CallContext *callcontext; @@ -2329,7 +2274,7 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic) InitFunctionCallInfoData(fcinfo, &flinfo, nargs, fexpr->inputcollid, (Node *) callcontext, NULL); i = 0; - foreach (lc, fexpr->args) + foreach(lc, fexpr->args) { EState *estate; ExprState *exprstate; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index e5d2de5330..fd3001c493 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3217,7 +3217,7 @@ _copyClosePortalStmt(const ClosePortalStmt *from) static CallStmt * _copyCallStmt(const CallStmt *from) { - CallStmt *newnode = makeNode(CallStmt); + CallStmt *newnode = makeNode(CallStmt); COPY_NODE_FIELD(funccall); @@ -3422,13 +3422,12 @@ _copyCreateFunctionStmt(const CreateFunctionStmt *from) { CreateFunctionStmt *newnode = makeNode(CreateFunctionStmt); + COPY_SCALAR_FIELD(is_procedure); COPY_SCALAR_FIELD(replace); COPY_NODE_FIELD(funcname); COPY_NODE_FIELD(parameters); COPY_NODE_FIELD(returnType); - COPY_SCALAR_FIELD(is_procedure); COPY_NODE_FIELD(options); - COPY_NODE_FIELD(withClause); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 785dc54d37..7d2aa1a2d3 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1370,13 +1370,12 @@ _equalCreateStatsStmt(const CreateStatsStmt *a, const CreateStatsStmt *b) static bool _equalCreateFunctionStmt(const CreateFunctionStmt *a, const CreateFunctionStmt *b) { + COMPARE_SCALAR_FIELD(is_procedure); COMPARE_SCALAR_FIELD(replace); COMPARE_NODE_FIELD(funcname); COMPARE_NODE_FIELD(parameters); COMPARE_NODE_FIELD(returnType); - COMPARE_SCALAR_FIELD(is_procedure); COMPARE_NODE_FIELD(options); - COMPARE_NODE_FIELD(withClause); return true; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 459a227e57..5329432f25 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -7506,51 +7506,51 @@ opt_nulls_order: NULLS_LA FIRST_P { $$ = SORTBY_NULLS_FIRST; } CreateFunctionStmt: CREATE opt_or_replace FUNCTION func_name func_args_with_defaults - RETURNS func_return createfunc_opt_list opt_definition + RETURNS func_return createfunc_opt_list { CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + n->is_procedure = false; n->replace = $2; n->funcname = $4; n->parameters = $5; n->returnType = $7; n->options = $8; - n->withClause = $9; $$ = (Node *)n; } | CREATE opt_or_replace FUNCTION func_name func_args_with_defaults - RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list opt_definition + RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list { CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + n->is_procedure = false; n->replace = $2; n->funcname = $4; n->parameters = mergeTableFuncParameters($5, $9); n->returnType = TableFuncTypeName($9); n->returnType->location = @7; n->options = $11; - n->withClause = $12; $$ = (Node *)n; } | CREATE opt_or_replace FUNCTION func_name func_args_with_defaults - createfunc_opt_list opt_definition + createfunc_opt_list { CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + n->is_procedure = false; n->replace = $2; n->funcname = $4; n->parameters = $5; n->returnType = NULL; n->options = $6; - n->withClause = $7; $$ = (Node *)n; } | CREATE opt_or_replace PROCEDURE func_name func_args_with_defaults createfunc_opt_list { CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + n->is_procedure = true; n->replace = $2; n->funcname = $4; n->parameters = $5; n->returnType = NULL; - n->is_procedure = true; n->options = $6; $$ = (Node *)n; } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index bbacbe144c..76a73b2a37 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2735,13 +2735,12 @@ typedef struct CreateStatsStmt typedef struct CreateFunctionStmt { NodeTag type; + bool is_procedure; /* it's really CREATE PROCEDURE */ bool replace; /* T => replace if already exists */ List *funcname; /* qualified name of function to create */ List *parameters; /* a list of FunctionParameter */ TypeName *returnType; /* the return type */ - bool is_procedure; List *options; /* a list of DefElem */ - List *withClause; /* a list of DefElem */ } CreateFunctionStmt; typedef enum FunctionParameterMode -- 2.40.0