1 /*-------------------------------------------------------------------------
5 * Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
8 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * src/backend/commands/functioncmds.c
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 "access/sysattr.h"
38 #include "catalog/dependency.h"
39 #include "catalog/indexing.h"
40 #include "catalog/pg_aggregate.h"
41 #include "catalog/pg_cast.h"
42 #include "catalog/pg_language.h"
43 #include "catalog/pg_namespace.h"
44 #include "catalog/pg_proc.h"
45 #include "catalog/pg_proc_fn.h"
46 #include "catalog/pg_type.h"
47 #include "catalog/pg_type_fn.h"
48 #include "commands/defrem.h"
49 #include "commands/proclang.h"
50 #include "miscadmin.h"
51 #include "optimizer/var.h"
52 #include "parser/parse_coerce.h"
53 #include "parser/parse_expr.h"
54 #include "parser/parse_func.h"
55 #include "parser/parse_type.h"
56 #include "utils/acl.h"
57 #include "utils/builtins.h"
58 #include "utils/fmgroids.h"
59 #include "utils/guc.h"
60 #include "utils/lsyscache.h"
61 #include "utils/rel.h"
62 #include "utils/syscache.h"
63 #include "utils/tqual.h"
66 static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup,
71 * Examine the RETURNS clause of the CREATE FUNCTION statement
72 * and return information about it as *prorettype_p and *returnsSet.
74 * This is more complex than the average typename lookup because we want to
75 * allow a shell type to be used, or even created if the specified return type
76 * doesn't exist yet. (Without this, there's no way to define the I/O procs
77 * for a new type.) But SQL function creation won't cope, so error out if
78 * the target language is SQL. (We do this here, not in the SQL-function
79 * validator, so as not to produce a NOTICE and then an ERROR for the same
83 compute_return_type(TypeName *returnType, Oid languageOid,
84 Oid *prorettype_p, bool *returnsSet_p)
89 typtup = LookupTypeName(NULL, returnType, NULL);
93 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
95 if (languageOid == SQLlanguageId)
97 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
98 errmsg("SQL function cannot return shell type %s",
99 TypeNameToString(returnType))));
102 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
103 errmsg("return type %s is only a shell",
104 TypeNameToString(returnType))));
106 rettype = typeTypeId(typtup);
107 ReleaseSysCache(typtup);
111 char *typnam = TypeNameToString(returnType);
117 * Only C-coded functions can be I/O functions. We enforce this
118 * restriction here mainly to prevent littering the catalogs with
119 * shell types due to simple typos in user-defined function
122 if (languageOid != INTERNALlanguageId &&
123 languageOid != ClanguageId)
125 (errcode(ERRCODE_UNDEFINED_OBJECT),
126 errmsg("type \"%s\" does not exist", typnam)));
128 /* Reject if there's typmod decoration, too */
129 if (returnType->typmods != NIL)
131 (errcode(ERRCODE_SYNTAX_ERROR),
132 errmsg("type modifier cannot be specified for shell type \"%s\"",
135 /* Otherwise, go ahead and make a shell type */
137 (errcode(ERRCODE_UNDEFINED_OBJECT),
138 errmsg("type \"%s\" is not yet defined", typnam),
139 errdetail("Creating a shell type definition.")));
140 namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
142 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
144 if (aclresult != ACLCHECK_OK)
145 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
146 get_namespace_name(namespaceId));
147 rettype = TypeShellMake(typname, namespaceId, GetUserId());
148 Assert(OidIsValid(rettype));
151 *prorettype_p = rettype;
152 *returnsSet_p = returnType->setof;
156 * Interpret the parameter list of the CREATE FUNCTION statement.
158 * Results are stored into output parameters. parameterTypes must always
159 * be created, but the other arrays are set to NULL if not needed.
160 * requiredResultType is set to InvalidOid if there are no OUT parameters,
161 * else it is set to the OID of the implied result type.
164 examine_parameter_list(List *parameters, Oid languageOid,
165 const char *queryString,
166 oidvector **parameterTypes,
167 ArrayType **allParameterTypes,
168 ArrayType **parameterModes,
169 ArrayType **parameterNames,
170 List **parameterDefaults,
171 Oid *requiredResultType)
173 int parameterCount = list_length(parameters);
181 bool have_names = false;
182 bool have_defaults = false;
187 *requiredResultType = InvalidOid; /* default result */
189 inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
190 allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
191 paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
192 paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
193 *parameterDefaults = NIL;
195 /* may need a pstate for parse analysis of default exprs */
196 pstate = make_parsestate(NULL);
197 pstate->p_sourcetext = queryString;
199 /* Scan the list and extract data into work arrays */
201 foreach(x, parameters)
203 FunctionParameter *fp = (FunctionParameter *) lfirst(x);
204 TypeName *t = fp->argType;
205 bool isinput = false;
209 typtup = LookupTypeName(NULL, t, NULL);
212 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
214 /* As above, hard error if language is SQL */
215 if (languageOid == SQLlanguageId)
217 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
218 errmsg("SQL function cannot accept shell type %s",
219 TypeNameToString(t))));
222 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
223 errmsg("argument type %s is only a shell",
224 TypeNameToString(t))));
226 toid = typeTypeId(typtup);
227 ReleaseSysCache(typtup);
232 (errcode(ERRCODE_UNDEFINED_OBJECT),
233 errmsg("type %s does not exist",
234 TypeNameToString(t))));
235 toid = InvalidOid; /* keep compiler quiet */
240 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
241 errmsg("functions cannot accept set arguments")));
243 /* handle input parameters */
244 if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
246 /* other input parameters can't follow a VARIADIC parameter */
249 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
250 errmsg("VARIADIC parameter must be the last input parameter")));
251 inTypes[inCount++] = toid;
255 /* handle output parameters */
256 if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
258 if (outCount == 0) /* save first output param's type */
259 *requiredResultType = toid;
263 if (fp->mode == FUNC_PARAM_VARIADIC)
266 /* validate variadic parameter type */
274 if (!OidIsValid(get_element_type(toid)))
276 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
277 errmsg("VARIADIC parameter must be an array")));
282 allTypes[i] = ObjectIdGetDatum(toid);
284 paramModes[i] = CharGetDatum(fp->mode);
286 if (fp->name && fp->name[0])
291 * As of Postgres 9.0 we disallow using the same name for two
292 * input or two output function parameters. Depending on the
293 * function's language, conflicting input and output names might
294 * be bad too, but we leave it to the PL to complain if so.
296 foreach(px, parameters)
298 FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
302 /* pure in doesn't conflict with pure out */
303 if ((fp->mode == FUNC_PARAM_IN ||
304 fp->mode == FUNC_PARAM_VARIADIC) &&
305 (prevfp->mode == FUNC_PARAM_OUT ||
306 prevfp->mode == FUNC_PARAM_TABLE))
308 if ((prevfp->mode == FUNC_PARAM_IN ||
309 prevfp->mode == FUNC_PARAM_VARIADIC) &&
310 (fp->mode == FUNC_PARAM_OUT ||
311 fp->mode == FUNC_PARAM_TABLE))
313 if (prevfp->name && prevfp->name[0] &&
314 strcmp(prevfp->name, fp->name) == 0)
316 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
317 errmsg("parameter name \"%s\" used more than once",
321 paramNames[i] = CStringGetTextDatum(fp->name);
331 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
332 errmsg("only input parameters can have default values")));
334 def = transformExpr(pstate, fp->defexpr);
335 def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
338 * Make sure no variables are referred to.
340 if (list_length(pstate->p_rtable) != 0 ||
341 contain_var_clause(def))
343 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
344 errmsg("cannot use table references in parameter default value")));
347 * It can't return a set either --- but coerce_to_specific_type
348 * already checked that for us.
350 * No subplans or aggregates, either...
352 * Note: the point of these restrictions is to ensure that an
353 * expression that, on its face, hasn't got subplans, aggregates,
354 * etc cannot suddenly have them after function default arguments
357 if (pstate->p_hasSubLinks)
359 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
360 errmsg("cannot use subquery in parameter default value")));
361 if (pstate->p_hasAggs)
363 (errcode(ERRCODE_GROUPING_ERROR),
364 errmsg("cannot use aggregate function in parameter default value")));
365 if (pstate->p_hasWindowFuncs)
367 (errcode(ERRCODE_WINDOWING_ERROR),
368 errmsg("cannot use window function in parameter default value")));
370 *parameterDefaults = lappend(*parameterDefaults, def);
371 have_defaults = true;
375 if (isinput && have_defaults)
377 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
378 errmsg("input parameters after one with a default value must also have defaults")));
384 free_parsestate(pstate);
386 /* Now construct the proper outputs as needed */
387 *parameterTypes = buildoidvector(inTypes, inCount);
389 if (outCount > 0 || varCount > 0)
391 *allParameterTypes = construct_array(allTypes, parameterCount, OIDOID,
392 sizeof(Oid), true, 'i');
393 *parameterModes = construct_array(paramModes, parameterCount, CHAROID,
396 *requiredResultType = RECORDOID;
397 /* otherwise we set requiredResultType correctly above */
401 *allParameterTypes = NULL;
402 *parameterModes = NULL;
407 for (i = 0; i < parameterCount; i++)
409 if (paramNames[i] == PointerGetDatum(NULL))
410 paramNames[i] = CStringGetTextDatum("");
412 *parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
416 *parameterNames = NULL;
421 * Recognize one of the options that can be passed to both CREATE
422 * FUNCTION and ALTER FUNCTION and return it via one of the out
423 * parameters. Returns true if the passed option was recognized. If
424 * the out parameter we were going to assign to points to non-NULL,
425 * raise a duplicate-clause error. (We don't try to detect duplicate
426 * SET parameters though --- if you're redundant, the last one wins.)
429 compute_common_attribute(DefElem *defel,
430 DefElem **volatility_item,
431 DefElem **strict_item,
432 DefElem **security_item,
437 if (strcmp(defel->defname, "volatility") == 0)
439 if (*volatility_item)
440 goto duplicate_error;
442 *volatility_item = defel;
444 else if (strcmp(defel->defname, "strict") == 0)
447 goto duplicate_error;
449 *strict_item = defel;
451 else if (strcmp(defel->defname, "security") == 0)
454 goto duplicate_error;
456 *security_item = defel;
458 else if (strcmp(defel->defname, "set") == 0)
460 *set_items = lappend(*set_items, defel->arg);
462 else if (strcmp(defel->defname, "cost") == 0)
465 goto duplicate_error;
469 else if (strcmp(defel->defname, "rows") == 0)
472 goto duplicate_error;
479 /* Recognized an option */
484 (errcode(ERRCODE_SYNTAX_ERROR),
485 errmsg("conflicting or redundant options")));
486 return false; /* keep compiler quiet */
490 interpret_func_volatility(DefElem *defel)
492 char *str = strVal(defel->arg);
494 if (strcmp(str, "immutable") == 0)
495 return PROVOLATILE_IMMUTABLE;
496 else if (strcmp(str, "stable") == 0)
497 return PROVOLATILE_STABLE;
498 else if (strcmp(str, "volatile") == 0)
499 return PROVOLATILE_VOLATILE;
502 elog(ERROR, "invalid volatility \"%s\"", str);
503 return 0; /* keep compiler quiet */
508 * Update a proconfig value according to a list of VariableSetStmt items.
510 * The input and result may be NULL to signify a null entry.
513 update_proconfig_value(ArrayType *a, List *set_items)
517 foreach(l, set_items)
519 VariableSetStmt *sstmt = (VariableSetStmt *) lfirst(l);
521 Assert(IsA(sstmt, VariableSetStmt));
522 if (sstmt->kind == VAR_RESET_ALL)
526 char *valuestr = ExtractSetVariableArgs(sstmt);
529 a = GUCArrayAdd(a, sstmt->name, valuestr);
531 a = GUCArrayDelete(a, sstmt->name);
540 * Dissect the list of options assembled in gram.y into function
544 compute_attributes_sql_style(List *options,
550 bool *security_definer,
551 ArrayType **proconfig,
556 DefElem *as_item = NULL;
557 DefElem *language_item = NULL;
558 DefElem *windowfunc_item = NULL;
559 DefElem *volatility_item = NULL;
560 DefElem *strict_item = NULL;
561 DefElem *security_item = NULL;
562 List *set_items = NIL;
563 DefElem *cost_item = NULL;
564 DefElem *rows_item = NULL;
566 foreach(option, options)
568 DefElem *defel = (DefElem *) lfirst(option);
570 if (strcmp(defel->defname, "as") == 0)
574 (errcode(ERRCODE_SYNTAX_ERROR),
575 errmsg("conflicting or redundant options")));
578 else if (strcmp(defel->defname, "language") == 0)
582 (errcode(ERRCODE_SYNTAX_ERROR),
583 errmsg("conflicting or redundant options")));
584 language_item = defel;
586 else if (strcmp(defel->defname, "window") == 0)
590 (errcode(ERRCODE_SYNTAX_ERROR),
591 errmsg("conflicting or redundant options")));
592 windowfunc_item = defel;
594 else if (compute_common_attribute(defel,
602 /* recognized common option */
606 elog(ERROR, "option \"%s\" not recognized",
610 /* process required items */
612 *as = (List *) as_item->arg;
616 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
617 errmsg("no function body specified")));
618 *as = NIL; /* keep compiler quiet */
622 *language = strVal(language_item->arg);
626 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
627 errmsg("no language specified")));
628 *language = NULL; /* keep compiler quiet */
631 /* process optional items */
633 *windowfunc_p = intVal(windowfunc_item->arg);
635 *volatility_p = interpret_func_volatility(volatility_item);
637 *strict_p = intVal(strict_item->arg);
639 *security_definer = intVal(security_item->arg);
641 *proconfig = update_proconfig_value(NULL, set_items);
644 *procost = defGetNumeric(cost_item);
647 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
648 errmsg("COST must be positive")));
652 *prorows = defGetNumeric(rows_item);
655 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
656 errmsg("ROWS must be positive")));
662 * Interpret the parameters *parameters and return their contents via
663 * *isStrict_p and *volatility_p.
665 * These parameters supply optional information about a function.
666 * All have defaults if not specified. Parameters:
668 * * isStrict means the function should not be called when any NULL
669 * inputs are present; instead a NULL result value should be assumed.
671 * * volatility tells the optimizer whether the function's result can
672 * be assumed to be repeatable over multiple evaluations.
676 compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatility_p)
680 foreach(pl, parameters)
682 DefElem *param = (DefElem *) lfirst(pl);
684 if (pg_strcasecmp(param->defname, "isstrict") == 0)
685 *isStrict_p = defGetBoolean(param);
686 else if (pg_strcasecmp(param->defname, "iscachable") == 0)
688 /* obsolete spelling of isImmutable */
689 if (defGetBoolean(param))
690 *volatility_p = PROVOLATILE_IMMUTABLE;
694 (errcode(ERRCODE_SYNTAX_ERROR),
695 errmsg("unrecognized function attribute \"%s\" ignored",
702 * For a dynamically linked C language object, the form of the clause is
704 * AS <object file name> [, <link symbol name> ]
708 * AS <object reference, or sql code>
711 interpret_AS_clause(Oid languageOid, const char *languageName,
712 char *funcname, List *as,
713 char **prosrc_str_p, char **probin_str_p)
717 if (languageOid == ClanguageId)
720 * For "C" language, store the file name in probin and, when given,
721 * the link symbol name in prosrc. If link symbol is omitted,
722 * substitute procedure name. We also allow link symbol to be
723 * specified as "-", since that was the habit in PG versions before
724 * 8.4, and there might be dump files out there that don't translate
725 * that back to "omitted".
727 *probin_str_p = strVal(linitial(as));
728 if (list_length(as) == 1)
729 *prosrc_str_p = funcname;
732 *prosrc_str_p = strVal(lsecond(as));
733 if (strcmp(*prosrc_str_p, "-") == 0)
734 *prosrc_str_p = funcname;
739 /* Everything else wants the given string in prosrc. */
740 *prosrc_str_p = strVal(linitial(as));
741 *probin_str_p = NULL;
743 if (list_length(as) != 1)
745 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
746 errmsg("only one AS item needed for language \"%s\"",
749 if (languageOid == INTERNALlanguageId)
752 * In PostgreSQL versions before 6.5, the SQL name of the created
753 * function could not be different from the internal name, and
754 * "prosrc" wasn't used. So there is code out there that does
755 * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
756 * modicum of backwards compatibility, accept an empty "prosrc"
757 * value as meaning the supplied SQL function name.
759 if (strlen(*prosrc_str_p) == 0)
760 *prosrc_str_p = funcname;
769 * Execute a CREATE FUNCTION utility statement.
772 CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
781 Oid languageValidator;
785 oidvector *parameterTypes;
786 ArrayType *allParameterTypes;
787 ArrayType *parameterModes;
788 ArrayType *parameterNames;
789 List *parameterDefaults;
790 Oid requiredResultType;
795 ArrayType *proconfig;
798 HeapTuple languageTuple;
799 Form_pg_language languageStruct;
802 /* Convert list of names to a name and namespace */
803 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
806 /* Check we have creation rights in target namespace */
807 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
808 if (aclresult != ACLCHECK_OK)
809 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
810 get_namespace_name(namespaceId));
812 /* default attributes */
813 isWindowFunc = false;
816 volatility = PROVOLATILE_VOLATILE;
818 procost = -1; /* indicates not set */
819 prorows = -1; /* indicates not set */
821 /* override attributes from explicit list */
822 compute_attributes_sql_style(stmt->options,
823 &as_clause, &language,
824 &isWindowFunc, &volatility,
825 &isStrict, &security,
826 &proconfig, &procost, &prorows);
828 /* Convert language name to canonical case */
829 languageName = case_translate_language_name(language);
831 /* Look up the language and validate permissions */
832 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
833 if (!HeapTupleIsValid(languageTuple))
835 (errcode(ERRCODE_UNDEFINED_OBJECT),
836 errmsg("language \"%s\" does not exist", languageName),
837 (PLTemplateExists(languageName) ?
838 errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
840 languageOid = HeapTupleGetOid(languageTuple);
841 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
843 if (languageStruct->lanpltrusted)
845 /* if trusted language, need USAGE privilege */
848 aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
849 if (aclresult != ACLCHECK_OK)
850 aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
851 NameStr(languageStruct->lanname));
855 /* if untrusted language, must be superuser */
857 aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
858 NameStr(languageStruct->lanname));
861 languageValidator = languageStruct->lanvalidator;
863 ReleaseSysCache(languageTuple);
866 * Convert remaining parameters of CREATE to form wanted by
869 examine_parameter_list(stmt->parameters, languageOid, queryString,
875 &requiredResultType);
877 if (stmt->returnType)
879 /* explicit RETURNS clause */
880 compute_return_type(stmt->returnType, languageOid,
881 &prorettype, &returnsSet);
882 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
884 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
885 errmsg("function result type must be %s because of OUT parameters",
886 format_type_be(requiredResultType))));
888 else if (OidIsValid(requiredResultType))
890 /* default RETURNS clause from OUT parameters */
891 prorettype = requiredResultType;
897 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
898 errmsg("function result type must be specified")));
899 /* Alternative possibility: default to RETURNS VOID */
900 prorettype = VOIDOID;
904 compute_attributes_with_style(stmt->withClause, &isStrict, &volatility);
906 interpret_AS_clause(languageOid, languageName, funcname, as_clause,
907 &prosrc_str, &probin_str);
910 * Set default values for COST and ROWS depending on other parameters;
911 * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
912 * values, keep it in sync if you change them.
916 /* SQL and PL-language functions are assumed more expensive */
917 if (languageOid == INTERNALlanguageId ||
918 languageOid == ClanguageId)
928 prorows = 0; /* dummy value if not returnsSet */
930 else if (!returnsSet)
932 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
933 errmsg("ROWS is not applicable when function does not return a set")));
936 * And now that we have all the parameters, and know we're permitted to do
937 * so, go ahead and create the function.
939 ProcedureCreate(funcname,
946 prosrc_str, /* converted to text later */
947 probin_str, /* converted to text later */
948 false, /* not an aggregate */
954 PointerGetDatum(allParameterTypes),
955 PointerGetDatum(parameterModes),
956 PointerGetDatum(parameterNames),
958 PointerGetDatum(proconfig),
966 * Deletes a function.
969 RemoveFunction(RemoveFuncStmt *stmt)
971 List *functionName = stmt->name;
972 List *argTypes = stmt->args; /* list of TypeName nodes */
975 ObjectAddress object;
978 * Find the function, do permissions and validity checks
980 funcOid = LookupFuncNameTypeNames(functionName, argTypes, stmt->missing_ok);
981 if (!OidIsValid(funcOid))
983 /* can only get here if stmt->missing_ok */
985 (errmsg("function %s(%s) does not exist, skipping",
986 NameListToString(functionName),
987 TypeNameListToString(argTypes))));
991 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
992 if (!HeapTupleIsValid(tup)) /* should not happen */
993 elog(ERROR, "cache lookup failed for function %u", funcOid);
995 /* Permission check: must own func or its namespace */
996 if (!pg_proc_ownercheck(funcOid, GetUserId()) &&
997 !pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace,
999 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1000 NameListToString(functionName));
1002 if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
1004 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1005 errmsg("\"%s\" is an aggregate function",
1006 NameListToString(functionName)),
1007 errhint("Use DROP AGGREGATE to drop aggregate functions.")));
1009 if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
1011 /* "Helpful" NOTICE when removing a builtin function ... */
1013 (errcode(ERRCODE_WARNING),
1014 errmsg("removing built-in function \"%s\"",
1015 NameListToString(functionName))));
1018 ReleaseSysCache(tup);
1023 object.classId = ProcedureRelationId;
1024 object.objectId = funcOid;
1025 object.objectSubId = 0;
1027 performDeletion(&object, stmt->behavior);
1031 * Guts of function deletion.
1033 * Note: this is also used for aggregate deletion, since the OIDs of
1034 * both functions and aggregates point to pg_proc.
1037 RemoveFunctionById(Oid funcOid)
1044 * Delete the pg_proc tuple.
1046 relation = heap_open(ProcedureRelationId, RowExclusiveLock);
1048 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1049 if (!HeapTupleIsValid(tup)) /* should not happen */
1050 elog(ERROR, "cache lookup failed for function %u", funcOid);
1052 isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
1054 simple_heap_delete(relation, &tup->t_self);
1056 ReleaseSysCache(tup);
1058 heap_close(relation, RowExclusiveLock);
1061 * If there's a pg_aggregate tuple, delete that too.
1065 relation = heap_open(AggregateRelationId, RowExclusiveLock);
1067 tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1068 if (!HeapTupleIsValid(tup)) /* should not happen */
1069 elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1071 simple_heap_delete(relation, &tup->t_self);
1073 ReleaseSysCache(tup);
1075 heap_close(relation, RowExclusiveLock);
1084 RenameFunction(List *name, List *argtypes, const char *newname)
1089 Form_pg_proc procForm;
1091 AclResult aclresult;
1093 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1095 procOid = LookupFuncNameTypeNames(name, argtypes, false);
1097 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid));
1098 if (!HeapTupleIsValid(tup)) /* should not happen */
1099 elog(ERROR, "cache lookup failed for function %u", procOid);
1100 procForm = (Form_pg_proc) GETSTRUCT(tup);
1102 if (procForm->proisagg)
1104 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1105 errmsg("\"%s\" is an aggregate function",
1106 NameListToString(name)),
1107 errhint("Use ALTER AGGREGATE to rename aggregate functions.")));
1109 namespaceOid = procForm->pronamespace;
1111 /* make sure the new name doesn't exist */
1112 if (SearchSysCacheExists3(PROCNAMEARGSNSP,
1113 CStringGetDatum(newname),
1114 PointerGetDatum(&procForm->proargtypes),
1115 ObjectIdGetDatum(namespaceOid)))
1118 (errcode(ERRCODE_DUPLICATE_FUNCTION),
1119 errmsg("function %s already exists in schema \"%s\"",
1120 funcname_signature_string(newname,
1123 procForm->proargtypes.values),
1124 get_namespace_name(namespaceOid))));
1128 if (!pg_proc_ownercheck(procOid, GetUserId()))
1129 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1130 NameListToString(name));
1132 /* must have CREATE privilege on namespace */
1133 aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
1134 if (aclresult != ACLCHECK_OK)
1135 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1136 get_namespace_name(namespaceOid));
1139 namestrcpy(&(procForm->proname), newname);
1140 simple_heap_update(rel, &tup->t_self, tup);
1141 CatalogUpdateIndexes(rel, tup);
1143 heap_close(rel, NoLock);
1144 heap_freetuple(tup);
1148 * Change function owner by name and args
1151 AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
1157 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1159 procOid = LookupFuncNameTypeNames(name, argtypes, false);
1161 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
1162 if (!HeapTupleIsValid(tup)) /* should not happen */
1163 elog(ERROR, "cache lookup failed for function %u", procOid);
1165 if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
1167 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1168 errmsg("\"%s\" is an aggregate function",
1169 NameListToString(name)),
1170 errhint("Use ALTER AGGREGATE to change owner of aggregate functions.")));
1172 AlterFunctionOwner_internal(rel, tup, newOwnerId);
1174 heap_close(rel, NoLock);
1178 * Change function owner by Oid
1181 AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId)
1186 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1188 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
1189 if (!HeapTupleIsValid(tup)) /* should not happen */
1190 elog(ERROR, "cache lookup failed for function %u", procOid);
1191 AlterFunctionOwner_internal(rel, tup, newOwnerId);
1193 heap_close(rel, NoLock);
1197 AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
1199 Form_pg_proc procForm;
1200 AclResult aclresult;
1203 Assert(RelationGetRelid(rel) == ProcedureRelationId);
1204 Assert(tup->t_tableOid == ProcedureRelationId);
1206 procForm = (Form_pg_proc) GETSTRUCT(tup);
1207 procOid = HeapTupleGetOid(tup);
1210 * If the new owner is the same as the existing owner, consider the
1211 * command to have succeeded. This is for dump restoration purposes.
1213 if (procForm->proowner != newOwnerId)
1215 Datum repl_val[Natts_pg_proc];
1216 bool repl_null[Natts_pg_proc];
1217 bool repl_repl[Natts_pg_proc];
1223 /* Superusers can always do it */
1226 /* Otherwise, must be owner of the existing object */
1227 if (!pg_proc_ownercheck(procOid, GetUserId()))
1228 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1229 NameStr(procForm->proname));
1231 /* Must be able to become new owner */
1232 check_is_member_of_role(GetUserId(), newOwnerId);
1234 /* New owner must have CREATE privilege on namespace */
1235 aclresult = pg_namespace_aclcheck(procForm->pronamespace,
1238 if (aclresult != ACLCHECK_OK)
1239 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1240 get_namespace_name(procForm->pronamespace));
1243 memset(repl_null, false, sizeof(repl_null));
1244 memset(repl_repl, false, sizeof(repl_repl));
1246 repl_repl[Anum_pg_proc_proowner - 1] = true;
1247 repl_val[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(newOwnerId);
1250 * Determine the modified ACL for the new owner. This is only
1251 * necessary when the ACL is non-null.
1253 aclDatum = SysCacheGetAttr(PROCOID, tup,
1254 Anum_pg_proc_proacl,
1258 newAcl = aclnewowner(DatumGetAclP(aclDatum),
1259 procForm->proowner, newOwnerId);
1260 repl_repl[Anum_pg_proc_proacl - 1] = true;
1261 repl_val[Anum_pg_proc_proacl - 1] = PointerGetDatum(newAcl);
1264 newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val,
1265 repl_null, repl_repl);
1267 simple_heap_update(rel, &newtuple->t_self, newtuple);
1268 CatalogUpdateIndexes(rel, newtuple);
1270 heap_freetuple(newtuple);
1272 /* Update owner dependency reference */
1273 changeDependencyOnOwner(ProcedureRelationId, procOid, newOwnerId);
1276 ReleaseSysCache(tup);
1280 * Implements the ALTER FUNCTION utility command (except for the
1281 * RENAME and OWNER clauses, which are handled as part of the generic
1285 AlterFunction(AlterFunctionStmt *stmt)
1289 Form_pg_proc procForm;
1292 DefElem *volatility_item = NULL;
1293 DefElem *strict_item = NULL;
1294 DefElem *security_def_item = NULL;
1295 List *set_items = NIL;
1296 DefElem *cost_item = NULL;
1297 DefElem *rows_item = NULL;
1299 rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1301 funcOid = LookupFuncNameTypeNames(stmt->func->funcname,
1302 stmt->func->funcargs,
1305 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1306 if (!HeapTupleIsValid(tup)) /* should not happen */
1307 elog(ERROR, "cache lookup failed for function %u", funcOid);
1309 procForm = (Form_pg_proc) GETSTRUCT(tup);
1311 /* Permission check: must own function */
1312 if (!pg_proc_ownercheck(funcOid, GetUserId()))
1313 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1314 NameListToString(stmt->func->funcname));
1316 if (procForm->proisagg)
1318 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1319 errmsg("\"%s\" is an aggregate function",
1320 NameListToString(stmt->func->funcname))));
1322 /* Examine requested actions. */
1323 foreach(l, stmt->actions)
1325 DefElem *defel = (DefElem *) lfirst(l);
1327 if (compute_common_attribute(defel,
1333 &rows_item) == false)
1334 elog(ERROR, "option \"%s\" not recognized", defel->defname);
1337 if (volatility_item)
1338 procForm->provolatile = interpret_func_volatility(volatility_item);
1340 procForm->proisstrict = intVal(strict_item->arg);
1341 if (security_def_item)
1342 procForm->prosecdef = intVal(security_def_item->arg);
1345 procForm->procost = defGetNumeric(cost_item);
1346 if (procForm->procost <= 0)
1348 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1349 errmsg("COST must be positive")));
1353 procForm->prorows = defGetNumeric(rows_item);
1354 if (procForm->prorows <= 0)
1356 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1357 errmsg("ROWS must be positive")));
1358 if (!procForm->proretset)
1360 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1361 errmsg("ROWS is not applicable when function does not return a set")));
1368 Datum repl_val[Natts_pg_proc];
1369 bool repl_null[Natts_pg_proc];
1370 bool repl_repl[Natts_pg_proc];
1372 /* extract existing proconfig setting */
1373 datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1374 a = isnull ? NULL : DatumGetArrayTypeP(datum);
1376 /* update according to each SET or RESET item, left to right */
1377 a = update_proconfig_value(a, set_items);
1379 /* update the tuple */
1380 memset(repl_repl, false, sizeof(repl_repl));
1381 repl_repl[Anum_pg_proc_proconfig - 1] = true;
1385 repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1386 repl_null[Anum_pg_proc_proconfig - 1] = true;
1390 repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1391 repl_null[Anum_pg_proc_proconfig - 1] = false;
1394 tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1395 repl_val, repl_null, repl_repl);
1399 simple_heap_update(rel, &tup->t_self, tup);
1400 CatalogUpdateIndexes(rel, tup);
1402 heap_close(rel, NoLock);
1403 heap_freetuple(tup);
1407 * SetFunctionReturnType - change declared return type of a function
1409 * This is presently only used for adjusting legacy functions that return
1410 * OPAQUE to return whatever we find their correct definition should be.
1411 * The caller should emit a suitable warning explaining what we did.
1414 SetFunctionReturnType(Oid funcOid, Oid newRetType)
1416 Relation pg_proc_rel;
1418 Form_pg_proc procForm;
1420 pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1422 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1423 if (!HeapTupleIsValid(tup)) /* should not happen */
1424 elog(ERROR, "cache lookup failed for function %u", funcOid);
1425 procForm = (Form_pg_proc) GETSTRUCT(tup);
1427 if (procForm->prorettype != OPAQUEOID) /* caller messed up */
1428 elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
1430 /* okay to overwrite copied tuple */
1431 procForm->prorettype = newRetType;
1433 /* update the catalog and its indexes */
1434 simple_heap_update(pg_proc_rel, &tup->t_self, tup);
1436 CatalogUpdateIndexes(pg_proc_rel, tup);
1438 heap_close(pg_proc_rel, RowExclusiveLock);
1443 * SetFunctionArgType - change declared argument type of a function
1445 * As above, but change an argument's type.
1448 SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
1450 Relation pg_proc_rel;
1452 Form_pg_proc procForm;
1454 pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
1456 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1457 if (!HeapTupleIsValid(tup)) /* should not happen */
1458 elog(ERROR, "cache lookup failed for function %u", funcOid);
1459 procForm = (Form_pg_proc) GETSTRUCT(tup);
1461 if (argIndex < 0 || argIndex >= procForm->pronargs ||
1462 procForm->proargtypes.values[argIndex] != OPAQUEOID)
1463 elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
1465 /* okay to overwrite copied tuple */
1466 procForm->proargtypes.values[argIndex] = newArgType;
1468 /* update the catalog and its indexes */
1469 simple_heap_update(pg_proc_rel, &tup->t_self, tup);
1471 CatalogUpdateIndexes(pg_proc_rel, tup);
1473 heap_close(pg_proc_rel, RowExclusiveLock);
1482 CreateCast(CreateCastStmt *stmt)
1494 Datum values[Natts_pg_cast];
1495 bool nulls[Natts_pg_cast];
1496 ObjectAddress myself,
1499 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
1500 targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
1501 sourcetyptype = get_typtype(sourcetypeid);
1502 targettyptype = get_typtype(targettypeid);
1504 /* No pseudo-types allowed */
1505 if (sourcetyptype == TYPTYPE_PSEUDO)
1507 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1508 errmsg("source data type %s is a pseudo-type",
1509 TypeNameToString(stmt->sourcetype))));
1511 if (targettyptype == TYPTYPE_PSEUDO)
1513 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1514 errmsg("target data type %s is a pseudo-type",
1515 TypeNameToString(stmt->targettype))));
1517 /* Permission check */
1518 if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1519 && !pg_type_ownercheck(targettypeid, GetUserId()))
1521 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1522 errmsg("must be owner of type %s or type %s",
1523 format_type_be(sourcetypeid),
1524 format_type_be(targettypeid))));
1526 /* Detemine the cast method */
1527 if (stmt->func != NULL)
1528 castmethod = COERCION_METHOD_FUNCTION;
1529 else if (stmt->inout)
1530 castmethod = COERCION_METHOD_INOUT;
1532 castmethod = COERCION_METHOD_BINARY;
1534 if (castmethod == COERCION_METHOD_FUNCTION)
1536 Form_pg_proc procstruct;
1538 funcid = LookupFuncNameTypeNames(stmt->func->funcname,
1539 stmt->func->funcargs,
1542 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1543 if (!HeapTupleIsValid(tuple))
1544 elog(ERROR, "cache lookup failed for function %u", funcid);
1546 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1547 nargs = procstruct->pronargs;
1548 if (nargs < 1 || nargs > 3)
1550 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1551 errmsg("cast function must take one to three arguments")));
1552 if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
1554 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1555 errmsg("argument of cast function must match or be binary-coercible from source data type")));
1556 if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1558 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1559 errmsg("second argument of cast function must be type integer")));
1560 if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1562 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1563 errmsg("third argument of cast function must be type boolean")));
1564 if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
1566 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1567 errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1570 * Restricting the volatility of a cast function may or may not be a
1571 * good idea in the abstract, but it definitely breaks many old
1572 * user-defined types. Disable this check --- tgl 2/1/03
1575 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1577 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1578 errmsg("cast function must not be volatile")));
1580 if (procstruct->proisagg)
1582 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1583 errmsg("cast function must not be an aggregate function")));
1584 if (procstruct->proiswindow)
1586 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1587 errmsg("cast function must not be a window function")));
1588 if (procstruct->proretset)
1590 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1591 errmsg("cast function must not return a set")));
1593 ReleaseSysCache(tuple);
1597 funcid = InvalidOid;
1601 if (castmethod == COERCION_METHOD_BINARY)
1611 * Must be superuser to create binary-compatible casts, since
1612 * erroneous casts can easily crash the backend.
1616 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1617 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1620 * Also, insist that the types match as to size, alignment, and
1621 * pass-by-value attributes; this provides at least a crude check that
1622 * they have similar representations. A pair of types that fail this
1623 * test should certainly not be equated.
1625 get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1626 get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1627 if (typ1len != typ2len ||
1628 typ1byval != typ2byval ||
1629 typ1align != typ2align)
1631 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1632 errmsg("source and target data types are not physically compatible")));
1635 * We know that composite, enum and array types are never binary-
1636 * compatible with each other. They all have OIDs embedded in them.
1638 * Theoretically you could build a user-defined base type that is
1639 * binary-compatible with a composite, enum, or array type. But we
1640 * disallow that too, as in practice such a cast is surely a mistake.
1641 * You can always work around that by writing a cast function.
1643 if (sourcetyptype == TYPTYPE_COMPOSITE ||
1644 targettyptype == TYPTYPE_COMPOSITE)
1646 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1647 errmsg("composite data types are not binary-compatible")));
1649 if (sourcetyptype == TYPTYPE_ENUM ||
1650 targettyptype == TYPTYPE_ENUM)
1652 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1653 errmsg("enum data types are not binary-compatible")));
1655 if (OidIsValid(get_element_type(sourcetypeid)) ||
1656 OidIsValid(get_element_type(targettypeid)))
1658 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1659 errmsg("array data types are not binary-compatible")));
1663 * Allow source and target types to be same only for length coercion
1664 * functions. We assume a multi-arg function does length coercion.
1666 if (sourcetypeid == targettypeid && nargs < 2)
1668 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1669 errmsg("source data type and target data type are the same")));
1671 /* convert CoercionContext enum to char value for castcontext */
1672 switch (stmt->context)
1674 case COERCION_IMPLICIT:
1675 castcontext = COERCION_CODE_IMPLICIT;
1677 case COERCION_ASSIGNMENT:
1678 castcontext = COERCION_CODE_ASSIGNMENT;
1680 case COERCION_EXPLICIT:
1681 castcontext = COERCION_CODE_EXPLICIT;
1684 elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1685 castcontext = 0; /* keep compiler quiet */
1689 relation = heap_open(CastRelationId, RowExclusiveLock);
1692 * Check for duplicate. This is just to give a friendly error message,
1693 * the unique index would catch it anyway (so no need to sweat about race
1696 tuple = SearchSysCache2(CASTSOURCETARGET,
1697 ObjectIdGetDatum(sourcetypeid),
1698 ObjectIdGetDatum(targettypeid));
1699 if (HeapTupleIsValid(tuple))
1701 (errcode(ERRCODE_DUPLICATE_OBJECT),
1702 errmsg("cast from type %s to type %s already exists",
1703 format_type_be(sourcetypeid),
1704 format_type_be(targettypeid))));
1707 values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
1708 values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
1709 values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
1710 values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
1711 values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
1713 MemSet(nulls, false, sizeof(nulls));
1715 tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1717 simple_heap_insert(relation, tuple);
1719 CatalogUpdateIndexes(relation, tuple);
1721 /* make dependency entries */
1722 myself.classId = CastRelationId;
1723 myself.objectId = HeapTupleGetOid(tuple);
1724 myself.objectSubId = 0;
1726 /* dependency on source type */
1727 referenced.classId = TypeRelationId;
1728 referenced.objectId = sourcetypeid;
1729 referenced.objectSubId = 0;
1730 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1732 /* dependency on target type */
1733 referenced.classId = TypeRelationId;
1734 referenced.objectId = targettypeid;
1735 referenced.objectSubId = 0;
1736 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1738 /* dependency on function */
1739 if (OidIsValid(funcid))
1741 referenced.classId = ProcedureRelationId;
1742 referenced.objectId = funcid;
1743 referenced.objectSubId = 0;
1744 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1747 heap_freetuple(tuple);
1749 heap_close(relation, RowExclusiveLock);
1758 DropCast(DropCastStmt *stmt)
1762 ObjectAddress object;
1764 /* when dropping a cast, the types must exist even if you use IF EXISTS */
1765 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
1766 targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
1768 object.classId = CastRelationId;
1769 object.objectId = get_cast_oid(sourcetypeid, targettypeid,
1771 object.objectSubId = 0;
1773 if (!OidIsValid(object.objectId))
1776 (errmsg("cast from type %s to type %s does not exist, skipping",
1777 format_type_be(sourcetypeid),
1778 format_type_be(targettypeid))));
1782 /* Permission check */
1783 if (!pg_type_ownercheck(sourcetypeid, GetUserId())
1784 && !pg_type_ownercheck(targettypeid, GetUserId()))
1786 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1787 errmsg("must be owner of type %s or type %s",
1788 format_type_be(sourcetypeid),
1789 format_type_be(targettypeid))));
1794 performDeletion(&object, stmt->behavior);
1798 * get_cast_oid - given two type OIDs, look up a cast OID
1800 * If missing_ok is false, throw an error if the cast is not found. If
1801 * true, just return InvalidOid.
1804 get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
1808 oid = GetSysCacheOid2(CASTSOURCETARGET,
1809 ObjectIdGetDatum(sourcetypeid),
1810 ObjectIdGetDatum(targettypeid));
1811 if (!OidIsValid(oid) && !missing_ok)
1813 (errcode(ERRCODE_UNDEFINED_OBJECT),
1814 errmsg("cast from type %s to type %s does not exist",
1815 format_type_be(sourcetypeid),
1816 format_type_be(targettypeid))));
1821 DropCastById(Oid castOid)
1824 ScanKeyData scankey;
1828 relation = heap_open(CastRelationId, RowExclusiveLock);
1830 ScanKeyInit(&scankey,
1831 ObjectIdAttributeNumber,
1832 BTEqualStrategyNumber, F_OIDEQ,
1833 ObjectIdGetDatum(castOid));
1834 scan = systable_beginscan(relation, CastOidIndexId, true,
1835 SnapshotNow, 1, &scankey);
1837 tuple = systable_getnext(scan);
1838 if (!HeapTupleIsValid(tuple))
1839 elog(ERROR, "could not find tuple for cast %u", castOid);
1840 simple_heap_delete(relation, &tuple->t_self);
1842 systable_endscan(scan);
1843 heap_close(relation, RowExclusiveLock);
1847 * Execute ALTER FUNCTION/AGGREGATE SET SCHEMA
1849 * These commands are identical except for the lookup procedure, so share code.
1852 AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
1853 const char *newschema)
1862 procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
1864 /* get function OID */
1866 procOid = LookupAggNameTypeNames(name, argtypes, false);
1868 procOid = LookupFuncNameTypeNames(name, argtypes, false);
1870 /* check permissions on function */
1871 if (!pg_proc_ownercheck(procOid, GetUserId()))
1872 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
1873 NameListToString(name));
1875 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid));
1876 if (!HeapTupleIsValid(tup))
1877 elog(ERROR, "cache lookup failed for function %u", procOid);
1878 proc = (Form_pg_proc) GETSTRUCT(tup);
1880 oldNspOid = proc->pronamespace;
1882 /* get schema OID and check its permissions */
1883 nspOid = LookupCreationNamespace(newschema);
1885 if (oldNspOid == nspOid)
1887 (errcode(ERRCODE_DUPLICATE_FUNCTION),
1888 errmsg("function \"%s\" is already in schema \"%s\"",
1889 NameListToString(name),
1892 /* disallow renaming into or out of temp schemas */
1893 if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
1895 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1896 errmsg("cannot move objects into or out of temporary schemas")));
1898 /* same for TOAST schema */
1899 if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
1901 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1902 errmsg("cannot move objects into or out of TOAST schema")));
1904 /* check for duplicate name (more friendly than unique-index failure) */
1905 if (SearchSysCacheExists3(PROCNAMEARGSNSP,
1906 CStringGetDatum(NameStr(proc->proname)),
1907 PointerGetDatum(&proc->proargtypes),
1908 ObjectIdGetDatum(nspOid)))
1910 (errcode(ERRCODE_DUPLICATE_FUNCTION),
1911 errmsg("function \"%s\" already exists in schema \"%s\"",
1912 NameStr(proc->proname),
1915 /* OK, modify the pg_proc row */
1917 /* tup is a copy, so we can scribble directly on it */
1918 proc->pronamespace = nspOid;
1920 simple_heap_update(procRel, &tup->t_self, tup);
1921 CatalogUpdateIndexes(procRel, tup);
1923 /* Update dependency on schema */
1924 if (changeDependencyFor(ProcedureRelationId, procOid,
1925 NamespaceRelationId, oldNspOid, nspOid) != 1)
1926 elog(ERROR, "failed to change schema dependency for function \"%s\"",
1927 NameListToString(name));
1929 heap_freetuple(tup);
1931 heap_close(procRel, RowExclusiveLock);
1937 * Execute inline procedural-language code
1940 ExecuteDoStmt(DoStmt *stmt)
1942 InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
1944 DefElem *as_item = NULL;
1945 DefElem *language_item = NULL;
1949 HeapTuple languageTuple;
1950 Form_pg_language languageStruct;
1952 /* Process options we got from gram.y */
1953 foreach(arg, stmt->args)
1955 DefElem *defel = (DefElem *) lfirst(arg);
1957 if (strcmp(defel->defname, "as") == 0)
1961 (errcode(ERRCODE_SYNTAX_ERROR),
1962 errmsg("conflicting or redundant options")));
1965 else if (strcmp(defel->defname, "language") == 0)
1969 (errcode(ERRCODE_SYNTAX_ERROR),
1970 errmsg("conflicting or redundant options")));
1971 language_item = defel;
1974 elog(ERROR, "option \"%s\" not recognized",
1979 codeblock->source_text = strVal(as_item->arg);
1982 (errcode(ERRCODE_SYNTAX_ERROR),
1983 errmsg("no inline code specified")));
1985 /* if LANGUAGE option wasn't specified, use the default */
1987 language = strVal(language_item->arg);
1989 language = "plpgsql";
1991 /* Convert language name to canonical case */
1992 languageName = case_translate_language_name(language);
1994 /* Look up the language and validate permissions */
1995 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(languageName));
1996 if (!HeapTupleIsValid(languageTuple))
1998 (errcode(ERRCODE_UNDEFINED_OBJECT),
1999 errmsg("language \"%s\" does not exist", languageName),
2000 (PLTemplateExists(languageName) ?
2001 errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
2003 codeblock->langOid = HeapTupleGetOid(languageTuple);
2004 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2005 codeblock->langIsTrusted = languageStruct->lanpltrusted;
2007 if (languageStruct->lanpltrusted)
2009 /* if trusted language, need USAGE privilege */
2010 AclResult aclresult;
2012 aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
2014 if (aclresult != ACLCHECK_OK)
2015 aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
2016 NameStr(languageStruct->lanname));
2020 /* if untrusted language, must be superuser */
2022 aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
2023 NameStr(languageStruct->lanname));
2026 /* get the handler function's OID */
2027 laninline = languageStruct->laninline;
2028 if (!OidIsValid(laninline))
2030 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2031 errmsg("language \"%s\" does not support inline code execution",
2032 NameStr(languageStruct->lanname))));
2034 ReleaseSysCache(languageTuple);
2036 /* execute the inline handler */
2037 OidFunctionCall1(laninline, PointerGetDatum(codeblock));