Fix handling of polymorphic output arguments for procedures.
[pgsql.git] / src / backend / commands / functioncmds.c
blob6593fd7d811521a236cdf831886610738bd8aa98
1 /*-------------------------------------------------------------------------
3 * functioncmds.c
5 * Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
6 * CAST commands.
8 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
12 * IDENTIFICATION
13 * src/backend/commands/functioncmds.c
15 * DESCRIPTION
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.
22 * NOTES
23 * These things must be defined and committed in the following order:
24 * "create function":
25 * input/output, recv/send procedures
26 * "create type":
27 * type
28 * "create operator":
29 * operators
31 *-------------------------------------------------------------------------
33 #include "postgres.h"
35 #include "access/htup_details.h"
36 #include "access/table.h"
37 #include "catalog/catalog.h"
38 #include "catalog/dependency.h"
39 #include "catalog/indexing.h"
40 #include "catalog/objectaccess.h"
41 #include "catalog/pg_aggregate.h"
42 #include "catalog/pg_cast.h"
43 #include "catalog/pg_language.h"
44 #include "catalog/pg_namespace.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_transform.h"
47 #include "catalog/pg_type.h"
48 #include "commands/defrem.h"
49 #include "commands/extension.h"
50 #include "commands/proclang.h"
51 #include "executor/executor.h"
52 #include "executor/functions.h"
53 #include "funcapi.h"
54 #include "miscadmin.h"
55 #include "nodes/nodeFuncs.h"
56 #include "optimizer/optimizer.h"
57 #include "parser/analyze.h"
58 #include "parser/parse_coerce.h"
59 #include "parser/parse_collate.h"
60 #include "parser/parse_expr.h"
61 #include "parser/parse_func.h"
62 #include "parser/parse_type.h"
63 #include "pgstat.h"
64 #include "tcop/pquery.h"
65 #include "tcop/utility.h"
66 #include "utils/acl.h"
67 #include "utils/builtins.h"
68 #include "utils/guc.h"
69 #include "utils/lsyscache.h"
70 #include "utils/rel.h"
71 #include "utils/snapmgr.h"
72 #include "utils/syscache.h"
73 #include "utils/typcache.h"
76 * Examine the RETURNS clause of the CREATE FUNCTION statement
77 * and return information about it as *prorettype_p and *returnsSet.
79 * This is more complex than the average typename lookup because we want to
80 * allow a shell type to be used, or even created if the specified return type
81 * doesn't exist yet. (Without this, there's no way to define the I/O procs
82 * for a new type.) But SQL function creation won't cope, so error out if
83 * the target language is SQL. (We do this here, not in the SQL-function
84 * validator, so as not to produce a NOTICE and then an ERROR for the same
85 * condition.)
87 static void
88 compute_return_type(TypeName *returnType, Oid languageOid,
89 Oid *prorettype_p, bool *returnsSet_p)
91 Oid rettype;
92 Type typtup;
93 AclResult aclresult;
95 typtup = LookupTypeName(NULL, returnType, NULL, false);
97 if (typtup)
99 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
101 if (languageOid == SQLlanguageId)
102 ereport(ERROR,
103 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
104 errmsg("SQL function cannot return shell type %s",
105 TypeNameToString(returnType))));
106 else
107 ereport(NOTICE,
108 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
109 errmsg("return type %s is only a shell",
110 TypeNameToString(returnType))));
112 rettype = typeTypeId(typtup);
113 ReleaseSysCache(typtup);
115 else
117 char *typnam = TypeNameToString(returnType);
118 Oid namespaceId;
119 char *typname;
120 ObjectAddress address;
123 * Only C-coded functions can be I/O functions. We enforce this
124 * restriction here mainly to prevent littering the catalogs with
125 * shell types due to simple typos in user-defined function
126 * definitions.
128 if (languageOid != INTERNALlanguageId &&
129 languageOid != ClanguageId)
130 ereport(ERROR,
131 (errcode(ERRCODE_UNDEFINED_OBJECT),
132 errmsg("type \"%s\" does not exist", typnam)));
134 /* Reject if there's typmod decoration, too */
135 if (returnType->typmods != NIL)
136 ereport(ERROR,
137 (errcode(ERRCODE_SYNTAX_ERROR),
138 errmsg("type modifier cannot be specified for shell type \"%s\"",
139 typnam)));
141 /* Otherwise, go ahead and make a shell type */
142 ereport(NOTICE,
143 (errcode(ERRCODE_UNDEFINED_OBJECT),
144 errmsg("type \"%s\" is not yet defined", typnam),
145 errdetail("Creating a shell type definition.")));
146 namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
147 &typname);
148 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(),
149 ACL_CREATE);
150 if (aclresult != ACLCHECK_OK)
151 aclcheck_error(aclresult, OBJECT_SCHEMA,
152 get_namespace_name(namespaceId));
153 address = TypeShellMake(typname, namespaceId, GetUserId());
154 rettype = address.objectId;
155 Assert(OidIsValid(rettype));
158 aclresult = object_aclcheck(TypeRelationId, rettype, GetUserId(), ACL_USAGE);
159 if (aclresult != ACLCHECK_OK)
160 aclcheck_error_type(aclresult, rettype);
162 *prorettype_p = rettype;
163 *returnsSet_p = returnType->setof;
167 * Interpret the function parameter list of a CREATE FUNCTION,
168 * CREATE PROCEDURE, or CREATE AGGREGATE statement.
170 * Input parameters:
171 * parameters: list of FunctionParameter structs
172 * languageOid: OID of function language (InvalidOid if it's CREATE AGGREGATE)
173 * objtype: identifies type of object being created
175 * Results are stored into output parameters. parameterTypes must always
176 * be created, but the other arrays/lists can be NULL pointers if not needed.
177 * variadicArgType is set to the variadic array type if there's a VARIADIC
178 * parameter (there can be only one); or to InvalidOid if not.
179 * requiredResultType is set to InvalidOid if there are no OUT parameters,
180 * else it is set to the OID of the implied result type.
182 void
183 interpret_function_parameter_list(ParseState *pstate,
184 List *parameters,
185 Oid languageOid,
186 ObjectType objtype,
187 oidvector **parameterTypes,
188 List **parameterTypes_list,
189 ArrayType **allParameterTypes,
190 ArrayType **parameterModes,
191 ArrayType **parameterNames,
192 List **inParameterNames_list,
193 List **parameterDefaults,
194 Oid *variadicArgType,
195 Oid *requiredResultType)
197 int parameterCount = list_length(parameters);
198 Oid *inTypes;
199 int inCount = 0;
200 Datum *allTypes;
201 Datum *paramModes;
202 Datum *paramNames;
203 int outCount = 0;
204 int varCount = 0;
205 bool have_names = false;
206 bool have_defaults = false;
207 ListCell *x;
208 int i;
210 *variadicArgType = InvalidOid; /* default result */
211 *requiredResultType = InvalidOid; /* default result */
213 inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
214 allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
215 paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
216 paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
217 *parameterDefaults = NIL;
219 /* Scan the list and extract data into work arrays */
220 i = 0;
221 foreach(x, parameters)
223 FunctionParameter *fp = (FunctionParameter *) lfirst(x);
224 TypeName *t = fp->argType;
225 FunctionParameterMode fpmode = fp->mode;
226 bool isinput = false;
227 Oid toid;
228 Type typtup;
229 AclResult aclresult;
231 /* For our purposes here, a defaulted mode spec is identical to IN */
232 if (fpmode == FUNC_PARAM_DEFAULT)
233 fpmode = FUNC_PARAM_IN;
235 typtup = LookupTypeName(NULL, t, NULL, false);
236 if (typtup)
238 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
240 /* As above, hard error if language is SQL */
241 if (languageOid == SQLlanguageId)
242 ereport(ERROR,
243 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
244 errmsg("SQL function cannot accept shell type %s",
245 TypeNameToString(t))));
246 /* We don't allow creating aggregates on shell types either */
247 else if (objtype == OBJECT_AGGREGATE)
248 ereport(ERROR,
249 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
250 errmsg("aggregate cannot accept shell type %s",
251 TypeNameToString(t))));
252 else
253 ereport(NOTICE,
254 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
255 errmsg("argument type %s is only a shell",
256 TypeNameToString(t))));
258 toid = typeTypeId(typtup);
259 ReleaseSysCache(typtup);
261 else
263 ereport(ERROR,
264 (errcode(ERRCODE_UNDEFINED_OBJECT),
265 errmsg("type %s does not exist",
266 TypeNameToString(t))));
267 toid = InvalidOid; /* keep compiler quiet */
270 aclresult = object_aclcheck(TypeRelationId, toid, GetUserId(), ACL_USAGE);
271 if (aclresult != ACLCHECK_OK)
272 aclcheck_error_type(aclresult, toid);
274 if (t->setof)
276 if (objtype == OBJECT_AGGREGATE)
277 ereport(ERROR,
278 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
279 errmsg("aggregates cannot accept set arguments")));
280 else if (objtype == OBJECT_PROCEDURE)
281 ereport(ERROR,
282 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
283 errmsg("procedures cannot accept set arguments")));
284 else
285 ereport(ERROR,
286 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
287 errmsg("functions cannot accept set arguments")));
290 /* handle input parameters */
291 if (fpmode != FUNC_PARAM_OUT && fpmode != FUNC_PARAM_TABLE)
293 /* other input parameters can't follow a VARIADIC parameter */
294 if (varCount > 0)
295 ereport(ERROR,
296 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
297 errmsg("VARIADIC parameter must be the last input parameter")));
298 inTypes[inCount++] = toid;
299 isinput = true;
300 if (parameterTypes_list)
301 *parameterTypes_list = lappend_oid(*parameterTypes_list, toid);
304 /* handle output parameters */
305 if (fpmode != FUNC_PARAM_IN && fpmode != FUNC_PARAM_VARIADIC)
307 if (objtype == OBJECT_PROCEDURE)
310 * We disallow OUT-after-VARIADIC only for procedures. While
311 * such a case causes no confusion in ordinary function calls,
312 * it would cause confusion in a CALL statement.
314 if (varCount > 0)
315 ereport(ERROR,
316 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
317 errmsg("VARIADIC parameter must be the last parameter")));
318 /* Procedures with output parameters always return RECORD */
319 *requiredResultType = RECORDOID;
321 else if (outCount == 0) /* save first output param's type */
322 *requiredResultType = toid;
323 outCount++;
326 if (fpmode == FUNC_PARAM_VARIADIC)
328 *variadicArgType = toid;
329 varCount++;
330 /* validate variadic parameter type */
331 switch (toid)
333 case ANYARRAYOID:
334 case ANYCOMPATIBLEARRAYOID:
335 case ANYOID:
336 /* okay */
337 break;
338 default:
339 if (!OidIsValid(get_element_type(toid)))
340 ereport(ERROR,
341 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
342 errmsg("VARIADIC parameter must be an array")));
343 break;
347 allTypes[i] = ObjectIdGetDatum(toid);
349 paramModes[i] = CharGetDatum(fpmode);
351 if (fp->name && fp->name[0])
353 ListCell *px;
356 * As of Postgres 9.0 we disallow using the same name for two
357 * input or two output function parameters. Depending on the
358 * function's language, conflicting input and output names might
359 * be bad too, but we leave it to the PL to complain if so.
361 foreach(px, parameters)
363 FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
364 FunctionParameterMode prevfpmode;
366 if (prevfp == fp)
367 break;
368 /* as above, default mode is IN */
369 prevfpmode = prevfp->mode;
370 if (prevfpmode == FUNC_PARAM_DEFAULT)
371 prevfpmode = FUNC_PARAM_IN;
372 /* pure in doesn't conflict with pure out */
373 if ((fpmode == FUNC_PARAM_IN ||
374 fpmode == FUNC_PARAM_VARIADIC) &&
375 (prevfpmode == FUNC_PARAM_OUT ||
376 prevfpmode == FUNC_PARAM_TABLE))
377 continue;
378 if ((prevfpmode == FUNC_PARAM_IN ||
379 prevfpmode == FUNC_PARAM_VARIADIC) &&
380 (fpmode == FUNC_PARAM_OUT ||
381 fpmode == FUNC_PARAM_TABLE))
382 continue;
383 if (prevfp->name && prevfp->name[0] &&
384 strcmp(prevfp->name, fp->name) == 0)
385 ereport(ERROR,
386 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
387 errmsg("parameter name \"%s\" used more than once",
388 fp->name)));
391 paramNames[i] = CStringGetTextDatum(fp->name);
392 have_names = true;
395 if (inParameterNames_list)
396 *inParameterNames_list = lappend(*inParameterNames_list, makeString(fp->name ? fp->name : pstrdup("")));
398 if (fp->defexpr)
400 Node *def;
402 if (!isinput)
403 ereport(ERROR,
404 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
405 errmsg("only input parameters can have default values")));
407 def = transformExpr(pstate, fp->defexpr,
408 EXPR_KIND_FUNCTION_DEFAULT);
409 def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
410 assign_expr_collations(pstate, def);
413 * Make sure no variables are referred to (this is probably dead
414 * code now that add_missing_from is history).
416 if (pstate->p_rtable != NIL ||
417 contain_var_clause(def))
418 ereport(ERROR,
419 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
420 errmsg("cannot use table references in parameter default value")));
423 * transformExpr() should have already rejected subqueries,
424 * aggregates, and window functions, based on the EXPR_KIND_ for a
425 * default expression.
427 * It can't return a set either --- but coerce_to_specific_type
428 * already checked that for us.
430 * Note: the point of these restrictions is to ensure that an
431 * expression that, on its face, hasn't got subplans, aggregates,
432 * etc cannot suddenly have them after function default arguments
433 * are inserted.
436 *parameterDefaults = lappend(*parameterDefaults, def);
437 have_defaults = true;
439 else
441 if (isinput && have_defaults)
442 ereport(ERROR,
443 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
444 errmsg("input parameters after one with a default value must also have defaults")));
447 * For procedures, we also can't allow OUT parameters after one
448 * with a default, because the same sort of confusion arises in a
449 * CALL statement.
451 if (objtype == OBJECT_PROCEDURE && have_defaults)
452 ereport(ERROR,
453 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
454 errmsg("procedure OUT parameters cannot appear after one with a default value")));
457 i++;
460 /* Now construct the proper outputs as needed */
461 *parameterTypes = buildoidvector(inTypes, inCount);
463 if (outCount > 0 || varCount > 0)
465 *allParameterTypes = construct_array_builtin(allTypes, parameterCount, OIDOID);
466 *parameterModes = construct_array_builtin(paramModes, parameterCount, CHAROID);
467 if (outCount > 1)
468 *requiredResultType = RECORDOID;
469 /* otherwise we set requiredResultType correctly above */
471 else
473 *allParameterTypes = NULL;
474 *parameterModes = NULL;
477 if (have_names)
479 for (i = 0; i < parameterCount; i++)
481 if (paramNames[i] == PointerGetDatum(NULL))
482 paramNames[i] = CStringGetTextDatum("");
484 *parameterNames = construct_array_builtin(paramNames, parameterCount, TEXTOID);
486 else
487 *parameterNames = NULL;
492 * Recognize one of the options that can be passed to both CREATE
493 * FUNCTION and ALTER FUNCTION and return it via one of the out
494 * parameters. Returns true if the passed option was recognized. If
495 * the out parameter we were going to assign to points to non-NULL,
496 * raise a duplicate-clause error. (We don't try to detect duplicate
497 * SET parameters though --- if you're redundant, the last one wins.)
499 static bool
500 compute_common_attribute(ParseState *pstate,
501 bool is_procedure,
502 DefElem *defel,
503 DefElem **volatility_item,
504 DefElem **strict_item,
505 DefElem **security_item,
506 DefElem **leakproof_item,
507 List **set_items,
508 DefElem **cost_item,
509 DefElem **rows_item,
510 DefElem **support_item,
511 DefElem **parallel_item)
513 if (strcmp(defel->defname, "volatility") == 0)
515 if (is_procedure)
516 goto procedure_error;
517 if (*volatility_item)
518 errorConflictingDefElem(defel, pstate);
520 *volatility_item = defel;
522 else if (strcmp(defel->defname, "strict") == 0)
524 if (is_procedure)
525 goto procedure_error;
526 if (*strict_item)
527 errorConflictingDefElem(defel, pstate);
529 *strict_item = defel;
531 else if (strcmp(defel->defname, "security") == 0)
533 if (*security_item)
534 errorConflictingDefElem(defel, pstate);
536 *security_item = defel;
538 else if (strcmp(defel->defname, "leakproof") == 0)
540 if (is_procedure)
541 goto procedure_error;
542 if (*leakproof_item)
543 errorConflictingDefElem(defel, pstate);
545 *leakproof_item = defel;
547 else if (strcmp(defel->defname, "set") == 0)
549 *set_items = lappend(*set_items, defel->arg);
551 else if (strcmp(defel->defname, "cost") == 0)
553 if (is_procedure)
554 goto procedure_error;
555 if (*cost_item)
556 errorConflictingDefElem(defel, pstate);
558 *cost_item = defel;
560 else if (strcmp(defel->defname, "rows") == 0)
562 if (is_procedure)
563 goto procedure_error;
564 if (*rows_item)
565 errorConflictingDefElem(defel, pstate);
567 *rows_item = defel;
569 else if (strcmp(defel->defname, "support") == 0)
571 if (is_procedure)
572 goto procedure_error;
573 if (*support_item)
574 errorConflictingDefElem(defel, pstate);
576 *support_item = defel;
578 else if (strcmp(defel->defname, "parallel") == 0)
580 if (is_procedure)
581 goto procedure_error;
582 if (*parallel_item)
583 errorConflictingDefElem(defel, pstate);
585 *parallel_item = defel;
587 else
588 return false;
590 /* Recognized an option */
591 return true;
593 procedure_error:
594 ereport(ERROR,
595 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
596 errmsg("invalid attribute in procedure definition"),
597 parser_errposition(pstate, defel->location)));
598 return false;
601 static char
602 interpret_func_volatility(DefElem *defel)
604 char *str = strVal(defel->arg);
606 if (strcmp(str, "immutable") == 0)
607 return PROVOLATILE_IMMUTABLE;
608 else if (strcmp(str, "stable") == 0)
609 return PROVOLATILE_STABLE;
610 else if (strcmp(str, "volatile") == 0)
611 return PROVOLATILE_VOLATILE;
612 else
614 elog(ERROR, "invalid volatility \"%s\"", str);
615 return 0; /* keep compiler quiet */
619 static char
620 interpret_func_parallel(DefElem *defel)
622 char *str = strVal(defel->arg);
624 if (strcmp(str, "safe") == 0)
625 return PROPARALLEL_SAFE;
626 else if (strcmp(str, "unsafe") == 0)
627 return PROPARALLEL_UNSAFE;
628 else if (strcmp(str, "restricted") == 0)
629 return PROPARALLEL_RESTRICTED;
630 else
632 ereport(ERROR,
633 (errcode(ERRCODE_SYNTAX_ERROR),
634 errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
635 return PROPARALLEL_UNSAFE; /* keep compiler quiet */
640 * Update a proconfig value according to a list of VariableSetStmt items.
642 * The input and result may be NULL to signify a null entry.
644 static ArrayType *
645 update_proconfig_value(ArrayType *a, List *set_items)
647 ListCell *l;
649 foreach(l, set_items)
651 VariableSetStmt *sstmt = lfirst_node(VariableSetStmt, l);
653 if (sstmt->kind == VAR_RESET_ALL)
654 a = NULL;
655 else
657 char *valuestr = ExtractSetVariableArgs(sstmt);
659 if (valuestr)
660 a = GUCArrayAdd(a, sstmt->name, valuestr);
661 else /* RESET */
662 a = GUCArrayDelete(a, sstmt->name);
666 return a;
669 static Oid
670 interpret_func_support(DefElem *defel)
672 List *procName = defGetQualifiedName(defel);
673 Oid procOid;
674 Oid argList[1];
677 * Support functions always take one INTERNAL argument and return
678 * INTERNAL.
680 argList[0] = INTERNALOID;
682 procOid = LookupFuncName(procName, 1, argList, true);
683 if (!OidIsValid(procOid))
684 ereport(ERROR,
685 (errcode(ERRCODE_UNDEFINED_FUNCTION),
686 errmsg("function %s does not exist",
687 func_signature_string(procName, 1, NIL, argList))));
689 if (get_func_rettype(procOid) != INTERNALOID)
690 ereport(ERROR,
691 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
692 errmsg("support function %s must return type %s",
693 NameListToString(procName), "internal")));
696 * Someday we might want an ACL check here; but for now, we insist that
697 * you be superuser to specify a support function, so privilege on the
698 * support function is moot.
700 if (!superuser())
701 ereport(ERROR,
702 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
703 errmsg("must be superuser to specify a support function")));
705 return procOid;
710 * Dissect the list of options assembled in gram.y into function
711 * attributes.
713 static void
714 compute_function_attributes(ParseState *pstate,
715 bool is_procedure,
716 List *options,
717 List **as,
718 char **language,
719 Node **transform,
720 bool *windowfunc_p,
721 char *volatility_p,
722 bool *strict_p,
723 bool *security_definer,
724 bool *leakproof_p,
725 ArrayType **proconfig,
726 float4 *procost,
727 float4 *prorows,
728 Oid *prosupport,
729 char *parallel_p)
731 ListCell *option;
732 DefElem *as_item = NULL;
733 DefElem *language_item = NULL;
734 DefElem *transform_item = NULL;
735 DefElem *windowfunc_item = NULL;
736 DefElem *volatility_item = NULL;
737 DefElem *strict_item = NULL;
738 DefElem *security_item = NULL;
739 DefElem *leakproof_item = NULL;
740 List *set_items = NIL;
741 DefElem *cost_item = NULL;
742 DefElem *rows_item = NULL;
743 DefElem *support_item = NULL;
744 DefElem *parallel_item = NULL;
746 foreach(option, options)
748 DefElem *defel = (DefElem *) lfirst(option);
750 if (strcmp(defel->defname, "as") == 0)
752 if (as_item)
753 errorConflictingDefElem(defel, pstate);
754 as_item = defel;
756 else if (strcmp(defel->defname, "language") == 0)
758 if (language_item)
759 errorConflictingDefElem(defel, pstate);
760 language_item = defel;
762 else if (strcmp(defel->defname, "transform") == 0)
764 if (transform_item)
765 errorConflictingDefElem(defel, pstate);
766 transform_item = defel;
768 else if (strcmp(defel->defname, "window") == 0)
770 if (windowfunc_item)
771 errorConflictingDefElem(defel, pstate);
772 if (is_procedure)
773 ereport(ERROR,
774 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
775 errmsg("invalid attribute in procedure definition"),
776 parser_errposition(pstate, defel->location)));
777 windowfunc_item = defel;
779 else if (compute_common_attribute(pstate,
780 is_procedure,
781 defel,
782 &volatility_item,
783 &strict_item,
784 &security_item,
785 &leakproof_item,
786 &set_items,
787 &cost_item,
788 &rows_item,
789 &support_item,
790 &parallel_item))
792 /* recognized common option */
793 continue;
795 else
796 elog(ERROR, "option \"%s\" not recognized",
797 defel->defname);
800 if (as_item)
801 *as = (List *) as_item->arg;
802 if (language_item)
803 *language = strVal(language_item->arg);
804 if (transform_item)
805 *transform = transform_item->arg;
806 if (windowfunc_item)
807 *windowfunc_p = boolVal(windowfunc_item->arg);
808 if (volatility_item)
809 *volatility_p = interpret_func_volatility(volatility_item);
810 if (strict_item)
811 *strict_p = boolVal(strict_item->arg);
812 if (security_item)
813 *security_definer = boolVal(security_item->arg);
814 if (leakproof_item)
815 *leakproof_p = boolVal(leakproof_item->arg);
816 if (set_items)
817 *proconfig = update_proconfig_value(NULL, set_items);
818 if (cost_item)
820 *procost = defGetNumeric(cost_item);
821 if (*procost <= 0)
822 ereport(ERROR,
823 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
824 errmsg("COST must be positive")));
826 if (rows_item)
828 *prorows = defGetNumeric(rows_item);
829 if (*prorows <= 0)
830 ereport(ERROR,
831 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
832 errmsg("ROWS must be positive")));
834 if (support_item)
835 *prosupport = interpret_func_support(support_item);
836 if (parallel_item)
837 *parallel_p = interpret_func_parallel(parallel_item);
842 * For a dynamically linked C language object, the form of the clause is
844 * AS <object file name> [, <link symbol name> ]
846 * In all other cases
848 * AS <object reference, or sql code>
850 static void
851 interpret_AS_clause(Oid languageOid, const char *languageName,
852 char *funcname, List *as, Node *sql_body_in,
853 List *parameterTypes, List *inParameterNames,
854 char **prosrc_str_p, char **probin_str_p,
855 Node **sql_body_out,
856 const char *queryString)
858 if (!sql_body_in && !as)
859 ereport(ERROR,
860 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
861 errmsg("no function body specified")));
863 if (sql_body_in && as)
864 ereport(ERROR,
865 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
866 errmsg("duplicate function body specified")));
868 if (sql_body_in && languageOid != SQLlanguageId)
869 ereport(ERROR,
870 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
871 errmsg("inline SQL function body only valid for language SQL")));
873 *sql_body_out = NULL;
875 if (languageOid == ClanguageId)
878 * For "C" language, store the file name in probin and, when given,
879 * the link symbol name in prosrc. If link symbol is omitted,
880 * substitute procedure name. We also allow link symbol to be
881 * specified as "-", since that was the habit in PG versions before
882 * 8.4, and there might be dump files out there that don't translate
883 * that back to "omitted".
885 *probin_str_p = strVal(linitial(as));
886 if (list_length(as) == 1)
887 *prosrc_str_p = funcname;
888 else
890 *prosrc_str_p = strVal(lsecond(as));
891 if (strcmp(*prosrc_str_p, "-") == 0)
892 *prosrc_str_p = funcname;
895 else if (sql_body_in)
897 SQLFunctionParseInfoPtr pinfo;
899 pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
901 pinfo->fname = funcname;
902 pinfo->nargs = list_length(parameterTypes);
903 pinfo->argtypes = (Oid *) palloc(pinfo->nargs * sizeof(Oid));
904 pinfo->argnames = (char **) palloc(pinfo->nargs * sizeof(char *));
905 for (int i = 0; i < list_length(parameterTypes); i++)
907 char *s = strVal(list_nth(inParameterNames, i));
909 pinfo->argtypes[i] = list_nth_oid(parameterTypes, i);
910 if (IsPolymorphicType(pinfo->argtypes[i]))
911 ereport(ERROR,
912 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
913 errmsg("SQL function with unquoted function body cannot have polymorphic arguments")));
915 if (s[0] != '\0')
916 pinfo->argnames[i] = s;
917 else
918 pinfo->argnames[i] = NULL;
921 if (IsA(sql_body_in, List))
923 List *stmts = linitial_node(List, castNode(List, sql_body_in));
924 ListCell *lc;
925 List *transformed_stmts = NIL;
927 foreach(lc, stmts)
929 Node *stmt = lfirst(lc);
930 Query *q;
931 ParseState *pstate = make_parsestate(NULL);
933 pstate->p_sourcetext = queryString;
934 sql_fn_parser_setup(pstate, pinfo);
935 q = transformStmt(pstate, stmt);
936 if (q->commandType == CMD_UTILITY)
937 ereport(ERROR,
938 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
939 errmsg("%s is not yet supported in unquoted SQL function body",
940 GetCommandTagName(CreateCommandTag(q->utilityStmt))));
941 transformed_stmts = lappend(transformed_stmts, q);
942 free_parsestate(pstate);
945 *sql_body_out = (Node *) list_make1(transformed_stmts);
947 else
949 Query *q;
950 ParseState *pstate = make_parsestate(NULL);
952 pstate->p_sourcetext = queryString;
953 sql_fn_parser_setup(pstate, pinfo);
954 q = transformStmt(pstate, sql_body_in);
955 if (q->commandType == CMD_UTILITY)
956 ereport(ERROR,
957 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
958 errmsg("%s is not yet supported in unquoted SQL function body",
959 GetCommandTagName(CreateCommandTag(q->utilityStmt))));
960 free_parsestate(pstate);
962 *sql_body_out = (Node *) q;
966 * We must put something in prosrc. For the moment, just record an
967 * empty string. It might be useful to store the original text of the
968 * CREATE FUNCTION statement --- but to make actual use of that in
969 * error reports, we'd also have to adjust readfuncs.c to not throw
970 * away node location fields when reading prosqlbody.
972 *prosrc_str_p = pstrdup("");
974 /* But we definitely don't need probin. */
975 *probin_str_p = NULL;
977 else
979 /* Everything else wants the given string in prosrc. */
980 *prosrc_str_p = strVal(linitial(as));
981 *probin_str_p = NULL;
983 if (list_length(as) != 1)
984 ereport(ERROR,
985 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
986 errmsg("only one AS item needed for language \"%s\"",
987 languageName)));
989 if (languageOid == INTERNALlanguageId)
992 * In PostgreSQL versions before 6.5, the SQL name of the created
993 * function could not be different from the internal name, and
994 * "prosrc" wasn't used. So there is code out there that does
995 * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
996 * modicum of backwards compatibility, accept an empty "prosrc"
997 * value as meaning the supplied SQL function name.
999 if (strlen(*prosrc_str_p) == 0)
1000 *prosrc_str_p = funcname;
1007 * CreateFunction
1008 * Execute a CREATE FUNCTION (or CREATE PROCEDURE) utility statement.
1010 ObjectAddress
1011 CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
1013 char *probin_str;
1014 char *prosrc_str;
1015 Node *prosqlbody;
1016 Oid prorettype;
1017 bool returnsSet;
1018 char *language;
1019 Oid languageOid;
1020 Oid languageValidator;
1021 Node *transformDefElem = NULL;
1022 char *funcname;
1023 Oid namespaceId;
1024 AclResult aclresult;
1025 oidvector *parameterTypes;
1026 List *parameterTypes_list = NIL;
1027 ArrayType *allParameterTypes;
1028 ArrayType *parameterModes;
1029 ArrayType *parameterNames;
1030 List *inParameterNames_list = NIL;
1031 List *parameterDefaults;
1032 Oid variadicArgType;
1033 List *trftypes_list = NIL;
1034 ArrayType *trftypes;
1035 Oid requiredResultType;
1036 bool isWindowFunc,
1037 isStrict,
1038 security,
1039 isLeakProof;
1040 char volatility;
1041 ArrayType *proconfig;
1042 float4 procost;
1043 float4 prorows;
1044 Oid prosupport;
1045 HeapTuple languageTuple;
1046 Form_pg_language languageStruct;
1047 List *as_clause;
1048 char parallel;
1050 /* Convert list of names to a name and namespace */
1051 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
1052 &funcname);
1054 /* Check we have creation rights in target namespace */
1055 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
1056 if (aclresult != ACLCHECK_OK)
1057 aclcheck_error(aclresult, OBJECT_SCHEMA,
1058 get_namespace_name(namespaceId));
1060 /* Set default attributes */
1061 as_clause = NIL;
1062 language = NULL;
1063 isWindowFunc = false;
1064 isStrict = false;
1065 security = false;
1066 isLeakProof = false;
1067 volatility = PROVOLATILE_VOLATILE;
1068 proconfig = NULL;
1069 procost = -1; /* indicates not set */
1070 prorows = -1; /* indicates not set */
1071 prosupport = InvalidOid;
1072 parallel = PROPARALLEL_UNSAFE;
1074 /* Extract non-default attributes from stmt->options list */
1075 compute_function_attributes(pstate,
1076 stmt->is_procedure,
1077 stmt->options,
1078 &as_clause, &language, &transformDefElem,
1079 &isWindowFunc, &volatility,
1080 &isStrict, &security, &isLeakProof,
1081 &proconfig, &procost, &prorows,
1082 &prosupport, &parallel);
1084 if (!language)
1086 if (stmt->sql_body)
1087 language = "sql";
1088 else
1089 ereport(ERROR,
1090 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1091 errmsg("no language specified")));
1094 /* Look up the language and validate permissions */
1095 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1096 if (!HeapTupleIsValid(languageTuple))
1097 ereport(ERROR,
1098 (errcode(ERRCODE_UNDEFINED_OBJECT),
1099 errmsg("language \"%s\" does not exist", language),
1100 (extension_file_exists(language) ?
1101 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1103 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1104 languageOid = languageStruct->oid;
1106 if (languageStruct->lanpltrusted)
1108 /* if trusted language, need USAGE privilege */
1109 aclresult = object_aclcheck(LanguageRelationId, languageOid, GetUserId(), ACL_USAGE);
1110 if (aclresult != ACLCHECK_OK)
1111 aclcheck_error(aclresult, OBJECT_LANGUAGE,
1112 NameStr(languageStruct->lanname));
1114 else
1116 /* if untrusted language, must be superuser */
1117 if (!superuser())
1118 aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE,
1119 NameStr(languageStruct->lanname));
1122 languageValidator = languageStruct->lanvalidator;
1124 ReleaseSysCache(languageTuple);
1127 * Only superuser is allowed to create leakproof functions because
1128 * leakproof functions can see tuples which have not yet been filtered out
1129 * by security barrier views or row-level security policies.
1131 if (isLeakProof && !superuser())
1132 ereport(ERROR,
1133 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1134 errmsg("only superuser can define a leakproof function")));
1136 if (transformDefElem)
1138 ListCell *lc;
1140 foreach(lc, castNode(List, transformDefElem))
1142 Oid typeid = typenameTypeId(NULL,
1143 lfirst_node(TypeName, lc));
1144 Oid elt = get_base_element_type(typeid);
1146 typeid = elt ? elt : typeid;
1148 get_transform_oid(typeid, languageOid, false);
1149 trftypes_list = lappend_oid(trftypes_list, typeid);
1154 * Convert remaining parameters of CREATE to form wanted by
1155 * ProcedureCreate.
1157 interpret_function_parameter_list(pstate,
1158 stmt->parameters,
1159 languageOid,
1160 stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION,
1161 &parameterTypes,
1162 &parameterTypes_list,
1163 &allParameterTypes,
1164 &parameterModes,
1165 &parameterNames,
1166 &inParameterNames_list,
1167 &parameterDefaults,
1168 &variadicArgType,
1169 &requiredResultType);
1171 if (stmt->is_procedure)
1173 Assert(!stmt->returnType);
1174 prorettype = requiredResultType ? requiredResultType : VOIDOID;
1175 returnsSet = false;
1177 else if (stmt->returnType)
1179 /* explicit RETURNS clause */
1180 compute_return_type(stmt->returnType, languageOid,
1181 &prorettype, &returnsSet);
1182 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1183 ereport(ERROR,
1184 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1185 errmsg("function result type must be %s because of OUT parameters",
1186 format_type_be(requiredResultType))));
1188 else if (OidIsValid(requiredResultType))
1190 /* default RETURNS clause from OUT parameters */
1191 prorettype = requiredResultType;
1192 returnsSet = false;
1194 else
1196 ereport(ERROR,
1197 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1198 errmsg("function result type must be specified")));
1199 /* Alternative possibility: default to RETURNS VOID */
1200 prorettype = VOIDOID;
1201 returnsSet = false;
1204 if (trftypes_list != NIL)
1206 ListCell *lc;
1207 Datum *arr;
1208 int i;
1210 arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1211 i = 0;
1212 foreach(lc, trftypes_list)
1213 arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1214 trftypes = construct_array_builtin(arr, list_length(trftypes_list), OIDOID);
1216 else
1218 /* store SQL NULL instead of empty array */
1219 trftypes = NULL;
1222 interpret_AS_clause(languageOid, language, funcname, as_clause, stmt->sql_body,
1223 parameterTypes_list, inParameterNames_list,
1224 &prosrc_str, &probin_str, &prosqlbody,
1225 pstate->p_sourcetext);
1228 * Set default values for COST and ROWS depending on other parameters;
1229 * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1230 * values, keep it in sync if you change them.
1232 if (procost < 0)
1234 /* SQL and PL-language functions are assumed more expensive */
1235 if (languageOid == INTERNALlanguageId ||
1236 languageOid == ClanguageId)
1237 procost = 1;
1238 else
1239 procost = 100;
1241 if (prorows < 0)
1243 if (returnsSet)
1244 prorows = 1000;
1245 else
1246 prorows = 0; /* dummy value if not returnsSet */
1248 else if (!returnsSet)
1249 ereport(ERROR,
1250 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1251 errmsg("ROWS is not applicable when function does not return a set")));
1254 * And now that we have all the parameters, and know we're permitted to do
1255 * so, go ahead and create the function.
1257 return ProcedureCreate(funcname,
1258 namespaceId,
1259 stmt->replace,
1260 returnsSet,
1261 prorettype,
1262 GetUserId(),
1263 languageOid,
1264 languageValidator,
1265 prosrc_str, /* converted to text later */
1266 probin_str, /* converted to text later */
1267 prosqlbody,
1268 stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1269 security,
1270 isLeakProof,
1271 isStrict,
1272 volatility,
1273 parallel,
1274 parameterTypes,
1275 PointerGetDatum(allParameterTypes),
1276 PointerGetDatum(parameterModes),
1277 PointerGetDatum(parameterNames),
1278 parameterDefaults,
1279 PointerGetDatum(trftypes),
1280 PointerGetDatum(proconfig),
1281 prosupport,
1282 procost,
1283 prorows);
1287 * Guts of function deletion.
1289 * Note: this is also used for aggregate deletion, since the OIDs of
1290 * both functions and aggregates point to pg_proc.
1292 void
1293 RemoveFunctionById(Oid funcOid)
1295 Relation relation;
1296 HeapTuple tup;
1297 char prokind;
1300 * Delete the pg_proc tuple.
1302 relation = table_open(ProcedureRelationId, RowExclusiveLock);
1304 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1305 if (!HeapTupleIsValid(tup)) /* should not happen */
1306 elog(ERROR, "cache lookup failed for function %u", funcOid);
1308 prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1310 CatalogTupleDelete(relation, &tup->t_self);
1312 ReleaseSysCache(tup);
1314 table_close(relation, RowExclusiveLock);
1316 pgstat_drop_function(funcOid);
1319 * If there's a pg_aggregate tuple, delete that too.
1321 if (prokind == PROKIND_AGGREGATE)
1323 relation = table_open(AggregateRelationId, RowExclusiveLock);
1325 tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1326 if (!HeapTupleIsValid(tup)) /* should not happen */
1327 elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1329 CatalogTupleDelete(relation, &tup->t_self);
1331 ReleaseSysCache(tup);
1333 table_close(relation, RowExclusiveLock);
1338 * Implements the ALTER FUNCTION utility command (except for the
1339 * RENAME and OWNER clauses, which are handled as part of the generic
1340 * ALTER framework).
1342 ObjectAddress
1343 AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
1345 HeapTuple tup;
1346 Oid funcOid;
1347 Form_pg_proc procForm;
1348 bool is_procedure;
1349 Relation rel;
1350 ListCell *l;
1351 DefElem *volatility_item = NULL;
1352 DefElem *strict_item = NULL;
1353 DefElem *security_def_item = NULL;
1354 DefElem *leakproof_item = NULL;
1355 List *set_items = NIL;
1356 DefElem *cost_item = NULL;
1357 DefElem *rows_item = NULL;
1358 DefElem *support_item = NULL;
1359 DefElem *parallel_item = NULL;
1360 ObjectAddress address;
1362 rel = table_open(ProcedureRelationId, RowExclusiveLock);
1364 funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1366 ObjectAddressSet(address, ProcedureRelationId, funcOid);
1368 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1369 if (!HeapTupleIsValid(tup)) /* should not happen */
1370 elog(ERROR, "cache lookup failed for function %u", funcOid);
1372 procForm = (Form_pg_proc) GETSTRUCT(tup);
1374 /* Permission check: must own function */
1375 if (!object_ownercheck(ProcedureRelationId, funcOid, GetUserId()))
1376 aclcheck_error(ACLCHECK_NOT_OWNER, stmt->objtype,
1377 NameListToString(stmt->func->objname));
1379 if (procForm->prokind == PROKIND_AGGREGATE)
1380 ereport(ERROR,
1381 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1382 errmsg("\"%s\" is an aggregate function",
1383 NameListToString(stmt->func->objname))));
1385 is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1387 /* Examine requested actions. */
1388 foreach(l, stmt->actions)
1390 DefElem *defel = (DefElem *) lfirst(l);
1392 if (compute_common_attribute(pstate,
1393 is_procedure,
1394 defel,
1395 &volatility_item,
1396 &strict_item,
1397 &security_def_item,
1398 &leakproof_item,
1399 &set_items,
1400 &cost_item,
1401 &rows_item,
1402 &support_item,
1403 &parallel_item) == false)
1404 elog(ERROR, "option \"%s\" not recognized", defel->defname);
1407 if (volatility_item)
1408 procForm->provolatile = interpret_func_volatility(volatility_item);
1409 if (strict_item)
1410 procForm->proisstrict = boolVal(strict_item->arg);
1411 if (security_def_item)
1412 procForm->prosecdef = boolVal(security_def_item->arg);
1413 if (leakproof_item)
1415 procForm->proleakproof = boolVal(leakproof_item->arg);
1416 if (procForm->proleakproof && !superuser())
1417 ereport(ERROR,
1418 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1419 errmsg("only superuser can define a leakproof function")));
1421 if (cost_item)
1423 procForm->procost = defGetNumeric(cost_item);
1424 if (procForm->procost <= 0)
1425 ereport(ERROR,
1426 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1427 errmsg("COST must be positive")));
1429 if (rows_item)
1431 procForm->prorows = defGetNumeric(rows_item);
1432 if (procForm->prorows <= 0)
1433 ereport(ERROR,
1434 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1435 errmsg("ROWS must be positive")));
1436 if (!procForm->proretset)
1437 ereport(ERROR,
1438 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1439 errmsg("ROWS is not applicable when function does not return a set")));
1441 if (support_item)
1443 /* interpret_func_support handles the privilege check */
1444 Oid newsupport = interpret_func_support(support_item);
1446 /* Add or replace dependency on support function */
1447 if (OidIsValid(procForm->prosupport))
1449 if (changeDependencyFor(ProcedureRelationId, funcOid,
1450 ProcedureRelationId, procForm->prosupport,
1451 newsupport) != 1)
1452 elog(ERROR, "could not change support dependency for function %s",
1453 get_func_name(funcOid));
1455 else
1457 ObjectAddress referenced;
1459 referenced.classId = ProcedureRelationId;
1460 referenced.objectId = newsupport;
1461 referenced.objectSubId = 0;
1462 recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1465 procForm->prosupport = newsupport;
1467 if (parallel_item)
1468 procForm->proparallel = interpret_func_parallel(parallel_item);
1469 if (set_items)
1471 Datum datum;
1472 bool isnull;
1473 ArrayType *a;
1474 Datum repl_val[Natts_pg_proc];
1475 bool repl_null[Natts_pg_proc];
1476 bool repl_repl[Natts_pg_proc];
1478 /* extract existing proconfig setting */
1479 datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1480 a = isnull ? NULL : DatumGetArrayTypeP(datum);
1482 /* update according to each SET or RESET item, left to right */
1483 a = update_proconfig_value(a, set_items);
1485 /* update the tuple */
1486 memset(repl_repl, false, sizeof(repl_repl));
1487 repl_repl[Anum_pg_proc_proconfig - 1] = true;
1489 if (a == NULL)
1491 repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1492 repl_null[Anum_pg_proc_proconfig - 1] = true;
1494 else
1496 repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1497 repl_null[Anum_pg_proc_proconfig - 1] = false;
1500 tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1501 repl_val, repl_null, repl_repl);
1503 /* DO NOT put more touches of procForm below here; it's now dangling. */
1505 /* Do the update */
1506 CatalogTupleUpdate(rel, &tup->t_self, tup);
1508 InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1510 table_close(rel, NoLock);
1511 heap_freetuple(tup);
1513 return address;
1518 * CREATE CAST
1520 ObjectAddress
1521 CreateCast(CreateCastStmt *stmt)
1523 Oid sourcetypeid;
1524 Oid targettypeid;
1525 char sourcetyptype;
1526 char targettyptype;
1527 Oid funcid;
1528 Oid incastid = InvalidOid;
1529 Oid outcastid = InvalidOid;
1530 int nargs;
1531 char castcontext;
1532 char castmethod;
1533 HeapTuple tuple;
1534 AclResult aclresult;
1535 ObjectAddress myself;
1537 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1538 targettypeid = typenameTypeId(NULL, stmt->targettype);
1539 sourcetyptype = get_typtype(sourcetypeid);
1540 targettyptype = get_typtype(targettypeid);
1542 /* No pseudo-types allowed */
1543 if (sourcetyptype == TYPTYPE_PSEUDO)
1544 ereport(ERROR,
1545 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1546 errmsg("source data type %s is a pseudo-type",
1547 TypeNameToString(stmt->sourcetype))));
1549 if (targettyptype == TYPTYPE_PSEUDO)
1550 ereport(ERROR,
1551 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1552 errmsg("target data type %s is a pseudo-type",
1553 TypeNameToString(stmt->targettype))));
1555 /* Permission check */
1556 if (!object_ownercheck(TypeRelationId, sourcetypeid, GetUserId())
1557 && !object_ownercheck(TypeRelationId, targettypeid, GetUserId()))
1558 ereport(ERROR,
1559 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1560 errmsg("must be owner of type %s or type %s",
1561 format_type_be(sourcetypeid),
1562 format_type_be(targettypeid))));
1564 aclresult = object_aclcheck(TypeRelationId, sourcetypeid, GetUserId(), ACL_USAGE);
1565 if (aclresult != ACLCHECK_OK)
1566 aclcheck_error_type(aclresult, sourcetypeid);
1568 aclresult = object_aclcheck(TypeRelationId, targettypeid, GetUserId(), ACL_USAGE);
1569 if (aclresult != ACLCHECK_OK)
1570 aclcheck_error_type(aclresult, targettypeid);
1572 /* Domains are allowed for historical reasons, but we warn */
1573 if (sourcetyptype == TYPTYPE_DOMAIN)
1574 ereport(WARNING,
1575 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1576 errmsg("cast will be ignored because the source data type is a domain")));
1578 else if (targettyptype == TYPTYPE_DOMAIN)
1579 ereport(WARNING,
1580 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1581 errmsg("cast will be ignored because the target data type is a domain")));
1583 /* Determine the cast method */
1584 if (stmt->func != NULL)
1585 castmethod = COERCION_METHOD_FUNCTION;
1586 else if (stmt->inout)
1587 castmethod = COERCION_METHOD_INOUT;
1588 else
1589 castmethod = COERCION_METHOD_BINARY;
1591 if (castmethod == COERCION_METHOD_FUNCTION)
1593 Form_pg_proc procstruct;
1595 funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1597 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1598 if (!HeapTupleIsValid(tuple))
1599 elog(ERROR, "cache lookup failed for function %u", funcid);
1601 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1602 nargs = procstruct->pronargs;
1603 if (nargs < 1 || nargs > 3)
1604 ereport(ERROR,
1605 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1606 errmsg("cast function must take one to three arguments")));
1607 if (!IsBinaryCoercibleWithCast(sourcetypeid,
1608 procstruct->proargtypes.values[0],
1609 &incastid))
1610 ereport(ERROR,
1611 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1612 errmsg("argument of cast function must match or be binary-coercible from source data type")));
1613 if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1614 ereport(ERROR,
1615 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1616 errmsg("second argument of cast function must be type %s",
1617 "integer")));
1618 if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1619 ereport(ERROR,
1620 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1621 errmsg("third argument of cast function must be type %s",
1622 "boolean")));
1623 if (!IsBinaryCoercibleWithCast(procstruct->prorettype,
1624 targettypeid,
1625 &outcastid))
1626 ereport(ERROR,
1627 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1628 errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1631 * Restricting the volatility of a cast function may or may not be a
1632 * good idea in the abstract, but it definitely breaks many old
1633 * user-defined types. Disable this check --- tgl 2/1/03
1635 #ifdef NOT_USED
1636 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1637 ereport(ERROR,
1638 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1639 errmsg("cast function must not be volatile")));
1640 #endif
1641 if (procstruct->prokind != PROKIND_FUNCTION)
1642 ereport(ERROR,
1643 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1644 errmsg("cast function must be a normal function")));
1645 if (procstruct->proretset)
1646 ereport(ERROR,
1647 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1648 errmsg("cast function must not return a set")));
1650 ReleaseSysCache(tuple);
1652 else
1654 funcid = InvalidOid;
1655 nargs = 0;
1658 if (castmethod == COERCION_METHOD_BINARY)
1660 int16 typ1len;
1661 int16 typ2len;
1662 bool typ1byval;
1663 bool typ2byval;
1664 char typ1align;
1665 char typ2align;
1668 * Must be superuser to create binary-compatible casts, since
1669 * erroneous casts can easily crash the backend.
1671 if (!superuser())
1672 ereport(ERROR,
1673 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1674 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1677 * Also, insist that the types match as to size, alignment, and
1678 * pass-by-value attributes; this provides at least a crude check that
1679 * they have similar representations. A pair of types that fail this
1680 * test should certainly not be equated.
1682 get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1683 get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1684 if (typ1len != typ2len ||
1685 typ1byval != typ2byval ||
1686 typ1align != typ2align)
1687 ereport(ERROR,
1688 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1689 errmsg("source and target data types are not physically compatible")));
1692 * We know that composite, enum and array types are never binary-
1693 * compatible with each other. They all have OIDs embedded in them.
1695 * Theoretically you could build a user-defined base type that is
1696 * binary-compatible with a composite, enum, or array type. But we
1697 * disallow that too, as in practice such a cast is surely a mistake.
1698 * You can always work around that by writing a cast function.
1700 if (sourcetyptype == TYPTYPE_COMPOSITE ||
1701 targettyptype == TYPTYPE_COMPOSITE)
1702 ereport(ERROR,
1703 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1704 errmsg("composite data types are not binary-compatible")));
1706 if (sourcetyptype == TYPTYPE_ENUM ||
1707 targettyptype == TYPTYPE_ENUM)
1708 ereport(ERROR,
1709 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1710 errmsg("enum data types are not binary-compatible")));
1712 if (OidIsValid(get_element_type(sourcetypeid)) ||
1713 OidIsValid(get_element_type(targettypeid)))
1714 ereport(ERROR,
1715 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1716 errmsg("array data types are not binary-compatible")));
1719 * We also disallow creating binary-compatibility casts involving
1720 * domains. Casting from a domain to its base type is already
1721 * allowed, and casting the other way ought to go through domain
1722 * coercion to permit constraint checking. Again, if you're intent on
1723 * having your own semantics for that, create a no-op cast function.
1725 * NOTE: if we were to relax this, the above checks for composites
1726 * etc. would have to be modified to look through domains to their
1727 * base types.
1729 if (sourcetyptype == TYPTYPE_DOMAIN ||
1730 targettyptype == TYPTYPE_DOMAIN)
1731 ereport(ERROR,
1732 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1733 errmsg("domain data types must not be marked binary-compatible")));
1737 * Allow source and target types to be same only for length coercion
1738 * functions. We assume a multi-arg function does length coercion.
1740 if (sourcetypeid == targettypeid && nargs < 2)
1741 ereport(ERROR,
1742 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1743 errmsg("source data type and target data type are the same")));
1745 /* convert CoercionContext enum to char value for castcontext */
1746 switch (stmt->context)
1748 case COERCION_IMPLICIT:
1749 castcontext = COERCION_CODE_IMPLICIT;
1750 break;
1751 case COERCION_ASSIGNMENT:
1752 castcontext = COERCION_CODE_ASSIGNMENT;
1753 break;
1754 /* COERCION_PLPGSQL is intentionally not covered here */
1755 case COERCION_EXPLICIT:
1756 castcontext = COERCION_CODE_EXPLICIT;
1757 break;
1758 default:
1759 elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1760 castcontext = 0; /* keep compiler quiet */
1761 break;
1764 myself = CastCreate(sourcetypeid, targettypeid, funcid, incastid, outcastid,
1765 castcontext, castmethod, DEPENDENCY_NORMAL);
1766 return myself;
1770 static void
1771 check_transform_function(Form_pg_proc procstruct)
1773 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1774 ereport(ERROR,
1775 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1776 errmsg("transform function must not be volatile")));
1777 if (procstruct->prokind != PROKIND_FUNCTION)
1778 ereport(ERROR,
1779 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1780 errmsg("transform function must be a normal function")));
1781 if (procstruct->proretset)
1782 ereport(ERROR,
1783 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1784 errmsg("transform function must not return a set")));
1785 if (procstruct->pronargs != 1)
1786 ereport(ERROR,
1787 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1788 errmsg("transform function must take one argument")));
1789 if (procstruct->proargtypes.values[0] != INTERNALOID)
1790 ereport(ERROR,
1791 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1792 errmsg("first argument of transform function must be type %s",
1793 "internal")));
1798 * CREATE TRANSFORM
1800 ObjectAddress
1801 CreateTransform(CreateTransformStmt *stmt)
1803 Oid typeid;
1804 char typtype;
1805 Oid langid;
1806 Oid fromsqlfuncid;
1807 Oid tosqlfuncid;
1808 AclResult aclresult;
1809 Form_pg_proc procstruct;
1810 Datum values[Natts_pg_transform];
1811 bool nulls[Natts_pg_transform] = {0};
1812 bool replaces[Natts_pg_transform] = {0};
1813 Oid transformid;
1814 HeapTuple tuple;
1815 HeapTuple newtuple;
1816 Relation relation;
1817 ObjectAddress myself,
1818 referenced;
1819 ObjectAddresses *addrs;
1820 bool is_replace;
1823 * Get the type
1825 typeid = typenameTypeId(NULL, stmt->type_name);
1826 typtype = get_typtype(typeid);
1828 if (typtype == TYPTYPE_PSEUDO)
1829 ereport(ERROR,
1830 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1831 errmsg("data type %s is a pseudo-type",
1832 TypeNameToString(stmt->type_name))));
1834 if (typtype == TYPTYPE_DOMAIN)
1835 ereport(ERROR,
1836 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1837 errmsg("data type %s is a domain",
1838 TypeNameToString(stmt->type_name))));
1840 if (!object_ownercheck(TypeRelationId, typeid, GetUserId()))
1841 aclcheck_error_type(ACLCHECK_NOT_OWNER, typeid);
1843 aclresult = object_aclcheck(TypeRelationId, typeid, GetUserId(), ACL_USAGE);
1844 if (aclresult != ACLCHECK_OK)
1845 aclcheck_error_type(aclresult, typeid);
1848 * Get the language
1850 langid = get_language_oid(stmt->lang, false);
1852 aclresult = object_aclcheck(LanguageRelationId, langid, GetUserId(), ACL_USAGE);
1853 if (aclresult != ACLCHECK_OK)
1854 aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1857 * Get the functions
1859 if (stmt->fromsql)
1861 fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1863 if (!object_ownercheck(ProcedureRelationId, fromsqlfuncid, GetUserId()))
1864 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1866 aclresult = object_aclcheck(ProcedureRelationId, fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1867 if (aclresult != ACLCHECK_OK)
1868 aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1870 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1871 if (!HeapTupleIsValid(tuple))
1872 elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1873 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1874 if (procstruct->prorettype != INTERNALOID)
1875 ereport(ERROR,
1876 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1877 errmsg("return data type of FROM SQL function must be %s",
1878 "internal")));
1879 check_transform_function(procstruct);
1880 ReleaseSysCache(tuple);
1882 else
1883 fromsqlfuncid = InvalidOid;
1885 if (stmt->tosql)
1887 tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1889 if (!object_ownercheck(ProcedureRelationId, tosqlfuncid, GetUserId()))
1890 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1892 aclresult = object_aclcheck(ProcedureRelationId, tosqlfuncid, GetUserId(), ACL_EXECUTE);
1893 if (aclresult != ACLCHECK_OK)
1894 aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1896 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1897 if (!HeapTupleIsValid(tuple))
1898 elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1899 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1900 if (procstruct->prorettype != typeid)
1901 ereport(ERROR,
1902 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1903 errmsg("return data type of TO SQL function must be the transform data type")));
1904 check_transform_function(procstruct);
1905 ReleaseSysCache(tuple);
1907 else
1908 tosqlfuncid = InvalidOid;
1911 * Ready to go
1913 values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1914 values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1915 values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1916 values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1918 relation = table_open(TransformRelationId, RowExclusiveLock);
1920 tuple = SearchSysCache2(TRFTYPELANG,
1921 ObjectIdGetDatum(typeid),
1922 ObjectIdGetDatum(langid));
1923 if (HeapTupleIsValid(tuple))
1925 Form_pg_transform form = (Form_pg_transform) GETSTRUCT(tuple);
1927 if (!stmt->replace)
1928 ereport(ERROR,
1929 (errcode(ERRCODE_DUPLICATE_OBJECT),
1930 errmsg("transform for type %s language \"%s\" already exists",
1931 format_type_be(typeid),
1932 stmt->lang)));
1934 replaces[Anum_pg_transform_trffromsql - 1] = true;
1935 replaces[Anum_pg_transform_trftosql - 1] = true;
1937 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1938 CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1940 transformid = form->oid;
1941 ReleaseSysCache(tuple);
1942 is_replace = true;
1944 else
1946 transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1947 Anum_pg_transform_oid);
1948 values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1949 newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1950 CatalogTupleInsert(relation, newtuple);
1951 is_replace = false;
1954 if (is_replace)
1955 deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1957 addrs = new_object_addresses();
1959 /* make dependency entries */
1960 ObjectAddressSet(myself, TransformRelationId, transformid);
1962 /* dependency on language */
1963 ObjectAddressSet(referenced, LanguageRelationId, langid);
1964 add_exact_object_address(&referenced, addrs);
1966 /* dependency on type */
1967 ObjectAddressSet(referenced, TypeRelationId, typeid);
1968 add_exact_object_address(&referenced, addrs);
1970 /* dependencies on functions */
1971 if (OidIsValid(fromsqlfuncid))
1973 ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
1974 add_exact_object_address(&referenced, addrs);
1976 if (OidIsValid(tosqlfuncid))
1978 ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
1979 add_exact_object_address(&referenced, addrs);
1982 record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
1983 free_object_addresses(addrs);
1985 /* dependency on extension */
1986 recordDependencyOnCurrentExtension(&myself, is_replace);
1988 /* Post creation hook for new transform */
1989 InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
1991 heap_freetuple(newtuple);
1993 table_close(relation, RowExclusiveLock);
1995 return myself;
2000 * get_transform_oid - given type OID and language OID, look up a transform OID
2002 * If missing_ok is false, throw an error if the transform is not found. If
2003 * true, just return InvalidOid.
2006 get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
2008 Oid oid;
2010 oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2011 ObjectIdGetDatum(type_id),
2012 ObjectIdGetDatum(lang_id));
2013 if (!OidIsValid(oid) && !missing_ok)
2014 ereport(ERROR,
2015 (errcode(ERRCODE_UNDEFINED_OBJECT),
2016 errmsg("transform for type %s language \"%s\" does not exist",
2017 format_type_be(type_id),
2018 get_language_name(lang_id, false))));
2019 return oid;
2024 * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA/RENAME
2026 * Is there a function with the given name and signature already in the given
2027 * namespace? If so, raise an appropriate error message.
2029 void
2030 IsThereFunctionInNamespace(const char *proname, int pronargs,
2031 oidvector *proargtypes, Oid nspOid)
2033 /* check for duplicate name (more friendly than unique-index failure) */
2034 if (SearchSysCacheExists3(PROCNAMEARGSNSP,
2035 CStringGetDatum(proname),
2036 PointerGetDatum(proargtypes),
2037 ObjectIdGetDatum(nspOid)))
2038 ereport(ERROR,
2039 (errcode(ERRCODE_DUPLICATE_FUNCTION),
2040 errmsg("function %s already exists in schema \"%s\"",
2041 funcname_signature_string(proname, pronargs,
2042 NIL, proargtypes->values),
2043 get_namespace_name(nspOid))));
2047 * ExecuteDoStmt
2048 * Execute inline procedural-language code
2050 * See at ExecuteCallStmt() about the atomic argument.
2052 void
2053 ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
2055 InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
2056 ListCell *arg;
2057 DefElem *as_item = NULL;
2058 DefElem *language_item = NULL;
2059 char *language;
2060 Oid laninline;
2061 HeapTuple languageTuple;
2062 Form_pg_language languageStruct;
2064 /* Process options we got from gram.y */
2065 foreach(arg, stmt->args)
2067 DefElem *defel = (DefElem *) lfirst(arg);
2069 if (strcmp(defel->defname, "as") == 0)
2071 if (as_item)
2072 errorConflictingDefElem(defel, pstate);
2073 as_item = defel;
2075 else if (strcmp(defel->defname, "language") == 0)
2077 if (language_item)
2078 errorConflictingDefElem(defel, pstate);
2079 language_item = defel;
2081 else
2082 elog(ERROR, "option \"%s\" not recognized",
2083 defel->defname);
2086 if (as_item)
2087 codeblock->source_text = strVal(as_item->arg);
2088 else
2089 ereport(ERROR,
2090 (errcode(ERRCODE_SYNTAX_ERROR),
2091 errmsg("no inline code specified")));
2093 /* if LANGUAGE option wasn't specified, use the default */
2094 if (language_item)
2095 language = strVal(language_item->arg);
2096 else
2097 language = "plpgsql";
2099 /* Look up the language and validate permissions */
2100 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2101 if (!HeapTupleIsValid(languageTuple))
2102 ereport(ERROR,
2103 (errcode(ERRCODE_UNDEFINED_OBJECT),
2104 errmsg("language \"%s\" does not exist", language),
2105 (extension_file_exists(language) ?
2106 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2108 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2109 codeblock->langOid = languageStruct->oid;
2110 codeblock->langIsTrusted = languageStruct->lanpltrusted;
2111 codeblock->atomic = atomic;
2113 if (languageStruct->lanpltrusted)
2115 /* if trusted language, need USAGE privilege */
2116 AclResult aclresult;
2118 aclresult = object_aclcheck(LanguageRelationId, codeblock->langOid, GetUserId(),
2119 ACL_USAGE);
2120 if (aclresult != ACLCHECK_OK)
2121 aclcheck_error(aclresult, OBJECT_LANGUAGE,
2122 NameStr(languageStruct->lanname));
2124 else
2126 /* if untrusted language, must be superuser */
2127 if (!superuser())
2128 aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE,
2129 NameStr(languageStruct->lanname));
2132 /* get the handler function's OID */
2133 laninline = languageStruct->laninline;
2134 if (!OidIsValid(laninline))
2135 ereport(ERROR,
2136 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2137 errmsg("language \"%s\" does not support inline code execution",
2138 NameStr(languageStruct->lanname))));
2140 ReleaseSysCache(languageTuple);
2142 /* execute the inline handler */
2143 OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2147 * Execute CALL statement
2149 * Inside a top-level CALL statement, transaction-terminating commands such as
2150 * COMMIT or a PL-specific equivalent are allowed. The terminology in the SQL
2151 * standard is that CALL establishes a non-atomic execution context. Most
2152 * other commands establish an atomic execution context, in which transaction
2153 * control actions are not allowed. If there are nested executions of CALL,
2154 * we want to track the execution context recursively, so that the nested
2155 * CALLs can also do transaction control. Note, however, that for example in
2156 * CALL -> SELECT -> CALL, the second call cannot do transaction control,
2157 * because the SELECT in between establishes an atomic execution context.
2159 * So when ExecuteCallStmt() is called from the top level, we pass in atomic =
2160 * false (recall that that means transactions = yes). We then create a
2161 * CallContext node with content atomic = false, which is passed in the
2162 * fcinfo->context field to the procedure invocation. The language
2163 * implementation should then take appropriate measures to allow or prevent
2164 * transaction commands based on that information, e.g., call
2165 * SPI_connect_ext(SPI_OPT_NONATOMIC). The language should also pass on the
2166 * atomic flag to any nested invocations to CALL.
2168 * The expression data structures and execution context that we create
2169 * within this function are children of the portalContext of the Portal
2170 * that the CALL utility statement runs in. Therefore, any pass-by-ref
2171 * values that we're passing to the procedure will survive transaction
2172 * commits that might occur inside the procedure.
2174 void
2175 ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
2177 LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2178 ListCell *lc;
2179 FuncExpr *fexpr;
2180 int nargs;
2181 int i;
2182 AclResult aclresult;
2183 FmgrInfo flinfo;
2184 CallContext *callcontext;
2185 EState *estate;
2186 ExprContext *econtext;
2187 HeapTuple tp;
2188 PgStat_FunctionCallUsage fcusage;
2189 Datum retval;
2191 fexpr = stmt->funcexpr;
2192 Assert(fexpr);
2193 Assert(IsA(fexpr, FuncExpr));
2195 aclresult = object_aclcheck(ProcedureRelationId, fexpr->funcid, GetUserId(), ACL_EXECUTE);
2196 if (aclresult != ACLCHECK_OK)
2197 aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2199 /* Prep the context object we'll pass to the procedure */
2200 callcontext = makeNode(CallContext);
2201 callcontext->atomic = atomic;
2203 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2204 if (!HeapTupleIsValid(tp))
2205 elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2208 * If proconfig is set we can't allow transaction commands because of the
2209 * way the GUC stacking works: The transaction boundary would have to pop
2210 * the proconfig setting off the stack. That restriction could be lifted
2211 * by redesigning the GUC nesting mechanism a bit.
2213 if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2214 callcontext->atomic = true;
2217 * In security definer procedures, we can't allow transaction commands.
2218 * StartTransaction() insists that the security context stack is empty,
2219 * and AbortTransaction() resets the security context. This could be
2220 * reorganized, but right now it doesn't work.
2222 if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2223 callcontext->atomic = true;
2225 ReleaseSysCache(tp);
2227 /* safety check; see ExecInitFunc() */
2228 nargs = list_length(fexpr->args);
2229 if (nargs > FUNC_MAX_ARGS)
2230 ereport(ERROR,
2231 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2232 errmsg_plural("cannot pass more than %d argument to a procedure",
2233 "cannot pass more than %d arguments to a procedure",
2234 FUNC_MAX_ARGS,
2235 FUNC_MAX_ARGS)));
2237 /* Initialize function call structure */
2238 InvokeFunctionExecuteHook(fexpr->funcid);
2239 fmgr_info(fexpr->funcid, &flinfo);
2240 fmgr_info_set_expr((Node *) fexpr, &flinfo);
2241 InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2242 (Node *) callcontext, NULL);
2245 * Evaluate procedure arguments inside a suitable execution context. Note
2246 * we can't free this context till the procedure returns.
2248 estate = CreateExecutorState();
2249 estate->es_param_list_info = params;
2250 econtext = CreateExprContext(estate);
2253 * If we're called in non-atomic context, we also have to ensure that the
2254 * argument expressions run with an up-to-date snapshot. Our caller will
2255 * have provided a current snapshot in atomic contexts, but not in
2256 * non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2257 * destroying the snapshot makes higher-level management too complicated.
2259 if (!atomic)
2260 PushActiveSnapshot(GetTransactionSnapshot());
2262 i = 0;
2263 foreach(lc, fexpr->args)
2265 ExprState *exprstate;
2266 Datum val;
2267 bool isnull;
2269 exprstate = ExecPrepareExpr(lfirst(lc), estate);
2271 val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2273 fcinfo->args[i].value = val;
2274 fcinfo->args[i].isnull = isnull;
2276 i++;
2279 /* Get rid of temporary snapshot for arguments, if we made one */
2280 if (!atomic)
2281 PopActiveSnapshot();
2283 /* Here we actually call the procedure */
2284 pgstat_init_function_usage(fcinfo, &fcusage);
2285 retval = FunctionCallInvoke(fcinfo);
2286 pgstat_end_function_usage(&fcusage, true);
2288 /* Handle the procedure's outputs */
2289 if (fexpr->funcresulttype == VOIDOID)
2291 /* do nothing */
2293 else if (fexpr->funcresulttype == RECORDOID)
2295 /* send tuple to client */
2296 HeapTupleHeader td;
2297 Oid tupType;
2298 int32 tupTypmod;
2299 TupleDesc retdesc;
2300 HeapTupleData rettupdata;
2301 TupOutputState *tstate;
2302 TupleTableSlot *slot;
2304 if (fcinfo->isnull)
2305 elog(ERROR, "procedure returned null record");
2308 * Ensure there's an active snapshot whilst we execute whatever's
2309 * involved here. Note that this is *not* sufficient to make the
2310 * world safe for TOAST pointers to be included in the returned data:
2311 * the referenced data could have gone away while we didn't hold a
2312 * snapshot. Hence, it's incumbent on PLs that can do COMMIT/ROLLBACK
2313 * to not return TOAST pointers, unless those pointers were fetched
2314 * after the last COMMIT/ROLLBACK in the procedure.
2316 * XXX that is a really nasty, hard-to-test requirement. Is there a
2317 * way to remove it?
2319 EnsurePortalSnapshotExists();
2321 td = DatumGetHeapTupleHeader(retval);
2322 tupType = HeapTupleHeaderGetTypeId(td);
2323 tupTypmod = HeapTupleHeaderGetTypMod(td);
2324 retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2326 tstate = begin_tup_output_tupdesc(dest, retdesc,
2327 &TTSOpsHeapTuple);
2329 rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2330 ItemPointerSetInvalid(&(rettupdata.t_self));
2331 rettupdata.t_tableOid = InvalidOid;
2332 rettupdata.t_data = td;
2334 slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2335 tstate->dest->receiveSlot(slot, tstate->dest);
2337 end_tup_output(tstate);
2339 ReleaseTupleDesc(retdesc);
2341 else
2342 elog(ERROR, "unexpected result type for procedure: %u",
2343 fexpr->funcresulttype);
2345 FreeExecutorState(estate);
2349 * Construct the tuple descriptor for a CALL statement return
2351 TupleDesc
2352 CallStmtResultDesc(CallStmt *stmt)
2354 FuncExpr *fexpr;
2355 HeapTuple tuple;
2356 TupleDesc tupdesc;
2358 fexpr = stmt->funcexpr;
2360 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2361 if (!HeapTupleIsValid(tuple))
2362 elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2364 tupdesc = build_function_result_tupdesc_t(tuple);
2366 ReleaseSysCache(tuple);
2369 * The result of build_function_result_tupdesc_t has the right column
2370 * names, but it just has the declared output argument types, which is the
2371 * wrong thing in polymorphic cases. Get the correct types by examining
2372 * stmt->outargs. We intentionally keep the atttypmod as -1 and the
2373 * attcollation as the type's default, since that's always the appropriate
2374 * thing for function outputs; there's no point in considering any
2375 * additional info available from outargs. Note that tupdesc is null if
2376 * there are no outargs.
2378 if (tupdesc)
2380 Assert(tupdesc->natts == list_length(stmt->outargs));
2381 for (int i = 0; i < tupdesc->natts; i++)
2383 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2384 Node *outarg = (Node *) list_nth(stmt->outargs, i);
2386 TupleDescInitEntry(tupdesc,
2387 i + 1,
2388 NameStr(att->attname),
2389 exprType(outarg),
2395 return tupdesc;