1 /*-------------------------------------------------------------------------
5 * Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
8 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.87 2007/11/15 21:14:33 momjian Exp $
16 * These routines take the parse tree and pick out the
17 * appropriate arguments/flags, and pass the results to the
18 * corresponding "FooDefine" routines (in src/catalog) that do
19 * the actual catalog-munging. These routines also verify permission
20 * of the user to execute the command.
23 * These things must be defined and committed in the following order:
25 * input/output, recv/send procedures
31 *-------------------------------------------------------------------------
35 #include "access/genam.h"
36 #include "access/heapam.h"
37 #include "catalog/dependency.h"
38 #include "catalog/indexing.h"
39 #include "catalog/pg_aggregate.h"
40 #include "catalog/pg_cast.h"
41 #include "catalog/pg_language.h"
42 #include "catalog/pg_namespace.h"
43 #include "catalog/pg_proc.h"
44 #include "catalog/pg_type.h"
45 #include "commands/defrem.h"
46 #include "commands/proclang.h"
47 #include "miscadmin.h"
48 #include "parser/parse_func.h"
49 #include "parser/parse_type.h"
50 #include "utils/acl.h"
51 #include "utils/builtins.h"
52 #include "utils/fmgroids.h"
53 #include "utils/guc.h"
54 #include "utils/lsyscache.h"
55 #include "utils/syscache.h"
58 static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup,
63 * Examine the RETURNS clause of the CREATE FUNCTION statement
64 * and return information about it as *prorettype_p and *returnsSet.
66 * This is more complex than the average typename lookup because we want to
67 * allow a shell type to be used, or even created if the specified return type
68 * doesn't exist yet. (Without this, there's no way to define the I/O procs
69 * for a new type.) But SQL function creation won't cope, so error out if
70 * the target language is SQL. (We do this here, not in the SQL-function
71 * validator, so as not to produce a NOTICE and then an ERROR for the same
75 compute_return_type(TypeName *returnType, Oid languageOid,
76 Oid *prorettype_p, bool *returnsSet_p)
81 typtup = LookupTypeName(NULL, returnType, NULL);
85 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
87 if (languageOid == SQLlanguageId)
89 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
90 errmsg("SQL function cannot return shell type %s",
91 TypeNameToString(returnType))));
94 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
95 errmsg("return type %s is only a shell",
96 TypeNameToString(returnType))));
98 rettype = typeTypeId(typtup);
99 ReleaseSysCache(typtup);
103 char *typnam = TypeNameToString(returnType);
109 * Only C-coded functions can be I/O functions. We enforce this
110 * restriction here mainly to prevent littering the catalogs with
111 * shell types due to simple typos in user-defined function
114 if (languageOid != INTERNALlanguageId &&
115 languageOid != ClanguageId)
117 (errcode(ERRCODE_UNDEFINED_OBJECT),
118 errmsg("type \"%s\" does not exist", typnam)));
120 /* Reject if there's typmod decoration, too */
121 if (returnType->typmods != NIL)
123 (errcode(ERRCODE_SYNTAX_ERROR),
124 errmsg("type modifier cannot be specified for shell type \"%s\"",
127 /* Otherwise, go ahead and make a shell type */
129 (errcode(ERRCODE_UNDEFINED_OBJECT),
130 errmsg("type \"%s\" is not yet defined", typnam),
131 errdetail("Creating a shell type definition.")));
132 namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
134 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
136 if (aclresult != ACLCHECK_OK)
137 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
138 get_namespace_name(namespaceId));
139 rettype = TypeShellMake(typname, namespaceId);
140 Assert(OidIsValid(rettype));
143 *prorettype_p = rettype;
144 *returnsSet_p = returnType->setof;
148 * Interpret the parameter list of the CREATE FUNCTION statement.
150 * Results are stored into output parameters. parameterTypes must always
151 * be created, but the other arrays are set to NULL if not needed.
152 * requiredResultType is set to InvalidOid if there are no OUT parameters,
153 * else it is set to the OID of the implied result type.
156 examine_parameter_list(List *parameters, Oid languageOid,
157 oidvector **parameterTypes,
158 ArrayType **allParameterTypes,
159 ArrayType **parameterModes,
160 ArrayType **parameterNames,
161 Oid *requiredResultType)
163 int parameterCount = list_length(parameters);
170 bool have_names = false;
174 *requiredResultType = InvalidOid; /* default result */
176 inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
177 allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
178 paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
179 paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
181 /* Scan the list and extract data into work arrays */
183 foreach(x, parameters)
185 FunctionParameter *fp = (FunctionParameter *) lfirst(x);
186 TypeName *t = fp->argType;
190 typtup = LookupTypeName(NULL, t, NULL);
193 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
195 /* As above, hard error if language is SQL */
196 if (languageOid == SQLlanguageId)
198 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
199 errmsg("SQL function cannot accept shell type %s",
200 TypeNameToString(t))));
203 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
204 errmsg("argument type %s is only a shell",
205 TypeNameToString(t))));
207 toid = typeTypeId(typtup);
208 ReleaseSysCache(typtup);
213 (errcode(ERRCODE_UNDEFINED_OBJECT),
214 errmsg("type %s does not exist",
215 TypeNameToString(t))));
216 toid = InvalidOid; /* keep compiler quiet */
221 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
222 errmsg("functions cannot accept set arguments")));
224 if (fp->mode != FUNC_PARAM_OUT)
225 inTypes[inCount++] = toid;
227 if (fp->mode != FUNC_PARAM_IN)
229 if (outCount == 0) /* save first OUT param's type */
230 *requiredResultType = toid;
234 allTypes[i] = ObjectIdGetDatum(toid);
236 paramModes[i] = CharGetDatum(fp->mode);
238 if (fp->name && fp->name[0])
240 paramNames[i] = DirectFunctionCall1(textin,
241 CStringGetDatum(fp->name));
248 /* Now construct the proper outputs as needed */
249 *parameterTypes = buildoidvector(inTypes, inCount);
253 *allParameterTypes = construct_array(allTypes, parameterCount, OIDOID,
254 sizeof(Oid), true, 'i');
255 *parameterModes = construct_array(paramModes, parameterCount, CHAROID,
258 *requiredResultType = RECORDOID;
259 /* otherwise we set requiredResultType correctly above */
263 *allParameterTypes = NULL;
264 *parameterModes = NULL;
269 for (i = 0; i < parameterCount; i++)
271 if (paramNames[i] == PointerGetDatum(NULL))
272 paramNames[i] = DirectFunctionCall1(textin,
273 CStringGetDatum(""));
275 *parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
279 *parameterNames = NULL;
284 * Recognize one of the options that can be passed to both CREATE
285 * FUNCTION and ALTER FUNCTION and return it via one of the out
286 * parameters. Returns true if the passed option was recognized. If
287 * the out parameter we were going to assign to points to non-NULL,
288 * raise a duplicate-clause error. (We don't try to detect duplicate
289 * SET parameters though --- if you're redundant, the last one wins.)
292 compute_common_attribute(DefElem *defel,
293 DefElem **volatility_item,
294 DefElem **strict_item,
295 DefElem **security_item,
300 if (strcmp(defel->defname, "volatility") == 0)
302 if (*volatility_item)
303 goto duplicate_error;
305 *volatility_item = defel;
307 else if (strcmp(defel->defname, "strict") == 0)
310 goto duplicate_error;
312 *strict_item = defel;
314 else if (strcmp(defel->defname, "security") == 0)
317 goto duplicate_error;
319 *security_item = defel;
321 else if (strcmp(defel->defname, "set") == 0)
323 *set_items = lappend(*set_items, defel->arg);
325 else if (strcmp(defel->defname, "cost") == 0)
328 goto duplicate_error;
332 else if (strcmp(defel->defname, "rows") == 0)
335 goto duplicate_error;
342 /* Recognized an option */
347 (errcode(ERRCODE_SYNTAX_ERROR),
348 errmsg("conflicting or redundant options")));
349 return false; /* keep compiler quiet */
353 interpret_func_volatility(DefElem *defel)
355 char *str = strVal(defel->arg);
357 if (strcmp(str, "immutable") == 0)
358 return PROVOLATILE_IMMUTABLE;
359 else if (strcmp(str, "stable") == 0)
360 return PROVOLATILE_STABLE;
361 else if (strcmp(str, "volatile") == 0)
362 return PROVOLATILE_VOLATILE;
365 elog(ERROR, "invalid volatility \"%s\"", str);
366 return 0; /* keep compiler quiet */
371 * Update a proconfig value according to a list of VariableSetStmt items.
373 * The input and result may be NULL to signify a null entry.
376 update_proconfig_value(ArrayType *a, List *set_items)
380 foreach(l, set_items)
382 VariableSetStmt *sstmt = (VariableSetStmt *) lfirst(l);
384 Assert(IsA(sstmt, VariableSetStmt));
385 if (sstmt->kind == VAR_RESET_ALL)
389 char *valuestr = ExtractSetVariableArgs(sstmt);
392 a = GUCArrayAdd(a, sstmt->name, valuestr);
394 a = GUCArrayDelete(a, sstmt->name);
403 * Dissect the list of options assembled in gram.y into function
407 compute_attributes_sql_style(List *options,
412 bool *security_definer,
413 ArrayType **proconfig,
418 DefElem *as_item = NULL;
419 DefElem *language_item = NULL;
420 DefElem *volatility_item = NULL;
421 DefElem *strict_item = NULL;
422 DefElem *security_item = NULL;
423 List *set_items = NIL;
424 DefElem *cost_item = NULL;
425 DefElem *rows_item = NULL;
427 foreach(option, options)
429 DefElem *defel = (DefElem *) lfirst(option);
431 if (strcmp(defel->defname, "as") == 0)
435 (errcode(ERRCODE_SYNTAX_ERROR),
436 errmsg("conflicting or redundant options")));
439 else if (strcmp(defel->defname, "language") == 0)
443 (errcode(ERRCODE_SYNTAX_ERROR),
444 errmsg("conflicting or redundant options")));
445 language_item = defel;
447 else if (compute_common_attribute(defel,
455 /* recognized common option */
459 elog(ERROR, "option \"%s\" not recognized",
463 /* process required items */
465 *as = (List *) as_item->arg;
469 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
470 errmsg("no function body specified")));
471 *as = NIL; /* keep compiler quiet */
475 *language = strVal(language_item->arg);
479 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
480 errmsg("no language specified")));
481 *language = NULL; /* keep compiler quiet */
484 /* process optional items */
486 *volatility_p = interpret_func_volatility(volatility_item);
488 *strict_p = intVal(strict_item->arg);
490 *security_definer = intVal(security_item->arg);
492 *proconfig = update_proconfig_value(NULL, set_items);
495 *procost = defGetNumeric(cost_item);
498 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
499 errmsg("COST must be positive")));
503 *prorows = defGetNumeric(rows_item);
506 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
507 errmsg("ROWS must be positive")));
513 * Interpret the parameters *parameters and return their contents via
514 * *isStrict_p and *volatility_p.
516 * These parameters supply optional information about a function.
517 * All have defaults if not specified. Parameters:
519 * * isStrict means the function should not be called when any NULL
520 * inputs are present; instead a NULL result value should be assumed.
522 * * volatility tells the optimizer whether the function's result can
523 * be assumed to be repeatable over multiple evaluations.
527 compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatility_p)
531 foreach(pl, parameters)
533 DefElem *param = (DefElem *) lfirst(pl);
535 if (pg_strcasecmp(param->defname, "isstrict") == 0)
536 *isStrict_p = defGetBoolean(param);
537 else if (pg_strcasecmp(param->defname, "iscachable") == 0)
539 /* obsolete spelling of isImmutable */
540 if (defGetBoolean(param))
541 *volatility_p = PROVOLATILE_IMMUTABLE;
545 (errcode(ERRCODE_SYNTAX_ERROR),
546 errmsg("unrecognized function attribute \"%s\" ignored",
553 * For a dynamically linked C language object, the form of the clause is
555 * AS <object file name> [, <link symbol name> ]
559 * AS <object reference, or sql code>
562 interpret_AS_clause(Oid languageOid, const char *languageName, List *as,
563 char **prosrc_str_p, char **probin_str_p)
567 if (languageOid == ClanguageId)
570 * For "C" language, store the file name in probin and, when given,
571 * the link symbol name in prosrc.
573 *probin_str_p = strVal(linitial(as));
574 if (list_length(as) == 1)
577 *prosrc_str_p = strVal(lsecond(as));
581 /* Everything else wants the given string in prosrc. */
582 *prosrc_str_p = strVal(linitial(as));
585 if (list_length(as) != 1)
587 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
588 errmsg("only one AS item needed for language \"%s\"",
597 * Execute a CREATE FUNCTION utility statement.
600 CreateFunction(CreateFunctionStmt *stmt)
609 Oid languageValidator;
613 oidvector *parameterTypes;
614 ArrayType *allParameterTypes;
615 ArrayType *parameterModes;
616 ArrayType *parameterNames;
617 Oid requiredResultType;
621 ArrayType *proconfig;
624 HeapTuple languageTuple;
625 Form_pg_language languageStruct;
628 /* Convert list of names to a name and namespace */
629 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
632 /* Check we have creation rights in target namespace */
633 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
634 if (aclresult != ACLCHECK_OK)
635 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
636 get_namespace_name(namespaceId));
638 /* default attributes */
641 volatility = PROVOLATILE_VOLATILE;
643 procost = -1; /* indicates not set */
644 prorows = -1; /* indicates not set */
646 /* override attributes from explicit list */
647 compute_attributes_sql_style(stmt->options,
648 &as_clause, &language,
649 &volatility, &isStrict, &security,
650 &proconfig, &procost, &prorows);
652 /* Convert language name to canonical case */
653 languageName = case_translate_language_name(language);
655 /* Look up the language and validate permissions */
656 languageTuple = SearchSysCache(LANGNAME,
657 PointerGetDatum(languageName),
659 if (!HeapTupleIsValid(languageTuple))
661 (errcode(ERRCODE_UNDEFINED_OBJECT),
662 errmsg("language \"%s\" does not exist", languageName),
663 (PLTemplateExists(languageName) ?
664 errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
666 languageOid = HeapTupleGetOid(languageTuple);
667 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
669 if (languageStruct->lanpltrusted)
671 /* if trusted language, need USAGE privilege */
674 aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
675 if (aclresult != ACLCHECK_OK)
676 aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
677 NameStr(languageStruct->lanname));
681 /* if untrusted language, must be superuser */
683 aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
684 NameStr(languageStruct->lanname));
687 languageValidator = languageStruct->lanvalidator;
689 ReleaseSysCache(languageTuple);
692 * Convert remaining parameters of CREATE to form wanted by
695 examine_parameter_list(stmt->parameters, languageOid,
700 &requiredResultType);
702 if (stmt->returnType)
704 /* explicit RETURNS clause */
705 compute_return_type(stmt->returnType, languageOid,
706 &prorettype, &returnsSet);
707 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
709 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
710 errmsg("function result type must be %s because of OUT parameters",
711 format_type_be(requiredResultType))));
713 else if (OidIsValid(requiredResultType))
715 /* default RETURNS clause from OUT parameters */
716 prorettype = requiredResultType;
722 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
723 errmsg("function result type must be specified")));
724 /* Alternative possibility: default to RETURNS VOID */
725 prorettype = VOIDOID;
729 compute_attributes_with_style(stmt->withClause, &isStrict, &volatility);
731 interpret_AS_clause(languageOid, languageName, as_clause,
732 &prosrc_str, &probin_str);
734 if (languageOid == INTERNALlanguageId)
737 * In PostgreSQL versions before 6.5, the SQL name of the created
738 * function could not be different from the internal name, and
739 * "prosrc" wasn't used. So there is code out there that does CREATE
740 * FUNCTION xyz AS '' LANGUAGE internal. To preserve some modicum of
741 * backwards compatibility, accept an empty "prosrc" value as meaning
742 * the supplied SQL function name.
744 if (strlen(prosrc_str) == 0)
745 prosrc_str = funcname;
748 if (languageOid == ClanguageId)
750 /* If link symbol is specified as "-", substitute procedure name */
751 if (strcmp(prosrc_str, "-") == 0)
752 prosrc_str = funcname;
756 * Set default values for COST and ROWS depending on other parameters;
757 * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
758 * values, keep it in sync if you change them.
762 /* SQL and PL-language functions are assumed more expensive */
763 if (languageOid == INTERNALlanguageId ||
764 languageOid == ClanguageId)
774 prorows = 0; /* dummy value if not returnsSet */
776 else if (!returnsSet)
778 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
779 errmsg("ROWS is not applicable when function does not return a set")));
782 * And now that we have all the parameters, and know we're permitted to do
783 * so, go ahead and create the function.
785 ProcedureCreate(funcname,
792 prosrc_str, /* converted to text later */
793 probin_str, /* converted to text later */
794 false, /* not an aggregate */
799 PointerGetDatum(allParameterTypes),
800 PointerGetDatum(parameterModes),
801 PointerGetDatum(parameterNames),
802 PointerGetDatum(proconfig),
810 * Deletes a function.
813 RemoveFunction(RemoveFuncStmt *stmt)
815 List *functionName = stmt->name;
816 List *argTypes = stmt->args; /* list of TypeName nodes */
819 ObjectAddress object;
822 * Find the function, do permissions and validity checks
824 funcOid = LookupFuncNameTypeNames(functionName, argTypes, stmt->missing_ok);
825 if (!OidIsValid(funcOid))
827 /* can only get here if stmt->missing_ok */
829 (errmsg("function %s(%s) does not exist, skipping",
830 NameListToString(functionName),
831 TypeNameListToString(argTypes))));
835 tup = SearchSysCache(PROCOID,
836 ObjectIdGetDatum(funcOid),
838 if (!HeapTupleIsValid(tup)) /* should not happen */
839 elog(ERROR, "cache lookup failed for function %u", funcOid);
841 /* Permission check: must own func or its namespace */
842 if (!pg_proc_ownercheck(funcOid, GetUserId()) &&
843 !pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace,
845 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
846 NameListToString(functionName));
848 if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
850 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
851 errmsg("\"%s\" is an aggregate function",
852 NameListToString(functionName)),
853 errhint("Use DROP AGGREGATE to drop aggregate functions.")));
855 if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
857 /* "Helpful" NOTICE when removing a builtin function ... */
859 (errcode(ERRCODE_WARNING),
860 errmsg("removing built-in function \"%s\"",
861 NameListToString(functionName))));
864 ReleaseSysCache(tup);
869 object.classId = ProcedureRelationId;
870 object.objectId = funcOid;
871 object.objectSubId = 0;
873 performDeletion(&object, stmt->behavior);
877 * Guts of function deletion.
879 * Note: this is also used for aggregate deletion, since the OIDs of
880 * both functions and aggregates point to pg_proc.
883 RemoveFunctionById(Oid funcOid)
890 * Delete the pg_proc tuple.
892 relation = heap_open(ProcedureRelationId, RowExclusiveLock);
894 tup = SearchSysCache(PROCOID,
895 ObjectIdGetDatum(funcOid),
897 if (!HeapTupleIsValid(tup)) /* should not happen */
898 elog(ERROR, "cache lookup failed for function %u", funcOid);
900 isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
902 simple_heap_delete(relation, &tup->t_self);
904 ReleaseSysCache(tup);
906 heap_close(relation, RowExclusiveLock);
909 * If there's a pg_aggregate tuple, delete that too.
913 relation = heap_open(AggregateRelationId, RowExclusiveLock);
915 tup = SearchSysCache(AGGFNOID,
916 ObjectIdGetDatum(funcOid),
918 if (!HeapTupleIsValid(tup)) /* should not happen */
919 elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
921 simple_heap_delete(relation, &tup->t_self);
923 ReleaseSysCache(tup);
925 heap_close(relation, RowExclusiveLock);
934 RenameFunction(List *name, List *argtypes, const char *newname)
939 Form_pg_proc procForm;
943 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
945 procOid = LookupFuncNameTypeNames(name, argtypes, false);
947 tup = SearchSysCacheCopy(PROCOID,
948 ObjectIdGetDatum(procOid),
950 if (!HeapTupleIsValid(tup)) /* should not happen */
951 elog(ERROR, "cache lookup failed for function %u", procOid);
952 procForm = (Form_pg_proc) GETSTRUCT(tup);
954 if (procForm->proisagg)
956 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
957 errmsg("\"%s\" is an aggregate function",
958 NameListToString(name)),
959 errhint("Use ALTER AGGREGATE to rename aggregate functions.")));
961 namespaceOid = procForm->pronamespace;
963 /* make sure the new name doesn't exist */
964 if (SearchSysCacheExists(PROCNAMEARGSNSP,
965 CStringGetDatum(newname),
966 PointerGetDatum(&procForm->proargtypes),
967 ObjectIdGetDatum(namespaceOid),
971 (errcode(ERRCODE_DUPLICATE_FUNCTION),
972 errmsg("function %s already exists in schema \"%s\"",
973 funcname_signature_string(newname,
975 procForm->proargtypes.values),
976 get_namespace_name(namespaceOid))));
980 if (!pg_proc_ownercheck(procOid, GetUserId()))
981 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
982 NameListToString(name));
984 /* must have CREATE privilege on namespace */
985 aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
986 if (aclresult != ACLCHECK_OK)
987 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
988 get_namespace_name(namespaceOid));
991 namestrcpy(&(procForm->proname), newname);
992 simple_heap_update(rel, &tup->t_self, tup);
993 CatalogUpdateIndexes(rel, tup);
995 heap_close(rel, NoLock);
1000 * Change function owner by name and args
1003 AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
1009 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1011 procOid = LookupFuncNameTypeNames(name, argtypes, false);
1013 tup = SearchSysCache(PROCOID,
1014 ObjectIdGetDatum(procOid),
1016 if (!HeapTupleIsValid(tup)) /* should not happen */
1017 elog(ERROR, "cache lookup failed for function %u", procOid);
1019 if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
1021 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1022 errmsg("\"%s\" is an aggregate function",
1023 NameListToString(name)),
1024 errhint("Use ALTER AGGREGATE to change owner of aggregate functions.")));
1026 AlterFunctionOwner_internal(rel, tup, newOwnerId);
1028 heap_close(rel, NoLock);
1032 * Change function owner by Oid
1035 AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId)
1040 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1042 tup = SearchSysCache(PROCOID,
1043 ObjectIdGetDatum(procOid),
1045 if (!HeapTupleIsValid(tup)) /* should not happen */
1046 elog(ERROR, "cache lookup failed for function %u", procOid);
1047 AlterFunctionOwner_internal(rel, tup, newOwnerId);
1049 heap_close(rel, NoLock);
1053 AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
1055 Form_pg_proc procForm;
1056 AclResult aclresult;
1059 Assert(RelationGetRelid(rel) == ProcedureRelationId);
1060 Assert(tup->t_tableOid == ProcedureRelationId);
1062 procForm = (Form_pg_proc) GETSTRUCT(tup);
1063 procOid = HeapTupleGetOid(tup);
1066 * If the new owner is the same as the existing owner, consider the
1067 * command to have succeeded. This is for dump restoration purposes.
1069 if (procForm->proowner != newOwnerId)
1071 Datum repl_val[Natts_pg_proc];
1072 char repl_null[Natts_pg_proc];
1073 char repl_repl[Natts_pg_proc];
1079 /* Superusers can always do it */
1082 /* Otherwise, must be owner of the existing object */
1083 if (!pg_proc_ownercheck(procOid, GetUserId()))
1084 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1085 NameStr(procForm->proname));
1087 /* Must be able to become new owner */
1088 check_is_member_of_role(GetUserId(), newOwnerId);
1090 /* New owner must have CREATE privilege on namespace */
1091 aclresult = pg_namespace_aclcheck(procForm->pronamespace,
1094 if (aclresult != ACLCHECK_OK)
1095 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1096 get_namespace_name(procForm->pronamespace));
1099 memset(repl_null, ' ', sizeof(repl_null));
1100 memset(repl_repl, ' ', sizeof(repl_repl));
1102 repl_repl[Anum_pg_proc_proowner - 1] = 'r';
1103 repl_val[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(newOwnerId);
1106 * Determine the modified ACL for the new owner. This is only
1107 * necessary when the ACL is non-null.
1109 aclDatum = SysCacheGetAttr(PROCOID, tup,
1110 Anum_pg_proc_proacl,
1114 newAcl = aclnewowner(DatumGetAclP(aclDatum),
1115 procForm->proowner, newOwnerId);
1116 repl_repl[Anum_pg_proc_proacl - 1] = 'r';
1117 repl_val[Anum_pg_proc_proacl - 1] = PointerGetDatum(newAcl);
1120 newtuple = heap_modifytuple(tup, RelationGetDescr(rel), repl_val,
1121 repl_null, repl_repl);
1123 simple_heap_update(rel, &newtuple->t_self, newtuple);
1124 CatalogUpdateIndexes(rel, newtuple);
1126 heap_freetuple(newtuple);
1128 /* Update owner dependency reference */
1129 changeDependencyOnOwner(ProcedureRelationId, procOid, newOwnerId);
1132 ReleaseSysCache(tup);
1136 * Implements the ALTER FUNCTION utility command (except for the
1137 * RENAME and OWNER clauses, which are handled as part of the generic
1141 AlterFunction(AlterFunctionStmt *stmt)
1145 Form_pg_proc procForm;
1148 DefElem *volatility_item = NULL;
1149 DefElem *strict_item = NULL;
1150 DefElem *security_def_item = NULL;
1151 List *set_items = NIL;
1152 DefElem *cost_item = NULL;
1153 DefElem *rows_item = NULL;
1155 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1157 funcOid = LookupFuncNameTypeNames(stmt->func->funcname,
1158 stmt->func->funcargs,
1161 tup = SearchSysCacheCopy(PROCOID,
1162 ObjectIdGetDatum(funcOid),
1164 if (!HeapTupleIsValid(tup)) /* should not happen */
1165 elog(ERROR, "cache lookup failed for function %u", funcOid);
1167 procForm = (Form_pg_proc) GETSTRUCT(tup);
1169 /* Permission check: must own function */
1170 if (!pg_proc_ownercheck(funcOid, GetUserId()))
1171 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1172 NameListToString(stmt->func->funcname));
1174 if (procForm->proisagg)
1176 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1177 errmsg("\"%s\" is an aggregate function",
1178 NameListToString(stmt->func->funcname))));
1180 /* Examine requested actions. */
1181 foreach(l, stmt->actions)
1183 DefElem *defel = (DefElem *) lfirst(l);
1185 if (compute_common_attribute(defel,
1191 &rows_item) == false)
1192 elog(ERROR, "option \"%s\" not recognized", defel->defname);
1195 if (volatility_item)
1196 procForm->provolatile = interpret_func_volatility(volatility_item);
1198 procForm->proisstrict = intVal(strict_item->arg);
1199 if (security_def_item)
1200 procForm->prosecdef = intVal(security_def_item->arg);
1203 procForm->procost = defGetNumeric(cost_item);
1204 if (procForm->procost <= 0)
1206 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1207 errmsg("COST must be positive")));
1211 procForm->prorows = defGetNumeric(rows_item);
1212 if (procForm->prorows <= 0)
1214 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1215 errmsg("ROWS must be positive")));
1216 if (!procForm->proretset)
1218 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1219 errmsg("ROWS is not applicable when function does not return a set")));
1226 Datum repl_val[Natts_pg_proc];
1227 char repl_null[Natts_pg_proc];
1228 char repl_repl[Natts_pg_proc];
1230 /* extract existing proconfig setting */
1231 datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1232 a = isnull ? NULL : DatumGetArrayTypeP(datum);
1234 /* update according to each SET or RESET item, left to right */
1235 a = update_proconfig_value(a, set_items);
1237 /* update the tuple */
1238 memset(repl_repl, ' ', sizeof(repl_repl));
1239 repl_repl[Anum_pg_proc_proconfig - 1] = 'r';
1243 repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1244 repl_null[Anum_pg_proc_proconfig - 1] = 'n';
1248 repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1249 repl_null[Anum_pg_proc_proconfig - 1] = ' ';
1252 tup = heap_modifytuple(tup, RelationGetDescr(rel),
1253 repl_val, repl_null, repl_repl);
1257 simple_heap_update(rel, &tup->t_self, tup);
1258 CatalogUpdateIndexes(rel, tup);
1260 heap_close(rel, NoLock);
1261 heap_freetuple(tup);
1265 * SetFunctionReturnType - change declared return type of a function
1267 * This is presently only used for adjusting legacy functions that return
1268 * OPAQUE to return whatever we find their correct definition should be.
1269 * The caller should emit a suitable warning explaining what we did.
1272 SetFunctionReturnType(Oid funcOid, Oid newRetType)
1274 Relation pg_proc_rel;
1276 Form_pg_proc procForm;
1278 pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1280 tup = SearchSysCacheCopy(PROCOID,
1281 ObjectIdGetDatum(funcOid),
1283 if (!HeapTupleIsValid(tup)) /* should not happen */
1284 elog(ERROR, "cache lookup failed for function %u", funcOid);
1285 procForm = (Form_pg_proc) GETSTRUCT(tup);
1287 if (procForm->prorettype != OPAQUEOID) /* caller messed up */
1288 elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
1290 /* okay to overwrite copied tuple */
1291 procForm->prorettype = newRetType;
1293 /* update the catalog and its indexes */
1294 simple_heap_update(pg_proc_rel, &tup->t_self, tup);
1296 CatalogUpdateIndexes(pg_proc_rel, tup);
1298 heap_close(pg_proc_rel, RowExclusiveLock);
1303 * SetFunctionArgType - change declared argument type of a function
1305 * As above, but change an argument's type.
1308 SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
1310 Relation pg_proc_rel;
1312 Form_pg_proc procForm;
1314 pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1316 tup = SearchSysCacheCopy(PROCOID,
1317 ObjectIdGetDatum(funcOid),
1319 if (!HeapTupleIsValid(tup)) /* should not happen */
1320 elog(ERROR, "cache lookup failed for function %u", funcOid);
1321 procForm = (Form_pg_proc) GETSTRUCT(tup);
1323 if (argIndex < 0 || argIndex >= procForm->pronargs ||
1324 procForm->proargtypes.values[argIndex] != OPAQUEOID)
1325 elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
1327 /* okay to overwrite copied tuple */
1328 procForm->proargtypes.values[argIndex] = newArgType;
1330 /* update the catalog and its indexes */
1331 simple_heap_update(pg_proc_rel, &tup->t_self, tup);
1333 CatalogUpdateIndexes(pg_proc_rel, tup);
1335 heap_close(pg_proc_rel, RowExclusiveLock);
1344 CreateCast(CreateCastStmt *stmt)
1353 Datum values[Natts_pg_cast];
1354 char nulls[Natts_pg_cast];
1355 ObjectAddress myself,
1358 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
1359 targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
1361 /* No pseudo-types allowed */
1362 if (get_typtype(sourcetypeid) == TYPTYPE_PSEUDO)
1364 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1365 errmsg("source data type %s is a pseudo-type",
1366 TypeNameToString(stmt->sourcetype))));
1368 if (get_typtype(targettypeid) == TYPTYPE_PSEUDO)
1370 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1371 errmsg("target data type %s is a pseudo-type",
1372 TypeNameToString(stmt->targettype))));
1374 /* Permission check */
1375 if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1376 && !pg_type_ownercheck(targettypeid, GetUserId()))
1378 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1379 errmsg("must be owner of type %s or type %s",
1380 TypeNameToString(stmt->sourcetype),
1381 TypeNameToString(stmt->targettype))));
1383 if (stmt->func != NULL)
1385 Form_pg_proc procstruct;
1387 funcid = LookupFuncNameTypeNames(stmt->func->funcname,
1388 stmt->func->funcargs,
1391 tuple = SearchSysCache(PROCOID,
1392 ObjectIdGetDatum(funcid),
1394 if (!HeapTupleIsValid(tuple))
1395 elog(ERROR, "cache lookup failed for function %u", funcid);
1397 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1398 nargs = procstruct->pronargs;
1399 if (nargs < 1 || nargs > 3)
1401 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1402 errmsg("cast function must take one to three arguments")));
1403 if (procstruct->proargtypes.values[0] != sourcetypeid)
1405 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1406 errmsg("argument of cast function must match source data type")));
1407 if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1409 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1410 errmsg("second argument of cast function must be type integer")));
1411 if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1413 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1414 errmsg("third argument of cast function must be type boolean")));
1415 if (procstruct->prorettype != targettypeid)
1417 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1418 errmsg("return data type of cast function must match target data type")));
1421 * Restricting the volatility of a cast function may or may not be a
1422 * good idea in the abstract, but it definitely breaks many old
1423 * user-defined types. Disable this check --- tgl 2/1/03
1426 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1428 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1429 errmsg("cast function must not be volatile")));
1431 if (procstruct->proisagg)
1433 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1434 errmsg("cast function must not be an aggregate function")));
1435 if (procstruct->proretset)
1437 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1438 errmsg("cast function must not return a set")));
1440 ReleaseSysCache(tuple);
1451 /* indicates binary coercibility */
1452 funcid = InvalidOid;
1456 * Must be superuser to create binary-compatible casts, since
1457 * erroneous casts can easily crash the backend.
1461 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1462 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1465 * Also, insist that the types match as to size, alignment, and
1466 * pass-by-value attributes; this provides at least a crude check that
1467 * they have similar representations. A pair of types that fail this
1468 * test should certainly not be equated.
1470 get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1471 get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1472 if (typ1len != typ2len ||
1473 typ1byval != typ2byval ||
1474 typ1align != typ2align)
1476 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1477 errmsg("source and target data types are not physically compatible")));
1481 * Allow source and target types to be same only for length coercion
1482 * functions. We assume a multi-arg function does length coercion.
1484 if (sourcetypeid == targettypeid && nargs < 2)
1486 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1487 errmsg("source data type and target data type are the same")));
1489 /* convert CoercionContext enum to char value for castcontext */
1490 switch (stmt->context)
1492 case COERCION_IMPLICIT:
1493 castcontext = COERCION_CODE_IMPLICIT;
1495 case COERCION_ASSIGNMENT:
1496 castcontext = COERCION_CODE_ASSIGNMENT;
1498 case COERCION_EXPLICIT:
1499 castcontext = COERCION_CODE_EXPLICIT;
1502 elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1503 castcontext = 0; /* keep compiler quiet */
1507 relation = heap_open(CastRelationId, RowExclusiveLock);
1510 * Check for duplicate. This is just to give a friendly error message,
1511 * the unique index would catch it anyway (so no need to sweat about race
1514 tuple = SearchSysCache(CASTSOURCETARGET,
1515 ObjectIdGetDatum(sourcetypeid),
1516 ObjectIdGetDatum(targettypeid),
1518 if (HeapTupleIsValid(tuple))
1520 (errcode(ERRCODE_DUPLICATE_OBJECT),
1521 errmsg("cast from type %s to type %s already exists",
1522 TypeNameToString(stmt->sourcetype),
1523 TypeNameToString(stmt->targettype))));
1526 values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
1527 values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
1528 values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
1529 values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
1531 MemSet(nulls, ' ', Natts_pg_cast);
1533 tuple = heap_formtuple(RelationGetDescr(relation), values, nulls);
1535 simple_heap_insert(relation, tuple);
1537 CatalogUpdateIndexes(relation, tuple);
1539 /* make dependency entries */
1540 myself.classId = CastRelationId;
1541 myself.objectId = HeapTupleGetOid(tuple);
1542 myself.objectSubId = 0;
1544 /* dependency on source type */
1545 referenced.classId = TypeRelationId;
1546 referenced.objectId = sourcetypeid;
1547 referenced.objectSubId = 0;
1548 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1550 /* dependency on target type */
1551 referenced.classId = TypeRelationId;
1552 referenced.objectId = targettypeid;
1553 referenced.objectSubId = 0;
1554 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1556 /* dependency on function */
1557 if (OidIsValid(funcid))
1559 referenced.classId = ProcedureRelationId;
1560 referenced.objectId = funcid;
1561 referenced.objectSubId = 0;
1562 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1565 heap_freetuple(tuple);
1567 heap_close(relation, RowExclusiveLock);
1576 DropCast(DropCastStmt *stmt)
1581 ObjectAddress object;
1583 /* when dropping a cast, the types must exist even if you use IF EXISTS */
1584 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
1585 targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
1587 tuple = SearchSysCache(CASTSOURCETARGET,
1588 ObjectIdGetDatum(sourcetypeid),
1589 ObjectIdGetDatum(targettypeid),
1591 if (!HeapTupleIsValid(tuple))
1593 if (!stmt->missing_ok)
1595 (errcode(ERRCODE_UNDEFINED_OBJECT),
1596 errmsg("cast from type %s to type %s does not exist",
1597 TypeNameToString(stmt->sourcetype),
1598 TypeNameToString(stmt->targettype))));
1601 (errmsg("cast from type %s to type %s does not exist, skipping",
1602 TypeNameToString(stmt->sourcetype),
1603 TypeNameToString(stmt->targettype))));
1608 /* Permission check */
1609 if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1610 && !pg_type_ownercheck(targettypeid, GetUserId()))
1612 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1613 errmsg("must be owner of type %s or type %s",
1614 TypeNameToString(stmt->sourcetype),
1615 TypeNameToString(stmt->targettype))));
1620 object.classId = CastRelationId;
1621 object.objectId = HeapTupleGetOid(tuple);
1622 object.objectSubId = 0;
1624 ReleaseSysCache(tuple);
1626 performDeletion(&object, stmt->behavior);
1631 DropCastById(Oid castOid)
1634 ScanKeyData scankey;
1638 relation = heap_open(CastRelationId, RowExclusiveLock);
1640 ScanKeyInit(&scankey,
1641 ObjectIdAttributeNumber,
1642 BTEqualStrategyNumber, F_OIDEQ,
1643 ObjectIdGetDatum(castOid));
1644 scan = systable_beginscan(relation, CastOidIndexId, true,
1645 SnapshotNow, 1, &scankey);
1647 tuple = systable_getnext(scan);
1648 if (!HeapTupleIsValid(tuple))
1649 elog(ERROR, "could not find tuple for cast %u", castOid);
1650 simple_heap_delete(relation, &tuple->t_self);
1652 systable_endscan(scan);
1653 heap_close(relation, RowExclusiveLock);
1657 * Execute ALTER FUNCTION/AGGREGATE SET SCHEMA
1659 * These commands are identical except for the lookup procedure, so share code.
1662 AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
1663 const char *newschema)
1672 procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
1674 /* get function OID */
1676 procOid = LookupAggNameTypeNames(name, argtypes, false);
1678 procOid = LookupFuncNameTypeNames(name, argtypes, false);
1680 /* check permissions on function */
1681 if (!pg_proc_ownercheck(procOid, GetUserId()))
1682 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1683 NameListToString(name));
1685 tup = SearchSysCacheCopy(PROCOID,
1686 ObjectIdGetDatum(procOid),
1688 if (!HeapTupleIsValid(tup))
1689 elog(ERROR, "cache lookup failed for function %u", procOid);
1690 proc = (Form_pg_proc) GETSTRUCT(tup);
1692 oldNspOid = proc->pronamespace;
1694 /* get schema OID and check its permissions */
1695 nspOid = LookupCreationNamespace(newschema);
1697 if (oldNspOid == nspOid)
1699 (errcode(ERRCODE_DUPLICATE_FUNCTION),
1700 errmsg("function \"%s\" is already in schema \"%s\"",
1701 NameListToString(name),
1704 /* disallow renaming into or out of temp schemas */
1705 if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
1707 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1708 errmsg("cannot move objects into or out of temporary schemas")));
1710 /* same for TOAST schema */
1711 if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
1713 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1714 errmsg("cannot move objects into or out of TOAST schema")));
1716 /* check for duplicate name (more friendly than unique-index failure) */
1717 if (SearchSysCacheExists(PROCNAMEARGSNSP,
1718 CStringGetDatum(NameStr(proc->proname)),
1719 PointerGetDatum(&proc->proargtypes),
1720 ObjectIdGetDatum(nspOid),
1723 (errcode(ERRCODE_DUPLICATE_FUNCTION),
1724 errmsg("function \"%s\" already exists in schema \"%s\"",
1725 NameStr(proc->proname),
1728 /* OK, modify the pg_proc row */
1730 /* tup is a copy, so we can scribble directly on it */
1731 proc->pronamespace = nspOid;
1733 simple_heap_update(procRel, &tup->t_self, tup);
1734 CatalogUpdateIndexes(procRel, tup);
1736 /* Update dependency on schema */
1737 if (changeDependencyFor(ProcedureRelationId, procOid,
1738 NamespaceRelationId, oldNspOid, nspOid) != 1)
1739 elog(ERROR, "failed to change schema dependency for function \"%s\"",
1740 NameListToString(name));
1742 heap_freetuple(tup);
1744 heap_close(procRel, RowExclusiveLock);