diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml
index fd229d11937..c0adb8cf1e6 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 df87dfeb543..a483714766d 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 e5d2de53306..fd3001c4934 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 785dc54d375..7d2aa1a2d3a 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 459a227e576..5329432f25c 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 bbacbe144c8..76a73b2a377 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