diff options
author | Neil Conway <neilc@samurai.com> | 2005-03-14 00:19:37 +0000 |
---|---|---|
committer | Neil Conway <neilc@samurai.com> | 2005-03-14 00:19:37 +0000 |
commit | c06965544188244efa703f6a97f3088a291d57b5 (patch) | |
tree | 3bb6f3068d418b4ef98828db4f856e852c02df20 /src/backend/commands/functioncmds.c | |
parent | 41e2a80f570bf0e8e68d0eef7d1510e5ec32b3ae (diff) | |
download | postgresql-c06965544188244efa703f6a97f3088a291d57b5.tar.gz postgresql-c06965544188244efa703f6a97f3088a291d57b5.zip |
Allow ALTER FUNCTION to change a function's strictness, volatility, and
whether or not it is a security definer. Changing a function's strictness
is required by SQL2003, and the other capabilities make sense. Also, allow
an optional RESTRICT noise word to be specified, for SQL conformance.
Some trivial regression tests added and the documentation has been
updated.
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r-- | src/backend/commands/functioncmds.c | 181 |
1 files changed, 141 insertions, 40 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index e2afbce1029..cbe14d130be 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -3,14 +3,14 @@ * functioncmds.c * * Routines for CREATE and DROP FUNCTION commands and CREATE and DROP - * CAST commands. + * CAST commands. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.55 2005/03/13 05:19:26 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.56 2005/03/14 00:19:36 neilc Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -195,12 +195,75 @@ examine_parameter_list(List *parameter, Oid languageOid, return parameterCount; } +/* + * Recognize one of the options that can be passed to both CREATE + * FUNCTION and ALTER FUNCTION and return it via one of the out + * parameters. Returns true if the passed option was recognized. If + * the out parameter we were going to assign to points to non-NULL, + * raise a duplicate error. + */ +static bool +compute_common_attribute(DefElem *defel, + DefElem **volatility_item, + DefElem **strict_item, + DefElem **security_item) +{ + if (strcmp(defel->defname, "volatility") == 0) + { + if (*volatility_item) + goto duplicate_error; + + *volatility_item = defel; + } + else if (strcmp(defel->defname, "strict") == 0) + { + if (*strict_item) + goto duplicate_error; + + *strict_item = defel; + } + else if (strcmp(defel->defname, "security") == 0) + { + if (*security_item) + goto duplicate_error; + + *security_item = defel; + } + else + return false; + + /* Recognized an option */ + return true; + +duplicate_error: + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + return false; /* keep compiler quiet */ +} + +static char +interpret_func_volatility(DefElem *defel) +{ + char *str = strVal(defel->arg); + + if (strcmp(str, "immutable") == 0) + return PROVOLATILE_IMMUTABLE; + else if (strcmp(str, "stable") == 0) + return PROVOLATILE_STABLE; + else if (strcmp(str, "volatile") == 0) + return PROVOLATILE_VOLATILE; + else + { + elog(ERROR, "invalid volatility \"%s\"", str); + return 0; /* keep compiler quiet */ + } +} /* * Dissect the list of options assembled in gram.y into function * attributes. */ - static void compute_attributes_sql_style(List *options, List **as, @@ -236,29 +299,13 @@ compute_attributes_sql_style(List *options, errmsg("conflicting or redundant options"))); language_item = defel; } - else if (strcmp(defel->defname, "volatility") == 0) + else if (compute_common_attribute(defel, + &volatility_item, + &strict_item, + &security_item)) { - if (volatility_item) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting or redundant options"))); - volatility_item = defel; - } - else if (strcmp(defel->defname, "strict") == 0) - { - if (strict_item) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting or redundant options"))); - strict_item = defel; - } - else if (strcmp(defel->defname, "security") == 0) - { - if (security_item) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting or redundant options"))); - security_item = defel; + /* recognized common option */ + continue; } else elog(ERROR, "option \"%s\" not recognized", @@ -280,18 +327,7 @@ compute_attributes_sql_style(List *options, errmsg("no language specified"))); if (volatility_item) - { - if (strcmp(strVal(volatility_item->arg), "immutable") == 0) - *volatility_p = PROVOLATILE_IMMUTABLE; - else if (strcmp(strVal(volatility_item->arg), "stable") == 0) - *volatility_p = PROVOLATILE_STABLE; - else if (strcmp(strVal(volatility_item->arg), "volatile") == 0) - *volatility_p = PROVOLATILE_VOLATILE; - else - elog(ERROR, "invalid volatility \"%s\"", - strVal(volatility_item->arg)); - } - + *volatility_p = interpret_func_volatility(volatility_item); if (strict_item) *strict_p = intVal(strict_item->arg); if (security_item) @@ -301,7 +337,7 @@ compute_attributes_sql_style(List *options, /*------------- * Interpret the parameters *parameters and return their contents via - * out parameters *isStrict_p and *volatility_p. + * *isStrict_p and *volatility_p. * * These parameters supply optional information about a function. * All have defaults if not specified. Parameters: @@ -347,9 +383,7 @@ compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatili * In all other cases * * AS <object reference, or sql code> - * */ - static void interpret_AS_clause(Oid languageOid, const char *languageName, List *as, char **prosrc_str_p, char **probin_str_p) @@ -799,7 +833,74 @@ AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId) heap_close(rel, NoLock); } +/* + * Implements the ALTER FUNCTION utility command (except for the + * RENAME and OWNER clauses, which are handled as part of the generic + * ALTER framework). + */ +void +AlterFunction(AlterFunctionStmt *stmt) +{ + HeapTuple tup; + Oid funcOid; + Form_pg_proc procForm; + Relation rel; + ListCell *l; + DefElem *volatility_item = NULL; + DefElem *strict_item = NULL; + DefElem *security_def_item = NULL; + + rel = heap_openr(ProcedureRelationName, RowExclusiveLock); + + funcOid = LookupFuncNameTypeNames(stmt->func->funcname, + stmt->func->funcargs, + false); + + tup = SearchSysCacheCopy(PROCOID, + ObjectIdGetDatum(funcOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "cache lookup failed for function %u", funcOid); + + procForm = (Form_pg_proc) GETSTRUCT(tup); + /* Permission check: must own function */ + if (!pg_proc_ownercheck(funcOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, + NameListToString(stmt->func->funcname)); + + if (procForm->proisagg) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is an aggregate function", + NameListToString(stmt->func->funcname)))); + + /* Examine requested actions. */ + foreach (l, stmt->actions) + { + DefElem *defel = (DefElem *) lfirst(l); + + if (compute_common_attribute(defel, + &volatility_item, + &strict_item, + &security_def_item) == false) + elog(ERROR, "option \"%s\" not recognized", defel->defname); + } + + if (volatility_item) + procForm->provolatile = interpret_func_volatility(volatility_item); + if (strict_item) + procForm->proisstrict = intVal(strict_item->arg); + if (security_def_item) + procForm->prosecdef = intVal(security_def_item->arg); + + /* Do the update */ + simple_heap_update(rel, &tup->t_self, tup); + CatalogUpdateIndexes(rel, tup); + + heap_close(rel, NoLock); + heap_freetuple(tup); +} /* * SetFunctionReturnType - change declared return type of a function |