Move routines to manipulate WAL into PostgreSQL::Test::Cluster
[pgsql.git] / src / backend / commands / functioncmds.c
blobb9fd7683abb4219706f2073c90028fad0b9d3c8d
1 /*-------------------------------------------------------------------------
3 * functioncmds.c
5 * Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
6 * CAST commands.
8 * Portions Copyright (c) 1996-2025, 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 "FooCreate" routines (in src/backend/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_p.
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(pstate, 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 parser_errposition(pstate, t->location)));
247 /* We don't allow creating aggregates on shell types either */
248 else if (objtype == OBJECT_AGGREGATE)
249 ereport(ERROR,
250 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
251 errmsg("aggregate cannot accept shell type %s",
252 TypeNameToString(t)),
253 parser_errposition(pstate, t->location)));
254 else
255 ereport(NOTICE,
256 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
257 errmsg("argument type %s is only a shell",
258 TypeNameToString(t)),
259 parser_errposition(pstate, t->location)));
261 toid = typeTypeId(typtup);
262 ReleaseSysCache(typtup);
264 else
266 ereport(ERROR,
267 (errcode(ERRCODE_UNDEFINED_OBJECT),
268 errmsg("type %s does not exist",
269 TypeNameToString(t)),
270 parser_errposition(pstate, t->location)));
271 toid = InvalidOid; /* keep compiler quiet */
274 aclresult = object_aclcheck(TypeRelationId, toid, GetUserId(), ACL_USAGE);
275 if (aclresult != ACLCHECK_OK)
276 aclcheck_error_type(aclresult, toid);
278 if (t->setof)
280 if (objtype == OBJECT_AGGREGATE)
281 ereport(ERROR,
282 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
283 errmsg("aggregates cannot accept set arguments"),
284 parser_errposition(pstate, fp->location)));
285 else if (objtype == OBJECT_PROCEDURE)
286 ereport(ERROR,
287 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
288 errmsg("procedures cannot accept set arguments"),
289 parser_errposition(pstate, fp->location)));
290 else
291 ereport(ERROR,
292 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
293 errmsg("functions cannot accept set arguments"),
294 parser_errposition(pstate, fp->location)));
297 /* handle input parameters */
298 if (fpmode != FUNC_PARAM_OUT && fpmode != FUNC_PARAM_TABLE)
300 /* other input parameters can't follow a VARIADIC parameter */
301 if (varCount > 0)
302 ereport(ERROR,
303 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
304 errmsg("VARIADIC parameter must be the last input parameter"),
305 parser_errposition(pstate, fp->location)));
306 inTypes[inCount++] = toid;
307 isinput = true;
308 if (parameterTypes_list)
309 *parameterTypes_list = lappend_oid(*parameterTypes_list, toid);
312 /* handle output parameters */
313 if (fpmode != FUNC_PARAM_IN && fpmode != FUNC_PARAM_VARIADIC)
315 if (objtype == OBJECT_PROCEDURE)
318 * We disallow OUT-after-VARIADIC only for procedures. While
319 * such a case causes no confusion in ordinary function calls,
320 * it would cause confusion in a CALL statement.
322 if (varCount > 0)
323 ereport(ERROR,
324 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
325 errmsg("VARIADIC parameter must be the last parameter"),
326 parser_errposition(pstate, fp->location)));
327 /* Procedures with output parameters always return RECORD */
328 *requiredResultType = RECORDOID;
330 else if (outCount == 0) /* save first output param's type */
331 *requiredResultType = toid;
332 outCount++;
335 if (fpmode == FUNC_PARAM_VARIADIC)
337 *variadicArgType = toid;
338 varCount++;
339 /* validate variadic parameter type */
340 switch (toid)
342 case ANYARRAYOID:
343 case ANYCOMPATIBLEARRAYOID:
344 case ANYOID:
345 /* okay */
346 break;
347 default:
348 if (!OidIsValid(get_element_type(toid)))
349 ereport(ERROR,
350 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
351 errmsg("VARIADIC parameter must be an array"),
352 parser_errposition(pstate, fp->location)));
353 break;
357 allTypes[i] = ObjectIdGetDatum(toid);
359 paramModes[i] = CharGetDatum(fpmode);
361 if (fp->name && fp->name[0])
363 ListCell *px;
366 * As of Postgres 9.0 we disallow using the same name for two
367 * input or two output function parameters. Depending on the
368 * function's language, conflicting input and output names might
369 * be bad too, but we leave it to the PL to complain if so.
371 foreach(px, parameters)
373 FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
374 FunctionParameterMode prevfpmode;
376 if (prevfp == fp)
377 break;
378 /* as above, default mode is IN */
379 prevfpmode = prevfp->mode;
380 if (prevfpmode == FUNC_PARAM_DEFAULT)
381 prevfpmode = FUNC_PARAM_IN;
382 /* pure in doesn't conflict with pure out */
383 if ((fpmode == FUNC_PARAM_IN ||
384 fpmode == FUNC_PARAM_VARIADIC) &&
385 (prevfpmode == FUNC_PARAM_OUT ||
386 prevfpmode == FUNC_PARAM_TABLE))
387 continue;
388 if ((prevfpmode == FUNC_PARAM_IN ||
389 prevfpmode == FUNC_PARAM_VARIADIC) &&
390 (fpmode == FUNC_PARAM_OUT ||
391 fpmode == FUNC_PARAM_TABLE))
392 continue;
393 if (prevfp->name && prevfp->name[0] &&
394 strcmp(prevfp->name, fp->name) == 0)
395 ereport(ERROR,
396 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
397 errmsg("parameter name \"%s\" used more than once",
398 fp->name),
399 parser_errposition(pstate, fp->location)));
402 paramNames[i] = CStringGetTextDatum(fp->name);
403 have_names = true;
406 if (inParameterNames_list)
407 *inParameterNames_list = lappend(*inParameterNames_list, makeString(fp->name ? fp->name : pstrdup("")));
409 if (fp->defexpr)
411 Node *def;
413 if (!isinput)
414 ereport(ERROR,
415 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
416 errmsg("only input parameters can have default values"),
417 parser_errposition(pstate, fp->location)));
419 def = transformExpr(pstate, fp->defexpr,
420 EXPR_KIND_FUNCTION_DEFAULT);
421 def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
422 assign_expr_collations(pstate, def);
425 * Make sure no variables are referred to (this is probably dead
426 * code now that add_missing_from is history).
428 if (pstate->p_rtable != NIL ||
429 contain_var_clause(def))
430 ereport(ERROR,
431 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
432 errmsg("cannot use table references in parameter default value"),
433 parser_errposition(pstate, fp->location)));
436 * transformExpr() should have already rejected subqueries,
437 * aggregates, and window functions, based on the EXPR_KIND_ for a
438 * default expression.
440 * It can't return a set either --- but coerce_to_specific_type
441 * already checked that for us.
443 * Note: the point of these restrictions is to ensure that an
444 * expression that, on its face, hasn't got subplans, aggregates,
445 * etc cannot suddenly have them after function default arguments
446 * are inserted.
449 *parameterDefaults = lappend(*parameterDefaults, def);
450 have_defaults = true;
452 else
454 if (isinput && have_defaults)
455 ereport(ERROR,
456 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
457 errmsg("input parameters after one with a default value must also have defaults"),
458 parser_errposition(pstate, fp->location)));
461 * For procedures, we also can't allow OUT parameters after one
462 * with a default, because the same sort of confusion arises in a
463 * CALL statement.
465 if (objtype == OBJECT_PROCEDURE && have_defaults)
466 ereport(ERROR,
467 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
468 errmsg("procedure OUT parameters cannot appear after one with a default value"),
469 parser_errposition(pstate, fp->location)));
472 i++;
475 /* Now construct the proper outputs as needed */
476 *parameterTypes = buildoidvector(inTypes, inCount);
478 if (outCount > 0 || varCount > 0)
480 *allParameterTypes = construct_array_builtin(allTypes, parameterCount, OIDOID);
481 *parameterModes = construct_array_builtin(paramModes, parameterCount, CHAROID);
482 if (outCount > 1)
483 *requiredResultType = RECORDOID;
484 /* otherwise we set requiredResultType correctly above */
486 else
488 *allParameterTypes = NULL;
489 *parameterModes = NULL;
492 if (have_names)
494 for (i = 0; i < parameterCount; i++)
496 if (paramNames[i] == PointerGetDatum(NULL))
497 paramNames[i] = CStringGetTextDatum("");
499 *parameterNames = construct_array_builtin(paramNames, parameterCount, TEXTOID);
501 else
502 *parameterNames = NULL;
507 * Recognize one of the options that can be passed to both CREATE
508 * FUNCTION and ALTER FUNCTION and return it via one of the out
509 * parameters. Returns true if the passed option was recognized. If
510 * the out parameter we were going to assign to points to non-NULL,
511 * raise a duplicate-clause error. (We don't try to detect duplicate
512 * SET parameters though --- if you're redundant, the last one wins.)
514 static bool
515 compute_common_attribute(ParseState *pstate,
516 bool is_procedure,
517 DefElem *defel,
518 DefElem **volatility_item,
519 DefElem **strict_item,
520 DefElem **security_item,
521 DefElem **leakproof_item,
522 List **set_items,
523 DefElem **cost_item,
524 DefElem **rows_item,
525 DefElem **support_item,
526 DefElem **parallel_item)
528 if (strcmp(defel->defname, "volatility") == 0)
530 if (is_procedure)
531 goto procedure_error;
532 if (*volatility_item)
533 errorConflictingDefElem(defel, pstate);
535 *volatility_item = defel;
537 else if (strcmp(defel->defname, "strict") == 0)
539 if (is_procedure)
540 goto procedure_error;
541 if (*strict_item)
542 errorConflictingDefElem(defel, pstate);
544 *strict_item = defel;
546 else if (strcmp(defel->defname, "security") == 0)
548 if (*security_item)
549 errorConflictingDefElem(defel, pstate);
551 *security_item = defel;
553 else if (strcmp(defel->defname, "leakproof") == 0)
555 if (is_procedure)
556 goto procedure_error;
557 if (*leakproof_item)
558 errorConflictingDefElem(defel, pstate);
560 *leakproof_item = defel;
562 else if (strcmp(defel->defname, "set") == 0)
564 *set_items = lappend(*set_items, defel->arg);
566 else if (strcmp(defel->defname, "cost") == 0)
568 if (is_procedure)
569 goto procedure_error;
570 if (*cost_item)
571 errorConflictingDefElem(defel, pstate);
573 *cost_item = defel;
575 else if (strcmp(defel->defname, "rows") == 0)
577 if (is_procedure)
578 goto procedure_error;
579 if (*rows_item)
580 errorConflictingDefElem(defel, pstate);
582 *rows_item = defel;
584 else if (strcmp(defel->defname, "support") == 0)
586 if (is_procedure)
587 goto procedure_error;
588 if (*support_item)
589 errorConflictingDefElem(defel, pstate);
591 *support_item = defel;
593 else if (strcmp(defel->defname, "parallel") == 0)
595 if (is_procedure)
596 goto procedure_error;
597 if (*parallel_item)
598 errorConflictingDefElem(defel, pstate);
600 *parallel_item = defel;
602 else
603 return false;
605 /* Recognized an option */
606 return true;
608 procedure_error:
609 ereport(ERROR,
610 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
611 errmsg("invalid attribute in procedure definition"),
612 parser_errposition(pstate, defel->location)));
613 return false;
616 static char
617 interpret_func_volatility(DefElem *defel)
619 char *str = strVal(defel->arg);
621 if (strcmp(str, "immutable") == 0)
622 return PROVOLATILE_IMMUTABLE;
623 else if (strcmp(str, "stable") == 0)
624 return PROVOLATILE_STABLE;
625 else if (strcmp(str, "volatile") == 0)
626 return PROVOLATILE_VOLATILE;
627 else
629 elog(ERROR, "invalid volatility \"%s\"", str);
630 return 0; /* keep compiler quiet */
634 static char
635 interpret_func_parallel(DefElem *defel)
637 char *str = strVal(defel->arg);
639 if (strcmp(str, "safe") == 0)
640 return PROPARALLEL_SAFE;
641 else if (strcmp(str, "unsafe") == 0)
642 return PROPARALLEL_UNSAFE;
643 else if (strcmp(str, "restricted") == 0)
644 return PROPARALLEL_RESTRICTED;
645 else
647 ereport(ERROR,
648 (errcode(ERRCODE_SYNTAX_ERROR),
649 errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
650 return PROPARALLEL_UNSAFE; /* keep compiler quiet */
655 * Update a proconfig value according to a list of VariableSetStmt items.
657 * The input and result may be NULL to signify a null entry.
659 static ArrayType *
660 update_proconfig_value(ArrayType *a, List *set_items)
662 ListCell *l;
664 foreach(l, set_items)
666 VariableSetStmt *sstmt = lfirst_node(VariableSetStmt, l);
668 if (sstmt->kind == VAR_RESET_ALL)
669 a = NULL;
670 else
672 char *valuestr = ExtractSetVariableArgs(sstmt);
674 if (valuestr)
675 a = GUCArrayAdd(a, sstmt->name, valuestr);
676 else /* RESET */
677 a = GUCArrayDelete(a, sstmt->name);
681 return a;
684 static Oid
685 interpret_func_support(DefElem *defel)
687 List *procName = defGetQualifiedName(defel);
688 Oid procOid;
689 Oid argList[1];
692 * Support functions always take one INTERNAL argument and return
693 * INTERNAL.
695 argList[0] = INTERNALOID;
697 procOid = LookupFuncName(procName, 1, argList, true);
698 if (!OidIsValid(procOid))
699 ereport(ERROR,
700 (errcode(ERRCODE_UNDEFINED_FUNCTION),
701 errmsg("function %s does not exist",
702 func_signature_string(procName, 1, NIL, argList))));
704 if (get_func_rettype(procOid) != INTERNALOID)
705 ereport(ERROR,
706 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
707 errmsg("support function %s must return type %s",
708 NameListToString(procName), "internal")));
711 * Someday we might want an ACL check here; but for now, we insist that
712 * you be superuser to specify a support function, so privilege on the
713 * support function is moot.
715 if (!superuser())
716 ereport(ERROR,
717 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
718 errmsg("must be superuser to specify a support function")));
720 return procOid;
725 * Dissect the list of options assembled in gram.y into function
726 * attributes.
728 static void
729 compute_function_attributes(ParseState *pstate,
730 bool is_procedure,
731 List *options,
732 List **as,
733 char **language,
734 Node **transform,
735 bool *windowfunc_p,
736 char *volatility_p,
737 bool *strict_p,
738 bool *security_definer,
739 bool *leakproof_p,
740 ArrayType **proconfig,
741 float4 *procost,
742 float4 *prorows,
743 Oid *prosupport,
744 char *parallel_p)
746 ListCell *option;
747 DefElem *as_item = NULL;
748 DefElem *language_item = NULL;
749 DefElem *transform_item = NULL;
750 DefElem *windowfunc_item = NULL;
751 DefElem *volatility_item = NULL;
752 DefElem *strict_item = NULL;
753 DefElem *security_item = NULL;
754 DefElem *leakproof_item = NULL;
755 List *set_items = NIL;
756 DefElem *cost_item = NULL;
757 DefElem *rows_item = NULL;
758 DefElem *support_item = NULL;
759 DefElem *parallel_item = NULL;
761 foreach(option, options)
763 DefElem *defel = (DefElem *) lfirst(option);
765 if (strcmp(defel->defname, "as") == 0)
767 if (as_item)
768 errorConflictingDefElem(defel, pstate);
769 as_item = defel;
771 else if (strcmp(defel->defname, "language") == 0)
773 if (language_item)
774 errorConflictingDefElem(defel, pstate);
775 language_item = defel;
777 else if (strcmp(defel->defname, "transform") == 0)
779 if (transform_item)
780 errorConflictingDefElem(defel, pstate);
781 transform_item = defel;
783 else if (strcmp(defel->defname, "window") == 0)
785 if (windowfunc_item)
786 errorConflictingDefElem(defel, pstate);
787 if (is_procedure)
788 ereport(ERROR,
789 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
790 errmsg("invalid attribute in procedure definition"),
791 parser_errposition(pstate, defel->location)));
792 windowfunc_item = defel;
794 else if (compute_common_attribute(pstate,
795 is_procedure,
796 defel,
797 &volatility_item,
798 &strict_item,
799 &security_item,
800 &leakproof_item,
801 &set_items,
802 &cost_item,
803 &rows_item,
804 &support_item,
805 &parallel_item))
807 /* recognized common option */
808 continue;
810 else
811 elog(ERROR, "option \"%s\" not recognized",
812 defel->defname);
815 if (as_item)
816 *as = (List *) as_item->arg;
817 if (language_item)
818 *language = strVal(language_item->arg);
819 if (transform_item)
820 *transform = transform_item->arg;
821 if (windowfunc_item)
822 *windowfunc_p = boolVal(windowfunc_item->arg);
823 if (volatility_item)
824 *volatility_p = interpret_func_volatility(volatility_item);
825 if (strict_item)
826 *strict_p = boolVal(strict_item->arg);
827 if (security_item)
828 *security_definer = boolVal(security_item->arg);
829 if (leakproof_item)
830 *leakproof_p = boolVal(leakproof_item->arg);
831 if (set_items)
832 *proconfig = update_proconfig_value(NULL, set_items);
833 if (cost_item)
835 *procost = defGetNumeric(cost_item);
836 if (*procost <= 0)
837 ereport(ERROR,
838 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
839 errmsg("COST must be positive")));
841 if (rows_item)
843 *prorows = defGetNumeric(rows_item);
844 if (*prorows <= 0)
845 ereport(ERROR,
846 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
847 errmsg("ROWS must be positive")));
849 if (support_item)
850 *prosupport = interpret_func_support(support_item);
851 if (parallel_item)
852 *parallel_p = interpret_func_parallel(parallel_item);
857 * For a dynamically linked C language object, the form of the clause is
859 * AS <object file name> [, <link symbol name> ]
861 * In all other cases
863 * AS <object reference, or sql code>
865 static void
866 interpret_AS_clause(Oid languageOid, const char *languageName,
867 char *funcname, List *as, Node *sql_body_in,
868 List *parameterTypes, List *inParameterNames,
869 char **prosrc_str_p, char **probin_str_p,
870 Node **sql_body_out,
871 const char *queryString)
873 if (!sql_body_in && !as)
874 ereport(ERROR,
875 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
876 errmsg("no function body specified")));
878 if (sql_body_in && as)
879 ereport(ERROR,
880 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
881 errmsg("duplicate function body specified")));
883 if (sql_body_in && languageOid != SQLlanguageId)
884 ereport(ERROR,
885 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
886 errmsg("inline SQL function body only valid for language SQL")));
888 *sql_body_out = NULL;
890 if (languageOid == ClanguageId)
893 * For "C" language, store the file name in probin and, when given,
894 * the link symbol name in prosrc. If link symbol is omitted,
895 * substitute procedure name. We also allow link symbol to be
896 * specified as "-", since that was the habit in PG versions before
897 * 8.4, and there might be dump files out there that don't translate
898 * that back to "omitted".
900 *probin_str_p = strVal(linitial(as));
901 if (list_length(as) == 1)
902 *prosrc_str_p = funcname;
903 else
905 *prosrc_str_p = strVal(lsecond(as));
906 if (strcmp(*prosrc_str_p, "-") == 0)
907 *prosrc_str_p = funcname;
910 else if (sql_body_in)
912 SQLFunctionParseInfoPtr pinfo;
914 pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
916 pinfo->fname = funcname;
917 pinfo->nargs = list_length(parameterTypes);
918 pinfo->argtypes = (Oid *) palloc(pinfo->nargs * sizeof(Oid));
919 pinfo->argnames = (char **) palloc(pinfo->nargs * sizeof(char *));
920 for (int i = 0; i < list_length(parameterTypes); i++)
922 char *s = strVal(list_nth(inParameterNames, i));
924 pinfo->argtypes[i] = list_nth_oid(parameterTypes, i);
925 if (IsPolymorphicType(pinfo->argtypes[i]))
926 ereport(ERROR,
927 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
928 errmsg("SQL function with unquoted function body cannot have polymorphic arguments")));
930 if (s[0] != '\0')
931 pinfo->argnames[i] = s;
932 else
933 pinfo->argnames[i] = NULL;
936 if (IsA(sql_body_in, List))
938 List *stmts = linitial_node(List, castNode(List, sql_body_in));
939 ListCell *lc;
940 List *transformed_stmts = NIL;
942 foreach(lc, stmts)
944 Node *stmt = lfirst(lc);
945 Query *q;
946 ParseState *pstate = make_parsestate(NULL);
948 pstate->p_sourcetext = queryString;
949 sql_fn_parser_setup(pstate, pinfo);
950 q = transformStmt(pstate, stmt);
951 if (q->commandType == CMD_UTILITY)
952 ereport(ERROR,
953 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
954 errmsg("%s is not yet supported in unquoted SQL function body",
955 GetCommandTagName(CreateCommandTag(q->utilityStmt))));
956 transformed_stmts = lappend(transformed_stmts, q);
957 free_parsestate(pstate);
960 *sql_body_out = (Node *) list_make1(transformed_stmts);
962 else
964 Query *q;
965 ParseState *pstate = make_parsestate(NULL);
967 pstate->p_sourcetext = queryString;
968 sql_fn_parser_setup(pstate, pinfo);
969 q = transformStmt(pstate, sql_body_in);
970 if (q->commandType == CMD_UTILITY)
971 ereport(ERROR,
972 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
973 errmsg("%s is not yet supported in unquoted SQL function body",
974 GetCommandTagName(CreateCommandTag(q->utilityStmt))));
975 free_parsestate(pstate);
977 *sql_body_out = (Node *) q;
981 * We must put something in prosrc. For the moment, just record an
982 * empty string. It might be useful to store the original text of the
983 * CREATE FUNCTION statement --- but to make actual use of that in
984 * error reports, we'd also have to adjust readfuncs.c to not throw
985 * away node location fields when reading prosqlbody.
987 *prosrc_str_p = pstrdup("");
989 /* But we definitely don't need probin. */
990 *probin_str_p = NULL;
992 else
994 /* Everything else wants the given string in prosrc. */
995 *prosrc_str_p = strVal(linitial(as));
996 *probin_str_p = NULL;
998 if (list_length(as) != 1)
999 ereport(ERROR,
1000 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1001 errmsg("only one AS item needed for language \"%s\"",
1002 languageName)));
1004 if (languageOid == INTERNALlanguageId)
1007 * In PostgreSQL versions before 6.5, the SQL name of the created
1008 * function could not be different from the internal name, and
1009 * "prosrc" wasn't used. So there is code out there that does
1010 * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
1011 * modicum of backwards compatibility, accept an empty "prosrc"
1012 * value as meaning the supplied SQL function name.
1014 if (strlen(*prosrc_str_p) == 0)
1015 *prosrc_str_p = funcname;
1022 * CreateFunction
1023 * Execute a CREATE FUNCTION (or CREATE PROCEDURE) utility statement.
1025 ObjectAddress
1026 CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
1028 char *probin_str;
1029 char *prosrc_str;
1030 Node *prosqlbody;
1031 Oid prorettype;
1032 bool returnsSet;
1033 char *language;
1034 Oid languageOid;
1035 Oid languageValidator;
1036 Node *transformDefElem = NULL;
1037 char *funcname;
1038 Oid namespaceId;
1039 AclResult aclresult;
1040 oidvector *parameterTypes;
1041 List *parameterTypes_list = NIL;
1042 ArrayType *allParameterTypes;
1043 ArrayType *parameterModes;
1044 ArrayType *parameterNames;
1045 List *inParameterNames_list = NIL;
1046 List *parameterDefaults;
1047 Oid variadicArgType;
1048 List *trftypes_list = NIL;
1049 ArrayType *trftypes;
1050 Oid requiredResultType;
1051 bool isWindowFunc,
1052 isStrict,
1053 security,
1054 isLeakProof;
1055 char volatility;
1056 ArrayType *proconfig;
1057 float4 procost;
1058 float4 prorows;
1059 Oid prosupport;
1060 HeapTuple languageTuple;
1061 Form_pg_language languageStruct;
1062 List *as_clause;
1063 char parallel;
1065 /* Convert list of names to a name and namespace */
1066 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
1067 &funcname);
1069 /* Check we have creation rights in target namespace */
1070 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
1071 if (aclresult != ACLCHECK_OK)
1072 aclcheck_error(aclresult, OBJECT_SCHEMA,
1073 get_namespace_name(namespaceId));
1075 /* Set default attributes */
1076 as_clause = NIL;
1077 language = NULL;
1078 isWindowFunc = false;
1079 isStrict = false;
1080 security = false;
1081 isLeakProof = false;
1082 volatility = PROVOLATILE_VOLATILE;
1083 proconfig = NULL;
1084 procost = -1; /* indicates not set */
1085 prorows = -1; /* indicates not set */
1086 prosupport = InvalidOid;
1087 parallel = PROPARALLEL_UNSAFE;
1089 /* Extract non-default attributes from stmt->options list */
1090 compute_function_attributes(pstate,
1091 stmt->is_procedure,
1092 stmt->options,
1093 &as_clause, &language, &transformDefElem,
1094 &isWindowFunc, &volatility,
1095 &isStrict, &security, &isLeakProof,
1096 &proconfig, &procost, &prorows,
1097 &prosupport, &parallel);
1099 if (!language)
1101 if (stmt->sql_body)
1102 language = "sql";
1103 else
1104 ereport(ERROR,
1105 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1106 errmsg("no language specified")));
1109 /* Look up the language and validate permissions */
1110 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1111 if (!HeapTupleIsValid(languageTuple))
1112 ereport(ERROR,
1113 (errcode(ERRCODE_UNDEFINED_OBJECT),
1114 errmsg("language \"%s\" does not exist", language),
1115 (extension_file_exists(language) ?
1116 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1118 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1119 languageOid = languageStruct->oid;
1121 if (languageStruct->lanpltrusted)
1123 /* if trusted language, need USAGE privilege */
1124 aclresult = object_aclcheck(LanguageRelationId, languageOid, GetUserId(), ACL_USAGE);
1125 if (aclresult != ACLCHECK_OK)
1126 aclcheck_error(aclresult, OBJECT_LANGUAGE,
1127 NameStr(languageStruct->lanname));
1129 else
1131 /* if untrusted language, must be superuser */
1132 if (!superuser())
1133 aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE,
1134 NameStr(languageStruct->lanname));
1137 languageValidator = languageStruct->lanvalidator;
1139 ReleaseSysCache(languageTuple);
1142 * Only superuser is allowed to create leakproof functions because
1143 * leakproof functions can see tuples which have not yet been filtered out
1144 * by security barrier views or row-level security policies.
1146 if (isLeakProof && !superuser())
1147 ereport(ERROR,
1148 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1149 errmsg("only superuser can define a leakproof function")));
1151 if (transformDefElem)
1153 ListCell *lc;
1155 foreach(lc, castNode(List, transformDefElem))
1157 Oid typeid = typenameTypeId(NULL,
1158 lfirst_node(TypeName, lc));
1159 Oid elt = get_base_element_type(typeid);
1161 typeid = elt ? elt : typeid;
1163 get_transform_oid(typeid, languageOid, false);
1164 trftypes_list = lappend_oid(trftypes_list, typeid);
1169 * Convert remaining parameters of CREATE to form wanted by
1170 * ProcedureCreate.
1172 interpret_function_parameter_list(pstate,
1173 stmt->parameters,
1174 languageOid,
1175 stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION,
1176 &parameterTypes,
1177 &parameterTypes_list,
1178 &allParameterTypes,
1179 &parameterModes,
1180 &parameterNames,
1181 &inParameterNames_list,
1182 &parameterDefaults,
1183 &variadicArgType,
1184 &requiredResultType);
1186 if (stmt->is_procedure)
1188 Assert(!stmt->returnType);
1189 prorettype = requiredResultType ? requiredResultType : VOIDOID;
1190 returnsSet = false;
1192 else if (stmt->returnType)
1194 /* explicit RETURNS clause */
1195 compute_return_type(stmt->returnType, languageOid,
1196 &prorettype, &returnsSet);
1197 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1198 ereport(ERROR,
1199 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1200 errmsg("function result type must be %s because of OUT parameters",
1201 format_type_be(requiredResultType))));
1203 else if (OidIsValid(requiredResultType))
1205 /* default RETURNS clause from OUT parameters */
1206 prorettype = requiredResultType;
1207 returnsSet = false;
1209 else
1211 ereport(ERROR,
1212 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1213 errmsg("function result type must be specified")));
1214 /* Alternative possibility: default to RETURNS VOID */
1215 prorettype = VOIDOID;
1216 returnsSet = false;
1219 if (trftypes_list != NIL)
1221 ListCell *lc;
1222 Datum *arr;
1223 int i;
1225 arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1226 i = 0;
1227 foreach(lc, trftypes_list)
1228 arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1229 trftypes = construct_array_builtin(arr, list_length(trftypes_list), OIDOID);
1231 else
1233 /* store SQL NULL instead of empty array */
1234 trftypes = NULL;
1237 interpret_AS_clause(languageOid, language, funcname, as_clause, stmt->sql_body,
1238 parameterTypes_list, inParameterNames_list,
1239 &prosrc_str, &probin_str, &prosqlbody,
1240 pstate->p_sourcetext);
1243 * Set default values for COST and ROWS depending on other parameters;
1244 * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1245 * values, keep it in sync if you change them.
1247 if (procost < 0)
1249 /* SQL and PL-language functions are assumed more expensive */
1250 if (languageOid == INTERNALlanguageId ||
1251 languageOid == ClanguageId)
1252 procost = 1;
1253 else
1254 procost = 100;
1256 if (prorows < 0)
1258 if (returnsSet)
1259 prorows = 1000;
1260 else
1261 prorows = 0; /* dummy value if not returnsSet */
1263 else if (!returnsSet)
1264 ereport(ERROR,
1265 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1266 errmsg("ROWS is not applicable when function does not return a set")));
1269 * And now that we have all the parameters, and know we're permitted to do
1270 * so, go ahead and create the function.
1272 return ProcedureCreate(funcname,
1273 namespaceId,
1274 stmt->replace,
1275 returnsSet,
1276 prorettype,
1277 GetUserId(),
1278 languageOid,
1279 languageValidator,
1280 prosrc_str, /* converted to text later */
1281 probin_str, /* converted to text later */
1282 prosqlbody,
1283 stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1284 security,
1285 isLeakProof,
1286 isStrict,
1287 volatility,
1288 parallel,
1289 parameterTypes,
1290 PointerGetDatum(allParameterTypes),
1291 PointerGetDatum(parameterModes),
1292 PointerGetDatum(parameterNames),
1293 parameterDefaults,
1294 PointerGetDatum(trftypes),
1295 PointerGetDatum(proconfig),
1296 prosupport,
1297 procost,
1298 prorows);
1302 * Guts of function deletion.
1304 * Note: this is also used for aggregate deletion, since the OIDs of
1305 * both functions and aggregates point to pg_proc.
1307 void
1308 RemoveFunctionById(Oid funcOid)
1310 Relation relation;
1311 HeapTuple tup;
1312 char prokind;
1315 * Delete the pg_proc tuple.
1317 relation = table_open(ProcedureRelationId, RowExclusiveLock);
1319 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1320 if (!HeapTupleIsValid(tup)) /* should not happen */
1321 elog(ERROR, "cache lookup failed for function %u", funcOid);
1323 prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1325 CatalogTupleDelete(relation, &tup->t_self);
1327 ReleaseSysCache(tup);
1329 table_close(relation, RowExclusiveLock);
1331 pgstat_drop_function(funcOid);
1334 * If there's a pg_aggregate tuple, delete that too.
1336 if (prokind == PROKIND_AGGREGATE)
1338 relation = table_open(AggregateRelationId, RowExclusiveLock);
1340 tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1341 if (!HeapTupleIsValid(tup)) /* should not happen */
1342 elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1344 CatalogTupleDelete(relation, &tup->t_self);
1346 ReleaseSysCache(tup);
1348 table_close(relation, RowExclusiveLock);
1353 * Implements the ALTER FUNCTION utility command (except for the
1354 * RENAME and OWNER clauses, which are handled as part of the generic
1355 * ALTER framework).
1357 ObjectAddress
1358 AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
1360 HeapTuple tup;
1361 Oid funcOid;
1362 Form_pg_proc procForm;
1363 bool is_procedure;
1364 Relation rel;
1365 ListCell *l;
1366 DefElem *volatility_item = NULL;
1367 DefElem *strict_item = NULL;
1368 DefElem *security_def_item = NULL;
1369 DefElem *leakproof_item = NULL;
1370 List *set_items = NIL;
1371 DefElem *cost_item = NULL;
1372 DefElem *rows_item = NULL;
1373 DefElem *support_item = NULL;
1374 DefElem *parallel_item = NULL;
1375 ObjectAddress address;
1377 rel = table_open(ProcedureRelationId, RowExclusiveLock);
1379 funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1381 ObjectAddressSet(address, ProcedureRelationId, funcOid);
1383 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1384 if (!HeapTupleIsValid(tup)) /* should not happen */
1385 elog(ERROR, "cache lookup failed for function %u", funcOid);
1387 procForm = (Form_pg_proc) GETSTRUCT(tup);
1389 /* Permission check: must own function */
1390 if (!object_ownercheck(ProcedureRelationId, funcOid, GetUserId()))
1391 aclcheck_error(ACLCHECK_NOT_OWNER, stmt->objtype,
1392 NameListToString(stmt->func->objname));
1394 if (procForm->prokind == PROKIND_AGGREGATE)
1395 ereport(ERROR,
1396 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1397 errmsg("\"%s\" is an aggregate function",
1398 NameListToString(stmt->func->objname))));
1400 is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1402 /* Examine requested actions. */
1403 foreach(l, stmt->actions)
1405 DefElem *defel = (DefElem *) lfirst(l);
1407 if (compute_common_attribute(pstate,
1408 is_procedure,
1409 defel,
1410 &volatility_item,
1411 &strict_item,
1412 &security_def_item,
1413 &leakproof_item,
1414 &set_items,
1415 &cost_item,
1416 &rows_item,
1417 &support_item,
1418 &parallel_item) == false)
1419 elog(ERROR, "option \"%s\" not recognized", defel->defname);
1422 if (volatility_item)
1423 procForm->provolatile = interpret_func_volatility(volatility_item);
1424 if (strict_item)
1425 procForm->proisstrict = boolVal(strict_item->arg);
1426 if (security_def_item)
1427 procForm->prosecdef = boolVal(security_def_item->arg);
1428 if (leakproof_item)
1430 procForm->proleakproof = boolVal(leakproof_item->arg);
1431 if (procForm->proleakproof && !superuser())
1432 ereport(ERROR,
1433 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1434 errmsg("only superuser can define a leakproof function")));
1436 if (cost_item)
1438 procForm->procost = defGetNumeric(cost_item);
1439 if (procForm->procost <= 0)
1440 ereport(ERROR,
1441 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1442 errmsg("COST must be positive")));
1444 if (rows_item)
1446 procForm->prorows = defGetNumeric(rows_item);
1447 if (procForm->prorows <= 0)
1448 ereport(ERROR,
1449 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1450 errmsg("ROWS must be positive")));
1451 if (!procForm->proretset)
1452 ereport(ERROR,
1453 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1454 errmsg("ROWS is not applicable when function does not return a set")));
1456 if (support_item)
1458 /* interpret_func_support handles the privilege check */
1459 Oid newsupport = interpret_func_support(support_item);
1461 /* Add or replace dependency on support function */
1462 if (OidIsValid(procForm->prosupport))
1464 if (changeDependencyFor(ProcedureRelationId, funcOid,
1465 ProcedureRelationId, procForm->prosupport,
1466 newsupport) != 1)
1467 elog(ERROR, "could not change support dependency for function %s",
1468 get_func_name(funcOid));
1470 else
1472 ObjectAddress referenced;
1474 referenced.classId = ProcedureRelationId;
1475 referenced.objectId = newsupport;
1476 referenced.objectSubId = 0;
1477 recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1480 procForm->prosupport = newsupport;
1482 if (parallel_item)
1483 procForm->proparallel = interpret_func_parallel(parallel_item);
1484 if (set_items)
1486 Datum datum;
1487 bool isnull;
1488 ArrayType *a;
1489 Datum repl_val[Natts_pg_proc];
1490 bool repl_null[Natts_pg_proc];
1491 bool repl_repl[Natts_pg_proc];
1493 /* extract existing proconfig setting */
1494 datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1495 a = isnull ? NULL : DatumGetArrayTypeP(datum);
1497 /* update according to each SET or RESET item, left to right */
1498 a = update_proconfig_value(a, set_items);
1500 /* update the tuple */
1501 memset(repl_repl, false, sizeof(repl_repl));
1502 repl_repl[Anum_pg_proc_proconfig - 1] = true;
1504 if (a == NULL)
1506 repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1507 repl_null[Anum_pg_proc_proconfig - 1] = true;
1509 else
1511 repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1512 repl_null[Anum_pg_proc_proconfig - 1] = false;
1515 tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1516 repl_val, repl_null, repl_repl);
1518 /* DO NOT put more touches of procForm below here; it's now dangling. */
1520 /* Do the update */
1521 CatalogTupleUpdate(rel, &tup->t_self, tup);
1523 InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1525 table_close(rel, NoLock);
1526 heap_freetuple(tup);
1528 return address;
1533 * CREATE CAST
1535 ObjectAddress
1536 CreateCast(CreateCastStmt *stmt)
1538 Oid sourcetypeid;
1539 Oid targettypeid;
1540 char sourcetyptype;
1541 char targettyptype;
1542 Oid funcid;
1543 Oid incastid = InvalidOid;
1544 Oid outcastid = InvalidOid;
1545 int nargs;
1546 char castcontext;
1547 char castmethod;
1548 HeapTuple tuple;
1549 AclResult aclresult;
1550 ObjectAddress myself;
1552 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1553 targettypeid = typenameTypeId(NULL, stmt->targettype);
1554 sourcetyptype = get_typtype(sourcetypeid);
1555 targettyptype = get_typtype(targettypeid);
1557 /* No pseudo-types allowed */
1558 if (sourcetyptype == TYPTYPE_PSEUDO)
1559 ereport(ERROR,
1560 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1561 errmsg("source data type %s is a pseudo-type",
1562 TypeNameToString(stmt->sourcetype))));
1564 if (targettyptype == TYPTYPE_PSEUDO)
1565 ereport(ERROR,
1566 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1567 errmsg("target data type %s is a pseudo-type",
1568 TypeNameToString(stmt->targettype))));
1570 /* Permission check */
1571 if (!object_ownercheck(TypeRelationId, sourcetypeid, GetUserId())
1572 && !object_ownercheck(TypeRelationId, targettypeid, GetUserId()))
1573 ereport(ERROR,
1574 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1575 errmsg("must be owner of type %s or type %s",
1576 format_type_be(sourcetypeid),
1577 format_type_be(targettypeid))));
1579 aclresult = object_aclcheck(TypeRelationId, sourcetypeid, GetUserId(), ACL_USAGE);
1580 if (aclresult != ACLCHECK_OK)
1581 aclcheck_error_type(aclresult, sourcetypeid);
1583 aclresult = object_aclcheck(TypeRelationId, targettypeid, GetUserId(), ACL_USAGE);
1584 if (aclresult != ACLCHECK_OK)
1585 aclcheck_error_type(aclresult, targettypeid);
1587 /* Domains are allowed for historical reasons, but we warn */
1588 if (sourcetyptype == TYPTYPE_DOMAIN)
1589 ereport(WARNING,
1590 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1591 errmsg("cast will be ignored because the source data type is a domain")));
1593 else if (targettyptype == TYPTYPE_DOMAIN)
1594 ereport(WARNING,
1595 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1596 errmsg("cast will be ignored because the target data type is a domain")));
1598 /* Determine the cast method */
1599 if (stmt->func != NULL)
1600 castmethod = COERCION_METHOD_FUNCTION;
1601 else if (stmt->inout)
1602 castmethod = COERCION_METHOD_INOUT;
1603 else
1604 castmethod = COERCION_METHOD_BINARY;
1606 if (castmethod == COERCION_METHOD_FUNCTION)
1608 Form_pg_proc procstruct;
1610 funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1612 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1613 if (!HeapTupleIsValid(tuple))
1614 elog(ERROR, "cache lookup failed for function %u", funcid);
1616 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1617 nargs = procstruct->pronargs;
1618 if (nargs < 1 || nargs > 3)
1619 ereport(ERROR,
1620 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1621 errmsg("cast function must take one to three arguments")));
1622 if (!IsBinaryCoercibleWithCast(sourcetypeid,
1623 procstruct->proargtypes.values[0],
1624 &incastid))
1625 ereport(ERROR,
1626 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1627 errmsg("argument of cast function must match or be binary-coercible from source data type")));
1628 if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1629 ereport(ERROR,
1630 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1631 errmsg("second argument of cast function must be type %s",
1632 "integer")));
1633 if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1634 ereport(ERROR,
1635 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1636 errmsg("third argument of cast function must be type %s",
1637 "boolean")));
1638 if (!IsBinaryCoercibleWithCast(procstruct->prorettype,
1639 targettypeid,
1640 &outcastid))
1641 ereport(ERROR,
1642 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1643 errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1646 * Restricting the volatility of a cast function may or may not be a
1647 * good idea in the abstract, but it definitely breaks many old
1648 * user-defined types. Disable this check --- tgl 2/1/03
1650 #ifdef NOT_USED
1651 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1652 ereport(ERROR,
1653 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1654 errmsg("cast function must not be volatile")));
1655 #endif
1656 if (procstruct->prokind != PROKIND_FUNCTION)
1657 ereport(ERROR,
1658 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1659 errmsg("cast function must be a normal function")));
1660 if (procstruct->proretset)
1661 ereport(ERROR,
1662 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1663 errmsg("cast function must not return a set")));
1665 ReleaseSysCache(tuple);
1667 else
1669 funcid = InvalidOid;
1670 nargs = 0;
1673 if (castmethod == COERCION_METHOD_BINARY)
1675 int16 typ1len;
1676 int16 typ2len;
1677 bool typ1byval;
1678 bool typ2byval;
1679 char typ1align;
1680 char typ2align;
1683 * Must be superuser to create binary-compatible casts, since
1684 * erroneous casts can easily crash the backend.
1686 if (!superuser())
1687 ereport(ERROR,
1688 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1689 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1692 * Also, insist that the types match as to size, alignment, and
1693 * pass-by-value attributes; this provides at least a crude check that
1694 * they have similar representations. A pair of types that fail this
1695 * test should certainly not be equated.
1697 get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1698 get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1699 if (typ1len != typ2len ||
1700 typ1byval != typ2byval ||
1701 typ1align != typ2align)
1702 ereport(ERROR,
1703 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1704 errmsg("source and target data types are not physically compatible")));
1707 * We know that composite, array, range and enum types are never
1708 * binary-compatible with each other. They all have OIDs embedded in
1709 * them.
1711 * Theoretically you could build a user-defined base type that is
1712 * binary-compatible with such a type. But we disallow it anyway, as
1713 * in practice such a cast is surely a mistake. You can always work
1714 * around that by writing a cast function.
1716 * NOTE: if we ever have a kind of container type that doesn't need to
1717 * be rejected for this reason, we'd likely need to recursively apply
1718 * all of these same checks to the contained type(s).
1720 if (sourcetyptype == TYPTYPE_COMPOSITE ||
1721 targettyptype == TYPTYPE_COMPOSITE)
1722 ereport(ERROR,
1723 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1724 errmsg("composite data types are not binary-compatible")));
1726 if (OidIsValid(get_element_type(sourcetypeid)) ||
1727 OidIsValid(get_element_type(targettypeid)))
1728 ereport(ERROR,
1729 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1730 errmsg("array data types are not binary-compatible")));
1732 if (sourcetyptype == TYPTYPE_RANGE ||
1733 targettyptype == TYPTYPE_RANGE ||
1734 sourcetyptype == TYPTYPE_MULTIRANGE ||
1735 targettyptype == TYPTYPE_MULTIRANGE)
1736 ereport(ERROR,
1737 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1738 errmsg("range data types are not binary-compatible")));
1740 if (sourcetyptype == TYPTYPE_ENUM ||
1741 targettyptype == TYPTYPE_ENUM)
1742 ereport(ERROR,
1743 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1744 errmsg("enum data types are not binary-compatible")));
1747 * We also disallow creating binary-compatibility casts involving
1748 * domains. Casting from a domain to its base type is already
1749 * allowed, and casting the other way ought to go through domain
1750 * coercion to permit constraint checking. Again, if you're intent on
1751 * having your own semantics for that, create a no-op cast function.
1753 * NOTE: if we were to relax this, the above checks for composites
1754 * etc. would have to be modified to look through domains to their
1755 * base types.
1757 if (sourcetyptype == TYPTYPE_DOMAIN ||
1758 targettyptype == TYPTYPE_DOMAIN)
1759 ereport(ERROR,
1760 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1761 errmsg("domain data types must not be marked binary-compatible")));
1765 * Allow source and target types to be same only for length coercion
1766 * functions. We assume a multi-arg function does length coercion.
1768 if (sourcetypeid == targettypeid && nargs < 2)
1769 ereport(ERROR,
1770 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1771 errmsg("source data type and target data type are the same")));
1773 /* convert CoercionContext enum to char value for castcontext */
1774 switch (stmt->context)
1776 case COERCION_IMPLICIT:
1777 castcontext = COERCION_CODE_IMPLICIT;
1778 break;
1779 case COERCION_ASSIGNMENT:
1780 castcontext = COERCION_CODE_ASSIGNMENT;
1781 break;
1782 /* COERCION_PLPGSQL is intentionally not covered here */
1783 case COERCION_EXPLICIT:
1784 castcontext = COERCION_CODE_EXPLICIT;
1785 break;
1786 default:
1787 elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1788 castcontext = 0; /* keep compiler quiet */
1789 break;
1792 myself = CastCreate(sourcetypeid, targettypeid, funcid, incastid, outcastid,
1793 castcontext, castmethod, DEPENDENCY_NORMAL);
1794 return myself;
1798 static void
1799 check_transform_function(Form_pg_proc procstruct)
1801 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1802 ereport(ERROR,
1803 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1804 errmsg("transform function must not be volatile")));
1805 if (procstruct->prokind != PROKIND_FUNCTION)
1806 ereport(ERROR,
1807 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1808 errmsg("transform function must be a normal function")));
1809 if (procstruct->proretset)
1810 ereport(ERROR,
1811 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1812 errmsg("transform function must not return a set")));
1813 if (procstruct->pronargs != 1)
1814 ereport(ERROR,
1815 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1816 errmsg("transform function must take one argument")));
1817 if (procstruct->proargtypes.values[0] != INTERNALOID)
1818 ereport(ERROR,
1819 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1820 errmsg("first argument of transform function must be type %s",
1821 "internal")));
1826 * CREATE TRANSFORM
1828 ObjectAddress
1829 CreateTransform(CreateTransformStmt *stmt)
1831 Oid typeid;
1832 char typtype;
1833 Oid langid;
1834 Oid fromsqlfuncid;
1835 Oid tosqlfuncid;
1836 AclResult aclresult;
1837 Form_pg_proc procstruct;
1838 Datum values[Natts_pg_transform];
1839 bool nulls[Natts_pg_transform] = {0};
1840 bool replaces[Natts_pg_transform] = {0};
1841 Oid transformid;
1842 HeapTuple tuple;
1843 HeapTuple newtuple;
1844 Relation relation;
1845 ObjectAddress myself,
1846 referenced;
1847 ObjectAddresses *addrs;
1848 bool is_replace;
1851 * Get the type
1853 typeid = typenameTypeId(NULL, stmt->type_name);
1854 typtype = get_typtype(typeid);
1856 if (typtype == TYPTYPE_PSEUDO)
1857 ereport(ERROR,
1858 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1859 errmsg("data type %s is a pseudo-type",
1860 TypeNameToString(stmt->type_name))));
1862 if (typtype == TYPTYPE_DOMAIN)
1863 ereport(ERROR,
1864 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1865 errmsg("data type %s is a domain",
1866 TypeNameToString(stmt->type_name))));
1868 if (!object_ownercheck(TypeRelationId, typeid, GetUserId()))
1869 aclcheck_error_type(ACLCHECK_NOT_OWNER, typeid);
1871 aclresult = object_aclcheck(TypeRelationId, typeid, GetUserId(), ACL_USAGE);
1872 if (aclresult != ACLCHECK_OK)
1873 aclcheck_error_type(aclresult, typeid);
1876 * Get the language
1878 langid = get_language_oid(stmt->lang, false);
1880 aclresult = object_aclcheck(LanguageRelationId, langid, GetUserId(), ACL_USAGE);
1881 if (aclresult != ACLCHECK_OK)
1882 aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1885 * Get the functions
1887 if (stmt->fromsql)
1889 fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1891 if (!object_ownercheck(ProcedureRelationId, fromsqlfuncid, GetUserId()))
1892 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1894 aclresult = object_aclcheck(ProcedureRelationId, fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1895 if (aclresult != ACLCHECK_OK)
1896 aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1898 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1899 if (!HeapTupleIsValid(tuple))
1900 elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1901 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1902 if (procstruct->prorettype != INTERNALOID)
1903 ereport(ERROR,
1904 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1905 errmsg("return data type of FROM SQL function must be %s",
1906 "internal")));
1907 check_transform_function(procstruct);
1908 ReleaseSysCache(tuple);
1910 else
1911 fromsqlfuncid = InvalidOid;
1913 if (stmt->tosql)
1915 tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1917 if (!object_ownercheck(ProcedureRelationId, tosqlfuncid, GetUserId()))
1918 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1920 aclresult = object_aclcheck(ProcedureRelationId, tosqlfuncid, GetUserId(), ACL_EXECUTE);
1921 if (aclresult != ACLCHECK_OK)
1922 aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1924 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1925 if (!HeapTupleIsValid(tuple))
1926 elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1927 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1928 if (procstruct->prorettype != typeid)
1929 ereport(ERROR,
1930 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1931 errmsg("return data type of TO SQL function must be the transform data type")));
1932 check_transform_function(procstruct);
1933 ReleaseSysCache(tuple);
1935 else
1936 tosqlfuncid = InvalidOid;
1939 * Ready to go
1941 values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1942 values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1943 values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1944 values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1946 relation = table_open(TransformRelationId, RowExclusiveLock);
1948 tuple = SearchSysCache2(TRFTYPELANG,
1949 ObjectIdGetDatum(typeid),
1950 ObjectIdGetDatum(langid));
1951 if (HeapTupleIsValid(tuple))
1953 Form_pg_transform form = (Form_pg_transform) GETSTRUCT(tuple);
1955 if (!stmt->replace)
1956 ereport(ERROR,
1957 (errcode(ERRCODE_DUPLICATE_OBJECT),
1958 errmsg("transform for type %s language \"%s\" already exists",
1959 format_type_be(typeid),
1960 stmt->lang)));
1962 replaces[Anum_pg_transform_trffromsql - 1] = true;
1963 replaces[Anum_pg_transform_trftosql - 1] = true;
1965 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1966 CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1968 transformid = form->oid;
1969 ReleaseSysCache(tuple);
1970 is_replace = true;
1972 else
1974 transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1975 Anum_pg_transform_oid);
1976 values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1977 newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1978 CatalogTupleInsert(relation, newtuple);
1979 is_replace = false;
1982 if (is_replace)
1983 deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1985 addrs = new_object_addresses();
1987 /* make dependency entries */
1988 ObjectAddressSet(myself, TransformRelationId, transformid);
1990 /* dependency on language */
1991 ObjectAddressSet(referenced, LanguageRelationId, langid);
1992 add_exact_object_address(&referenced, addrs);
1994 /* dependency on type */
1995 ObjectAddressSet(referenced, TypeRelationId, typeid);
1996 add_exact_object_address(&referenced, addrs);
1998 /* dependencies on functions */
1999 if (OidIsValid(fromsqlfuncid))
2001 ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
2002 add_exact_object_address(&referenced, addrs);
2004 if (OidIsValid(tosqlfuncid))
2006 ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
2007 add_exact_object_address(&referenced, addrs);
2010 record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
2011 free_object_addresses(addrs);
2013 /* dependency on extension */
2014 recordDependencyOnCurrentExtension(&myself, is_replace);
2016 /* Post creation hook for new transform */
2017 InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
2019 heap_freetuple(newtuple);
2021 table_close(relation, RowExclusiveLock);
2023 return myself;
2028 * get_transform_oid - given type OID and language OID, look up a transform OID
2030 * If missing_ok is false, throw an error if the transform is not found. If
2031 * true, just return InvalidOid.
2034 get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
2036 Oid oid;
2038 oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2039 ObjectIdGetDatum(type_id),
2040 ObjectIdGetDatum(lang_id));
2041 if (!OidIsValid(oid) && !missing_ok)
2042 ereport(ERROR,
2043 (errcode(ERRCODE_UNDEFINED_OBJECT),
2044 errmsg("transform for type %s language \"%s\" does not exist",
2045 format_type_be(type_id),
2046 get_language_name(lang_id, false))));
2047 return oid;
2052 * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA/RENAME
2054 * Is there a function with the given name and signature already in the given
2055 * namespace? If so, raise an appropriate error message.
2057 void
2058 IsThereFunctionInNamespace(const char *proname, int pronargs,
2059 oidvector *proargtypes, Oid nspOid)
2061 /* check for duplicate name (more friendly than unique-index failure) */
2062 if (SearchSysCacheExists3(PROCNAMEARGSNSP,
2063 CStringGetDatum(proname),
2064 PointerGetDatum(proargtypes),
2065 ObjectIdGetDatum(nspOid)))
2066 ereport(ERROR,
2067 (errcode(ERRCODE_DUPLICATE_FUNCTION),
2068 errmsg("function %s already exists in schema \"%s\"",
2069 funcname_signature_string(proname, pronargs,
2070 NIL, proargtypes->values),
2071 get_namespace_name(nspOid))));
2075 * ExecuteDoStmt
2076 * Execute inline procedural-language code
2078 * See at ExecuteCallStmt() about the atomic argument.
2080 void
2081 ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
2083 InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
2084 ListCell *arg;
2085 DefElem *as_item = NULL;
2086 DefElem *language_item = NULL;
2087 char *language;
2088 Oid laninline;
2089 HeapTuple languageTuple;
2090 Form_pg_language languageStruct;
2092 /* Process options we got from gram.y */
2093 foreach(arg, stmt->args)
2095 DefElem *defel = (DefElem *) lfirst(arg);
2097 if (strcmp(defel->defname, "as") == 0)
2099 if (as_item)
2100 errorConflictingDefElem(defel, pstate);
2101 as_item = defel;
2103 else if (strcmp(defel->defname, "language") == 0)
2105 if (language_item)
2106 errorConflictingDefElem(defel, pstate);
2107 language_item = defel;
2109 else
2110 elog(ERROR, "option \"%s\" not recognized",
2111 defel->defname);
2114 if (as_item)
2115 codeblock->source_text = strVal(as_item->arg);
2116 else
2117 ereport(ERROR,
2118 (errcode(ERRCODE_SYNTAX_ERROR),
2119 errmsg("no inline code specified")));
2121 /* if LANGUAGE option wasn't specified, use the default */
2122 if (language_item)
2123 language = strVal(language_item->arg);
2124 else
2125 language = "plpgsql";
2127 /* Look up the language and validate permissions */
2128 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2129 if (!HeapTupleIsValid(languageTuple))
2130 ereport(ERROR,
2131 (errcode(ERRCODE_UNDEFINED_OBJECT),
2132 errmsg("language \"%s\" does not exist", language),
2133 (extension_file_exists(language) ?
2134 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2136 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2137 codeblock->langOid = languageStruct->oid;
2138 codeblock->langIsTrusted = languageStruct->lanpltrusted;
2139 codeblock->atomic = atomic;
2141 if (languageStruct->lanpltrusted)
2143 /* if trusted language, need USAGE privilege */
2144 AclResult aclresult;
2146 aclresult = object_aclcheck(LanguageRelationId, codeblock->langOid, GetUserId(),
2147 ACL_USAGE);
2148 if (aclresult != ACLCHECK_OK)
2149 aclcheck_error(aclresult, OBJECT_LANGUAGE,
2150 NameStr(languageStruct->lanname));
2152 else
2154 /* if untrusted language, must be superuser */
2155 if (!superuser())
2156 aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_LANGUAGE,
2157 NameStr(languageStruct->lanname));
2160 /* get the handler function's OID */
2161 laninline = languageStruct->laninline;
2162 if (!OidIsValid(laninline))
2163 ereport(ERROR,
2164 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2165 errmsg("language \"%s\" does not support inline code execution",
2166 NameStr(languageStruct->lanname))));
2168 ReleaseSysCache(languageTuple);
2170 /* execute the inline handler */
2171 OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2175 * Execute CALL statement
2177 * Inside a top-level CALL statement, transaction-terminating commands such as
2178 * COMMIT or a PL-specific equivalent are allowed. The terminology in the SQL
2179 * standard is that CALL establishes a non-atomic execution context. Most
2180 * other commands establish an atomic execution context, in which transaction
2181 * control actions are not allowed. If there are nested executions of CALL,
2182 * we want to track the execution context recursively, so that the nested
2183 * CALLs can also do transaction control. Note, however, that for example in
2184 * CALL -> SELECT -> CALL, the second call cannot do transaction control,
2185 * because the SELECT in between establishes an atomic execution context.
2187 * So when ExecuteCallStmt() is called from the top level, we pass in atomic =
2188 * false (recall that that means transactions = yes). We then create a
2189 * CallContext node with content atomic = false, which is passed in the
2190 * fcinfo->context field to the procedure invocation. The language
2191 * implementation should then take appropriate measures to allow or prevent
2192 * transaction commands based on that information, e.g., call
2193 * SPI_connect_ext(SPI_OPT_NONATOMIC). The language should also pass on the
2194 * atomic flag to any nested invocations to CALL.
2196 * The expression data structures and execution context that we create
2197 * within this function are children of the portalContext of the Portal
2198 * that the CALL utility statement runs in. Therefore, any pass-by-ref
2199 * values that we're passing to the procedure will survive transaction
2200 * commits that might occur inside the procedure.
2202 void
2203 ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
2205 LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2206 ListCell *lc;
2207 FuncExpr *fexpr;
2208 int nargs;
2209 int i;
2210 AclResult aclresult;
2211 FmgrInfo flinfo;
2212 CallContext *callcontext;
2213 EState *estate;
2214 ExprContext *econtext;
2215 HeapTuple tp;
2216 PgStat_FunctionCallUsage fcusage;
2217 Datum retval;
2219 fexpr = stmt->funcexpr;
2220 Assert(fexpr);
2221 Assert(IsA(fexpr, FuncExpr));
2223 aclresult = object_aclcheck(ProcedureRelationId, fexpr->funcid, GetUserId(), ACL_EXECUTE);
2224 if (aclresult != ACLCHECK_OK)
2225 aclcheck_error(aclresult, OBJECT_PROCEDURE, get_func_name(fexpr->funcid));
2227 /* Prep the context object we'll pass to the procedure */
2228 callcontext = makeNode(CallContext);
2229 callcontext->atomic = atomic;
2231 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2232 if (!HeapTupleIsValid(tp))
2233 elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2236 * If proconfig is set we can't allow transaction commands because of the
2237 * way the GUC stacking works: The transaction boundary would have to pop
2238 * the proconfig setting off the stack. That restriction could be lifted
2239 * by redesigning the GUC nesting mechanism a bit.
2241 if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2242 callcontext->atomic = true;
2245 * In security definer procedures, we can't allow transaction commands.
2246 * StartTransaction() insists that the security context stack is empty,
2247 * and AbortTransaction() resets the security context. This could be
2248 * reorganized, but right now it doesn't work.
2250 if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2251 callcontext->atomic = true;
2253 ReleaseSysCache(tp);
2255 /* safety check; see ExecInitFunc() */
2256 nargs = list_length(fexpr->args);
2257 if (nargs > FUNC_MAX_ARGS)
2258 ereport(ERROR,
2259 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2260 errmsg_plural("cannot pass more than %d argument to a procedure",
2261 "cannot pass more than %d arguments to a procedure",
2262 FUNC_MAX_ARGS,
2263 FUNC_MAX_ARGS)));
2265 /* Initialize function call structure */
2266 InvokeFunctionExecuteHook(fexpr->funcid);
2267 fmgr_info(fexpr->funcid, &flinfo);
2268 fmgr_info_set_expr((Node *) fexpr, &flinfo);
2269 InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2270 (Node *) callcontext, NULL);
2273 * Evaluate procedure arguments inside a suitable execution context. Note
2274 * we can't free this context till the procedure returns.
2276 estate = CreateExecutorState();
2277 estate->es_param_list_info = params;
2278 econtext = CreateExprContext(estate);
2281 * If we're called in non-atomic context, we also have to ensure that the
2282 * argument expressions run with an up-to-date snapshot. Our caller will
2283 * have provided a current snapshot in atomic contexts, but not in
2284 * non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2285 * destroying the snapshot makes higher-level management too complicated.
2287 if (!atomic)
2288 PushActiveSnapshot(GetTransactionSnapshot());
2290 i = 0;
2291 foreach(lc, fexpr->args)
2293 ExprState *exprstate;
2294 Datum val;
2295 bool isnull;
2297 exprstate = ExecPrepareExpr(lfirst(lc), estate);
2299 val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2301 fcinfo->args[i].value = val;
2302 fcinfo->args[i].isnull = isnull;
2304 i++;
2307 /* Get rid of temporary snapshot for arguments, if we made one */
2308 if (!atomic)
2309 PopActiveSnapshot();
2311 /* Here we actually call the procedure */
2312 pgstat_init_function_usage(fcinfo, &fcusage);
2313 retval = FunctionCallInvoke(fcinfo);
2314 pgstat_end_function_usage(&fcusage, true);
2316 /* Handle the procedure's outputs */
2317 if (fexpr->funcresulttype == VOIDOID)
2319 /* do nothing */
2321 else if (fexpr->funcresulttype == RECORDOID)
2323 /* send tuple to client */
2324 HeapTupleHeader td;
2325 Oid tupType;
2326 int32 tupTypmod;
2327 TupleDesc retdesc;
2328 HeapTupleData rettupdata;
2329 TupOutputState *tstate;
2330 TupleTableSlot *slot;
2332 if (fcinfo->isnull)
2333 elog(ERROR, "procedure returned null record");
2336 * Ensure there's an active snapshot whilst we execute whatever's
2337 * involved here. Note that this is *not* sufficient to make the
2338 * world safe for TOAST pointers to be included in the returned data:
2339 * the referenced data could have gone away while we didn't hold a
2340 * snapshot. Hence, it's incumbent on PLs that can do COMMIT/ROLLBACK
2341 * to not return TOAST pointers, unless those pointers were fetched
2342 * after the last COMMIT/ROLLBACK in the procedure.
2344 * XXX that is a really nasty, hard-to-test requirement. Is there a
2345 * way to remove it?
2347 EnsurePortalSnapshotExists();
2349 td = DatumGetHeapTupleHeader(retval);
2350 tupType = HeapTupleHeaderGetTypeId(td);
2351 tupTypmod = HeapTupleHeaderGetTypMod(td);
2352 retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2354 tstate = begin_tup_output_tupdesc(dest, retdesc,
2355 &TTSOpsHeapTuple);
2357 rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2358 ItemPointerSetInvalid(&(rettupdata.t_self));
2359 rettupdata.t_tableOid = InvalidOid;
2360 rettupdata.t_data = td;
2362 slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2363 tstate->dest->receiveSlot(slot, tstate->dest);
2365 end_tup_output(tstate);
2367 ReleaseTupleDesc(retdesc);
2369 else
2370 elog(ERROR, "unexpected result type for procedure: %u",
2371 fexpr->funcresulttype);
2373 FreeExecutorState(estate);
2377 * Construct the tuple descriptor for a CALL statement return
2379 TupleDesc
2380 CallStmtResultDesc(CallStmt *stmt)
2382 FuncExpr *fexpr;
2383 HeapTuple tuple;
2384 TupleDesc tupdesc;
2386 fexpr = stmt->funcexpr;
2388 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2389 if (!HeapTupleIsValid(tuple))
2390 elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2392 tupdesc = build_function_result_tupdesc_t(tuple);
2394 ReleaseSysCache(tuple);
2397 * The result of build_function_result_tupdesc_t has the right column
2398 * names, but it just has the declared output argument types, which is the
2399 * wrong thing in polymorphic cases. Get the correct types by examining
2400 * stmt->outargs. We intentionally keep the atttypmod as -1 and the
2401 * attcollation as the type's default, since that's always the appropriate
2402 * thing for function outputs; there's no point in considering any
2403 * additional info available from outargs. Note that tupdesc is null if
2404 * there are no outargs.
2406 if (tupdesc)
2408 Assert(tupdesc->natts == list_length(stmt->outargs));
2409 for (int i = 0; i < tupdesc->natts; i++)
2411 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2412 Node *outarg = (Node *) list_nth(stmt->outargs, i);
2414 TupleDescInitEntry(tupdesc,
2415 i + 1,
2416 NameStr(att->attname),
2417 exprType(outarg),
2423 return tupdesc;