aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/functioncmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r--src/backend/commands/functioncmds.c181
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