PostgreSQL Source Code git master
functioncmds.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * functioncmds.c
4 *
5 * Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
6 * CAST commands.
7 *
8 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
10 *
11 *
12 * IDENTIFICATION
13 * src/backend/commands/functioncmds.c
14 *
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.
21 *
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
30 *
31 *-------------------------------------------------------------------------
32 */
33#include "postgres.h"
34
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"
42#include "catalog/pg_cast.h"
43#include "catalog/pg_language.h"
45#include "catalog/pg_proc.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"
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"
74
75/*
76 * Examine the RETURNS clause of the CREATE FUNCTION statement
77 * and return information about it as *prorettype_p and *returnsSet_p.
78 *
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.)
86 */
87static void
88compute_return_type(TypeName *returnType, Oid languageOid,
89 Oid *prorettype_p, bool *returnsSet_p)
90{
91 Oid rettype;
92 Type typtup;
93 AclResult aclresult;
94
95 typtup = LookupTypeName(NULL, returnType, NULL, false);
96
97 if (typtup)
98 {
99 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
100 {
101 if (languageOid == SQLlanguageId)
103 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
104 errmsg("SQL function cannot return shell type %s",
105 TypeNameToString(returnType))));
106 else
108 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
109 errmsg("return type %s is only a shell",
110 TypeNameToString(returnType))));
111 }
112 rettype = typeTypeId(typtup);
113 ReleaseSysCache(typtup);
114 }
115 else
116 {
117 char *typnam = TypeNameToString(returnType);
118 Oid namespaceId;
119 char *typname;
120 ObjectAddress address;
121
122 /*
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.
127 */
128 if (languageOid != INTERNALlanguageId &&
129 languageOid != ClanguageId)
131 (errcode(ERRCODE_UNDEFINED_OBJECT),
132 errmsg("type \"%s\" does not exist", typnam)));
133
134 /* Reject if there's typmod decoration, too */
135 if (returnType->typmods != NIL)
137 (errcode(ERRCODE_SYNTAX_ERROR),
138 errmsg("type modifier cannot be specified for shell type \"%s\"",
139 typnam)));
140
141 /* Otherwise, go ahead and make a shell type */
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));
156 /* Ensure the new shell type is visible to ProcedureCreate */
158 }
159
160 aclresult = object_aclcheck(TypeRelationId, rettype, GetUserId(), ACL_USAGE);
161 if (aclresult != ACLCHECK_OK)
162 aclcheck_error_type(aclresult, rettype);
163
164 *prorettype_p = rettype;
165 *returnsSet_p = returnType->setof;
166}
167
168/*
169 * Interpret the function parameter list of a CREATE FUNCTION,
170 * CREATE PROCEDURE, or CREATE AGGREGATE statement.
171 *
172 * Input parameters:
173 * parameters: list of FunctionParameter structs
174 * languageOid: OID of function language (InvalidOid if it's CREATE AGGREGATE)
175 * objtype: identifies type of object being created
176 *
177 * Results are stored into output parameters. parameterTypes must always
178 * be created, but the other arrays/lists can be NULL pointers if not needed.
179 * variadicArgType is set to the variadic array type if there's a VARIADIC
180 * parameter (there can be only one); or to InvalidOid if not.
181 * requiredResultType is set to InvalidOid if there are no OUT parameters,
182 * else it is set to the OID of the implied result type.
183 */
184void
186 List *parameters,
187 Oid languageOid,
188 ObjectType objtype,
189 oidvector **parameterTypes,
190 List **parameterTypes_list,
191 ArrayType **allParameterTypes,
192 ArrayType **parameterModes,
193 ArrayType **parameterNames,
194 List **inParameterNames_list,
195 List **parameterDefaults,
196 Oid *variadicArgType,
197 Oid *requiredResultType)
198{
199 int parameterCount = list_length(parameters);
200 Oid *inTypes;
201 int inCount = 0;
202 Datum *allTypes;
203 Datum *paramModes;
204 Datum *paramNames;
205 int outCount = 0;
206 int varCount = 0;
207 bool have_names = false;
208 bool have_defaults = false;
209 ListCell *x;
210 int i;
211
212 *variadicArgType = InvalidOid; /* default result */
213 *requiredResultType = InvalidOid; /* default result */
214
215 inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
216 allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
217 paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
218 paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
219 *parameterDefaults = NIL;
220
221 /* Scan the list and extract data into work arrays */
222 i = 0;
223 foreach(x, parameters)
224 {
226 TypeName *t = fp->argType;
227 FunctionParameterMode fpmode = fp->mode;
228 bool isinput = false;
229 Oid toid;
230 Type typtup;
231 AclResult aclresult;
232
233 /* For our purposes here, a defaulted mode spec is identical to IN */
234 if (fpmode == FUNC_PARAM_DEFAULT)
235 fpmode = FUNC_PARAM_IN;
236
237 typtup = LookupTypeName(pstate, t, NULL, false);
238 if (typtup)
239 {
240 if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
241 {
242 /* As above, hard error if language is SQL */
243 if (languageOid == SQLlanguageId)
245 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
246 errmsg("SQL function cannot accept shell type %s",
248 parser_errposition(pstate, t->location)));
249 /* We don't allow creating aggregates on shell types either */
250 else if (objtype == OBJECT_AGGREGATE)
252 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
253 errmsg("aggregate cannot accept shell type %s",
255 parser_errposition(pstate, t->location)));
256 else
258 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
259 errmsg("argument type %s is only a shell",
261 parser_errposition(pstate, t->location)));
262 }
263 toid = typeTypeId(typtup);
264 ReleaseSysCache(typtup);
265 }
266 else
267 {
269 (errcode(ERRCODE_UNDEFINED_OBJECT),
270 errmsg("type %s does not exist",
272 parser_errposition(pstate, t->location)));
273 toid = InvalidOid; /* keep compiler quiet */
274 }
275
276 aclresult = object_aclcheck(TypeRelationId, toid, GetUserId(), ACL_USAGE);
277 if (aclresult != ACLCHECK_OK)
278 aclcheck_error_type(aclresult, toid);
279
280 if (t->setof)
281 {
282 if (objtype == OBJECT_AGGREGATE)
284 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
285 errmsg("aggregates cannot accept set arguments"),
286 parser_errposition(pstate, fp->location)));
287 else if (objtype == OBJECT_PROCEDURE)
289 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
290 errmsg("procedures cannot accept set arguments"),
291 parser_errposition(pstate, fp->location)));
292 else
294 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
295 errmsg("functions cannot accept set arguments"),
296 parser_errposition(pstate, fp->location)));
297 }
298
299 /* handle input parameters */
300 if (fpmode != FUNC_PARAM_OUT && fpmode != FUNC_PARAM_TABLE)
301 {
302 /* other input parameters can't follow a VARIADIC parameter */
303 if (varCount > 0)
305 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
306 errmsg("VARIADIC parameter must be the last input parameter"),
307 parser_errposition(pstate, fp->location)));
308 inTypes[inCount++] = toid;
309 isinput = true;
310 if (parameterTypes_list)
311 *parameterTypes_list = lappend_oid(*parameterTypes_list, toid);
312 }
313
314 /* handle output parameters */
315 if (fpmode != FUNC_PARAM_IN && fpmode != FUNC_PARAM_VARIADIC)
316 {
317 if (objtype == OBJECT_PROCEDURE)
318 {
319 /*
320 * We disallow OUT-after-VARIADIC only for procedures. While
321 * such a case causes no confusion in ordinary function calls,
322 * it would cause confusion in a CALL statement.
323 */
324 if (varCount > 0)
326 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
327 errmsg("VARIADIC parameter must be the last parameter"),
328 parser_errposition(pstate, fp->location)));
329 /* Procedures with output parameters always return RECORD */
330 *requiredResultType = RECORDOID;
331 }
332 else if (outCount == 0) /* save first output param's type */
333 *requiredResultType = toid;
334 outCount++;
335 }
336
337 if (fpmode == FUNC_PARAM_VARIADIC)
338 {
339 *variadicArgType = toid;
340 varCount++;
341 /* validate variadic parameter type */
342 switch (toid)
343 {
344 case ANYARRAYOID:
345 case ANYCOMPATIBLEARRAYOID:
346 case ANYOID:
347 /* okay */
348 break;
349 default:
350 if (!OidIsValid(get_element_type(toid)))
352 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
353 errmsg("VARIADIC parameter must be an array"),
354 parser_errposition(pstate, fp->location)));
355 break;
356 }
357 }
358
359 allTypes[i] = ObjectIdGetDatum(toid);
360
361 paramModes[i] = CharGetDatum(fpmode);
362
363 if (fp->name && fp->name[0])
364 {
365 ListCell *px;
366
367 /*
368 * As of Postgres 9.0 we disallow using the same name for two
369 * input or two output function parameters. Depending on the
370 * function's language, conflicting input and output names might
371 * be bad too, but we leave it to the PL to complain if so.
372 */
373 foreach(px, parameters)
374 {
376 FunctionParameterMode prevfpmode;
377
378 if (prevfp == fp)
379 break;
380 /* as above, default mode is IN */
381 prevfpmode = prevfp->mode;
382 if (prevfpmode == FUNC_PARAM_DEFAULT)
383 prevfpmode = FUNC_PARAM_IN;
384 /* pure in doesn't conflict with pure out */
385 if ((fpmode == FUNC_PARAM_IN ||
386 fpmode == FUNC_PARAM_VARIADIC) &&
387 (prevfpmode == FUNC_PARAM_OUT ||
388 prevfpmode == FUNC_PARAM_TABLE))
389 continue;
390 if ((prevfpmode == FUNC_PARAM_IN ||
391 prevfpmode == FUNC_PARAM_VARIADIC) &&
392 (fpmode == FUNC_PARAM_OUT ||
393 fpmode == FUNC_PARAM_TABLE))
394 continue;
395 if (prevfp->name && prevfp->name[0] &&
396 strcmp(prevfp->name, fp->name) == 0)
398 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
399 errmsg("parameter name \"%s\" used more than once",
400 fp->name),
401 parser_errposition(pstate, fp->location)));
402 }
403
404 paramNames[i] = CStringGetTextDatum(fp->name);
405 have_names = true;
406 }
407
408 if (inParameterNames_list)
409 *inParameterNames_list = lappend(*inParameterNames_list, makeString(fp->name ? fp->name : pstrdup("")));
410
411 if (fp->defexpr)
412 {
413 Node *def;
414
415 if (!isinput)
417 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
418 errmsg("only input parameters can have default values"),
419 parser_errposition(pstate, fp->location)));
420
421 def = transformExpr(pstate, fp->defexpr,
423 def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
424 assign_expr_collations(pstate, def);
425
426 /*
427 * Make sure no variables are referred to (this is probably dead
428 * code now that add_missing_from is history).
429 */
430 if (pstate->p_rtable != NIL ||
433 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
434 errmsg("cannot use table references in parameter default value"),
435 parser_errposition(pstate, fp->location)));
436
437 /*
438 * transformExpr() should have already rejected subqueries,
439 * aggregates, and window functions, based on the EXPR_KIND_ for a
440 * default expression.
441 *
442 * It can't return a set either --- but coerce_to_specific_type
443 * already checked that for us.
444 *
445 * Note: the point of these restrictions is to ensure that an
446 * expression that, on its face, hasn't got subplans, aggregates,
447 * etc cannot suddenly have them after function default arguments
448 * are inserted.
449 */
450
451 *parameterDefaults = lappend(*parameterDefaults, def);
452 have_defaults = true;
453 }
454 else
455 {
456 if (isinput && have_defaults)
458 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
459 errmsg("input parameters after one with a default value must also have defaults"),
460 parser_errposition(pstate, fp->location)));
461
462 /*
463 * For procedures, we also can't allow OUT parameters after one
464 * with a default, because the same sort of confusion arises in a
465 * CALL statement.
466 */
467 if (objtype == OBJECT_PROCEDURE && have_defaults)
469 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
470 errmsg("procedure OUT parameters cannot appear after one with a default value"),
471 parser_errposition(pstate, fp->location)));
472 }
473
474 i++;
475 }
476
477 /* Now construct the proper outputs as needed */
478 *parameterTypes = buildoidvector(inTypes, inCount);
479
480 if (outCount > 0 || varCount > 0)
481 {
482 *allParameterTypes = construct_array_builtin(allTypes, parameterCount, OIDOID);
483 *parameterModes = construct_array_builtin(paramModes, parameterCount, CHAROID);
484 if (outCount > 1)
485 *requiredResultType = RECORDOID;
486 /* otherwise we set requiredResultType correctly above */
487 }
488 else
489 {
490 *allParameterTypes = NULL;
491 *parameterModes = NULL;
492 }
493
494 if (have_names)
495 {
496 for (i = 0; i < parameterCount; i++)
497 {
498 if (paramNames[i] == PointerGetDatum(NULL))
499 paramNames[i] = CStringGetTextDatum("");
500 }
501 *parameterNames = construct_array_builtin(paramNames, parameterCount, TEXTOID);
502 }
503 else
504 *parameterNames = NULL;
505}
506
507
508/*
509 * Recognize one of the options that can be passed to both CREATE
510 * FUNCTION and ALTER FUNCTION and return it via one of the out
511 * parameters. Returns true if the passed option was recognized. If
512 * the out parameter we were going to assign to points to non-NULL,
513 * raise a duplicate-clause error. (We don't try to detect duplicate
514 * SET parameters though --- if you're redundant, the last one wins.)
515 */
516static bool
518 bool is_procedure,
519 DefElem *defel,
520 DefElem **volatility_item,
521 DefElem **strict_item,
522 DefElem **security_item,
523 DefElem **leakproof_item,
524 List **set_items,
525 DefElem **cost_item,
526 DefElem **rows_item,
527 DefElem **support_item,
528 DefElem **parallel_item)
529{
530 if (strcmp(defel->defname, "volatility") == 0)
531 {
532 if (is_procedure)
533 goto procedure_error;
534 if (*volatility_item)
535 errorConflictingDefElem(defel, pstate);
536
537 *volatility_item = defel;
538 }
539 else if (strcmp(defel->defname, "strict") == 0)
540 {
541 if (is_procedure)
542 goto procedure_error;
543 if (*strict_item)
544 errorConflictingDefElem(defel, pstate);
545
546 *strict_item = defel;
547 }
548 else if (strcmp(defel->defname, "security") == 0)
549 {
550 if (*security_item)
551 errorConflictingDefElem(defel, pstate);
552
553 *security_item = defel;
554 }
555 else if (strcmp(defel->defname, "leakproof") == 0)
556 {
557 if (is_procedure)
558 goto procedure_error;
559 if (*leakproof_item)
560 errorConflictingDefElem(defel, pstate);
561
562 *leakproof_item = defel;
563 }
564 else if (strcmp(defel->defname, "set") == 0)
565 {
566 *set_items = lappend(*set_items, defel->arg);
567 }
568 else if (strcmp(defel->defname, "cost") == 0)
569 {
570 if (is_procedure)
571 goto procedure_error;
572 if (*cost_item)
573 errorConflictingDefElem(defel, pstate);
574
575 *cost_item = defel;
576 }
577 else if (strcmp(defel->defname, "rows") == 0)
578 {
579 if (is_procedure)
580 goto procedure_error;
581 if (*rows_item)
582 errorConflictingDefElem(defel, pstate);
583
584 *rows_item = defel;
585 }
586 else if (strcmp(defel->defname, "support") == 0)
587 {
588 if (is_procedure)
589 goto procedure_error;
590 if (*support_item)
591 errorConflictingDefElem(defel, pstate);
592
593 *support_item = defel;
594 }
595 else if (strcmp(defel->defname, "parallel") == 0)
596 {
597 if (is_procedure)
598 goto procedure_error;
599 if (*parallel_item)
600 errorConflictingDefElem(defel, pstate);
601
602 *parallel_item = defel;
603 }
604 else
605 return false;
606
607 /* Recognized an option */
608 return true;
609
610procedure_error:
612 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
613 errmsg("invalid attribute in procedure definition"),
614 parser_errposition(pstate, defel->location)));
615 return false;
616}
617
618static char
620{
621 char *str = strVal(defel->arg);
622
623 if (strcmp(str, "immutable") == 0)
624 return PROVOLATILE_IMMUTABLE;
625 else if (strcmp(str, "stable") == 0)
626 return PROVOLATILE_STABLE;
627 else if (strcmp(str, "volatile") == 0)
628 return PROVOLATILE_VOLATILE;
629 else
630 {
631 elog(ERROR, "invalid volatility \"%s\"", str);
632 return 0; /* keep compiler quiet */
633 }
634}
635
636static char
638{
639 char *str = strVal(defel->arg);
640
641 if (strcmp(str, "safe") == 0)
642 return PROPARALLEL_SAFE;
643 else if (strcmp(str, "unsafe") == 0)
644 return PROPARALLEL_UNSAFE;
645 else if (strcmp(str, "restricted") == 0)
646 return PROPARALLEL_RESTRICTED;
647 else
648 {
650 (errcode(ERRCODE_SYNTAX_ERROR),
651 errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
652 return PROPARALLEL_UNSAFE; /* keep compiler quiet */
653 }
654}
655
656/*
657 * Update a proconfig value according to a list of VariableSetStmt items.
658 *
659 * The input and result may be NULL to signify a null entry.
660 */
661static ArrayType *
663{
664 ListCell *l;
665
666 foreach(l, set_items)
667 {
669
670 if (sstmt->kind == VAR_RESET_ALL)
671 a = NULL;
672 else
673 {
674 char *valuestr = ExtractSetVariableArgs(sstmt);
675
676 if (valuestr)
677 a = GUCArrayAdd(a, sstmt->name, valuestr);
678 else /* RESET */
679 a = GUCArrayDelete(a, sstmt->name);
680 }
681 }
682
683 return a;
684}
685
686static Oid
688{
689 List *procName = defGetQualifiedName(defel);
690 Oid procOid;
691 Oid argList[1];
692
693 /*
694 * Support functions always take one INTERNAL argument and return
695 * INTERNAL.
696 */
697 argList[0] = INTERNALOID;
698
699 procOid = LookupFuncName(procName, 1, argList, true);
700 if (!OidIsValid(procOid))
702 (errcode(ERRCODE_UNDEFINED_FUNCTION),
703 errmsg("function %s does not exist",
704 func_signature_string(procName, 1, NIL, argList))));
705
706 if (get_func_rettype(procOid) != INTERNALOID)
708 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
709 errmsg("support function %s must return type %s",
710 NameListToString(procName), "internal")));
711
712 /*
713 * Someday we might want an ACL check here; but for now, we insist that
714 * you be superuser to specify a support function, so privilege on the
715 * support function is moot.
716 */
717 if (!superuser())
719 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
720 errmsg("must be superuser to specify a support function")));
721
722 return procOid;
723}
724
725
726/*
727 * Dissect the list of options assembled in gram.y into function
728 * attributes.
729 */
730static void
732 bool is_procedure,
733 List *options,
734 List **as,
735 char **language,
736 Node **transform,
737 bool *windowfunc_p,
738 char *volatility_p,
739 bool *strict_p,
740 bool *security_definer,
741 bool *leakproof_p,
742 ArrayType **proconfig,
743 float4 *procost,
744 float4 *prorows,
745 Oid *prosupport,
746 char *parallel_p)
747{
749 DefElem *as_item = NULL;
750 DefElem *language_item = NULL;
751 DefElem *transform_item = NULL;
752 DefElem *windowfunc_item = NULL;
753 DefElem *volatility_item = NULL;
754 DefElem *strict_item = NULL;
755 DefElem *security_item = NULL;
756 DefElem *leakproof_item = NULL;
757 List *set_items = NIL;
758 DefElem *cost_item = NULL;
759 DefElem *rows_item = NULL;
760 DefElem *support_item = NULL;
761 DefElem *parallel_item = NULL;
762
763 foreach(option, options)
764 {
765 DefElem *defel = (DefElem *) lfirst(option);
766
767 if (strcmp(defel->defname, "as") == 0)
768 {
769 if (as_item)
770 errorConflictingDefElem(defel, pstate);
771 as_item = defel;
772 }
773 else if (strcmp(defel->defname, "language") == 0)
774 {
775 if (language_item)
776 errorConflictingDefElem(defel, pstate);
777 language_item = defel;
778 }
779 else if (strcmp(defel->defname, "transform") == 0)
780 {
781 if (transform_item)
782 errorConflictingDefElem(defel, pstate);
783 transform_item = defel;
784 }
785 else if (strcmp(defel->defname, "window") == 0)
786 {
787 if (windowfunc_item)
788 errorConflictingDefElem(defel, pstate);
789 if (is_procedure)
791 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
792 errmsg("invalid attribute in procedure definition"),
793 parser_errposition(pstate, defel->location)));
794 windowfunc_item = defel;
795 }
796 else if (compute_common_attribute(pstate,
797 is_procedure,
798 defel,
799 &volatility_item,
800 &strict_item,
801 &security_item,
802 &leakproof_item,
803 &set_items,
804 &cost_item,
805 &rows_item,
806 &support_item,
807 &parallel_item))
808 {
809 /* recognized common option */
810 continue;
811 }
812 else
813 elog(ERROR, "option \"%s\" not recognized",
814 defel->defname);
815 }
816
817 if (as_item)
818 *as = (List *) as_item->arg;
819 if (language_item)
820 *language = strVal(language_item->arg);
821 if (transform_item)
822 *transform = transform_item->arg;
823 if (windowfunc_item)
824 *windowfunc_p = boolVal(windowfunc_item->arg);
825 if (volatility_item)
826 *volatility_p = interpret_func_volatility(volatility_item);
827 if (strict_item)
828 *strict_p = boolVal(strict_item->arg);
829 if (security_item)
830 *security_definer = boolVal(security_item->arg);
831 if (leakproof_item)
832 *leakproof_p = boolVal(leakproof_item->arg);
833 if (set_items)
834 *proconfig = update_proconfig_value(NULL, set_items);
835 if (cost_item)
836 {
837 *procost = defGetNumeric(cost_item);
838 if (*procost <= 0)
840 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
841 errmsg("COST must be positive")));
842 }
843 if (rows_item)
844 {
845 *prorows = defGetNumeric(rows_item);
846 if (*prorows <= 0)
848 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
849 errmsg("ROWS must be positive")));
850 }
851 if (support_item)
852 *prosupport = interpret_func_support(support_item);
853 if (parallel_item)
854 *parallel_p = interpret_func_parallel(parallel_item);
855}
856
857
858/*
859 * For a dynamically linked C language object, the form of the clause is
860 *
861 * AS <object file name> [, <link symbol name> ]
862 *
863 * In all other cases
864 *
865 * AS <object reference, or sql code>
866 */
867static void
868interpret_AS_clause(Oid languageOid, const char *languageName,
869 char *funcname, List *as, Node *sql_body_in,
870 List *parameterTypes, List *inParameterNames,
871 char **prosrc_str_p, char **probin_str_p,
872 Node **sql_body_out,
873 const char *queryString)
874{
875 if (!sql_body_in && !as)
877 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
878 errmsg("no function body specified")));
879
880 if (sql_body_in && as)
882 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
883 errmsg("duplicate function body specified")));
884
885 if (sql_body_in && languageOid != SQLlanguageId)
887 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
888 errmsg("inline SQL function body only valid for language SQL")));
889
890 *sql_body_out = NULL;
891
892 if (languageOid == ClanguageId)
893 {
894 /*
895 * For "C" language, store the file name in probin and, when given,
896 * the link symbol name in prosrc. If link symbol is omitted,
897 * substitute procedure name. We also allow link symbol to be
898 * specified as "-", since that was the habit in PG versions before
899 * 8.4, and there might be dump files out there that don't translate
900 * that back to "omitted".
901 */
902 *probin_str_p = strVal(linitial(as));
903 if (list_length(as) == 1)
904 *prosrc_str_p = funcname;
905 else
906 {
907 *prosrc_str_p = strVal(lsecond(as));
908 if (strcmp(*prosrc_str_p, "-") == 0)
909 *prosrc_str_p = funcname;
910 }
911 }
912 else if (sql_body_in)
913 {
915
917
918 pinfo->fname = funcname;
919 pinfo->nargs = list_length(parameterTypes);
920 pinfo->argtypes = (Oid *) palloc(pinfo->nargs * sizeof(Oid));
921 pinfo->argnames = (char **) palloc(pinfo->nargs * sizeof(char *));
922 for (int i = 0; i < list_length(parameterTypes); i++)
923 {
924 char *s = strVal(list_nth(inParameterNames, i));
925
926 pinfo->argtypes[i] = list_nth_oid(parameterTypes, i);
927 if (IsPolymorphicType(pinfo->argtypes[i]))
929 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
930 errmsg("SQL function with unquoted function body cannot have polymorphic arguments")));
931
932 if (s[0] != '\0')
933 pinfo->argnames[i] = s;
934 else
935 pinfo->argnames[i] = NULL;
936 }
937
938 if (IsA(sql_body_in, List))
939 {
940 List *stmts = linitial_node(List, castNode(List, sql_body_in));
941 ListCell *lc;
942 List *transformed_stmts = NIL;
943
944 foreach(lc, stmts)
945 {
946 Node *stmt = lfirst(lc);
947 Query *q;
948 ParseState *pstate = make_parsestate(NULL);
949
950 pstate->p_sourcetext = queryString;
951 sql_fn_parser_setup(pstate, pinfo);
952 q = transformStmt(pstate, stmt);
953 if (q->commandType == CMD_UTILITY)
955 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
956 errmsg("%s is not yet supported in unquoted SQL function body",
958 transformed_stmts = lappend(transformed_stmts, q);
959 free_parsestate(pstate);
960 }
961
962 *sql_body_out = (Node *) list_make1(transformed_stmts);
963 }
964 else
965 {
966 Query *q;
967 ParseState *pstate = make_parsestate(NULL);
968
969 pstate->p_sourcetext = queryString;
970 sql_fn_parser_setup(pstate, pinfo);
971 q = transformStmt(pstate, sql_body_in);
972 if (q->commandType == CMD_UTILITY)
974 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
975 errmsg("%s is not yet supported in unquoted SQL function body",
977 free_parsestate(pstate);
978
979 *sql_body_out = (Node *) q;
980 }
981
982 /*
983 * We must put something in prosrc. For the moment, just record an
984 * empty string. It might be useful to store the original text of the
985 * CREATE FUNCTION statement --- but to make actual use of that in
986 * error reports, we'd also have to adjust readfuncs.c to not throw
987 * away node location fields when reading prosqlbody.
988 */
989 *prosrc_str_p = pstrdup("");
990
991 /* But we definitely don't need probin. */
992 *probin_str_p = NULL;
993 }
994 else
995 {
996 /* Everything else wants the given string in prosrc. */
997 *prosrc_str_p = strVal(linitial(as));
998 *probin_str_p = NULL;
999
1000 if (list_length(as) != 1)
1001 ereport(ERROR,
1002 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1003 errmsg("only one AS item needed for language \"%s\"",
1004 languageName)));
1005
1006 if (languageOid == INTERNALlanguageId)
1007 {
1008 /*
1009 * In PostgreSQL versions before 6.5, the SQL name of the created
1010 * function could not be different from the internal name, and
1011 * "prosrc" wasn't used. So there is code out there that does
1012 * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
1013 * modicum of backwards compatibility, accept an empty "prosrc"
1014 * value as meaning the supplied SQL function name.
1015 */
1016 if (strlen(*prosrc_str_p) == 0)
1017 *prosrc_str_p = funcname;
1018 }
1019 }
1020}
1021
1022
1023/*
1024 * CreateFunction
1025 * Execute a CREATE FUNCTION (or CREATE PROCEDURE) utility statement.
1026 */
1029{
1030 char *probin_str;
1031 char *prosrc_str;
1032 Node *prosqlbody;
1033 Oid prorettype;
1034 bool returnsSet;
1035 char *language;
1036 Oid languageOid;
1037 Oid languageValidator;
1038 Node *transformDefElem = NULL;
1039 char *funcname;
1040 Oid namespaceId;
1041 AclResult aclresult;
1042 oidvector *parameterTypes;
1043 List *parameterTypes_list = NIL;
1044 ArrayType *allParameterTypes;
1045 ArrayType *parameterModes;
1046 ArrayType *parameterNames;
1047 List *inParameterNames_list = NIL;
1048 List *parameterDefaults;
1049 Oid variadicArgType;
1050 List *trftypes_list = NIL;
1051 List *trfoids_list = NIL;
1052 ArrayType *trftypes;
1053 Oid requiredResultType;
1054 bool isWindowFunc,
1055 isStrict,
1056 security,
1057 isLeakProof;
1058 char volatility;
1059 ArrayType *proconfig;
1060 float4 procost;
1061 float4 prorows;
1062 Oid prosupport;
1063 HeapTuple languageTuple;
1064 Form_pg_language languageStruct;
1065 List *as_clause;
1066 char parallel;
1067
1068 /* Convert list of names to a name and namespace */
1069 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
1070 &funcname);
1071
1072 /* Check we have creation rights in target namespace */
1073 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(), ACL_CREATE);
1074 if (aclresult != ACLCHECK_OK)
1075 aclcheck_error(aclresult, OBJECT_SCHEMA,
1076 get_namespace_name(namespaceId));
1077
1078 /* Set default attributes */
1079 as_clause = NIL;
1080 language = NULL;
1081 isWindowFunc = false;
1082 isStrict = false;
1083 security = false;
1084 isLeakProof = false;
1085 volatility = PROVOLATILE_VOLATILE;
1086 proconfig = NULL;
1087 procost = -1; /* indicates not set */
1088 prorows = -1; /* indicates not set */
1089 prosupport = InvalidOid;
1090 parallel = PROPARALLEL_UNSAFE;
1091
1092 /* Extract non-default attributes from stmt->options list */
1094 stmt->is_procedure,
1095 stmt->options,
1096 &as_clause, &language, &transformDefElem,
1097 &isWindowFunc, &volatility,
1098 &isStrict, &security, &isLeakProof,
1099 &proconfig, &procost, &prorows,
1100 &prosupport, &parallel);
1101
1102 if (!language)
1103 {
1104 if (stmt->sql_body)
1105 language = "sql";
1106 else
1107 ereport(ERROR,
1108 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1109 errmsg("no language specified")));
1110 }
1111
1112 /* Look up the language and validate permissions */
1113 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
1114 if (!HeapTupleIsValid(languageTuple))
1115 ereport(ERROR,
1116 (errcode(ERRCODE_UNDEFINED_OBJECT),
1117 errmsg("language \"%s\" does not exist", language),
1118 (extension_file_exists(language) ?
1119 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
1120
1121 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
1122 languageOid = languageStruct->oid;
1123
1124 if (languageStruct->lanpltrusted)
1125 {
1126 /* if trusted language, need USAGE privilege */
1127 aclresult = object_aclcheck(LanguageRelationId, languageOid, GetUserId(), ACL_USAGE);
1128 if (aclresult != ACLCHECK_OK)
1130 NameStr(languageStruct->lanname));
1131 }
1132 else
1133 {
1134 /* if untrusted language, must be superuser */
1135 if (!superuser())
1137 NameStr(languageStruct->lanname));
1138 }
1139
1140 languageValidator = languageStruct->lanvalidator;
1141
1142 ReleaseSysCache(languageTuple);
1143
1144 /*
1145 * Only superuser is allowed to create leakproof functions because
1146 * leakproof functions can see tuples which have not yet been filtered out
1147 * by security barrier views or row-level security policies.
1148 */
1149 if (isLeakProof && !superuser())
1150 ereport(ERROR,
1151 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1152 errmsg("only superuser can define a leakproof function")));
1153
1154 if (transformDefElem)
1155 {
1156 ListCell *lc;
1157
1158 foreach(lc, castNode(List, transformDefElem))
1159 {
1160 Oid typeid = typenameTypeId(NULL,
1161 lfirst_node(TypeName, lc));
1162 Oid elt = get_base_element_type(typeid);
1163 Oid transformid;
1164
1165 typeid = elt ? elt : typeid;
1166 transformid = get_transform_oid(typeid, languageOid, false);
1167 trftypes_list = lappend_oid(trftypes_list, typeid);
1168 trfoids_list = lappend_oid(trfoids_list, transformid);
1169 }
1170 }
1171
1172 /*
1173 * Convert remaining parameters of CREATE to form wanted by
1174 * ProcedureCreate.
1175 */
1177 stmt->parameters,
1178 languageOid,
1179 stmt->is_procedure ? OBJECT_PROCEDURE : OBJECT_FUNCTION,
1180 &parameterTypes,
1181 &parameterTypes_list,
1182 &allParameterTypes,
1183 &parameterModes,
1184 &parameterNames,
1185 &inParameterNames_list,
1186 &parameterDefaults,
1187 &variadicArgType,
1188 &requiredResultType);
1189
1190 if (stmt->is_procedure)
1191 {
1192 Assert(!stmt->returnType);
1193 prorettype = requiredResultType ? requiredResultType : VOIDOID;
1194 returnsSet = false;
1195 }
1196 else if (stmt->returnType)
1197 {
1198 /* explicit RETURNS clause */
1199 compute_return_type(stmt->returnType, languageOid,
1200 &prorettype, &returnsSet);
1201 if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
1202 ereport(ERROR,
1203 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1204 errmsg("function result type must be %s because of OUT parameters",
1205 format_type_be(requiredResultType))));
1206 }
1207 else if (OidIsValid(requiredResultType))
1208 {
1209 /* default RETURNS clause from OUT parameters */
1210 prorettype = requiredResultType;
1211 returnsSet = false;
1212 }
1213 else
1214 {
1215 ereport(ERROR,
1216 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1217 errmsg("function result type must be specified")));
1218 /* Alternative possibility: default to RETURNS VOID */
1219 prorettype = VOIDOID;
1220 returnsSet = false;
1221 }
1222
1223 if (trftypes_list != NIL)
1224 {
1225 ListCell *lc;
1226 Datum *arr;
1227 int i;
1228
1229 arr = palloc(list_length(trftypes_list) * sizeof(Datum));
1230 i = 0;
1231 foreach(lc, trftypes_list)
1232 arr[i++] = ObjectIdGetDatum(lfirst_oid(lc));
1233 trftypes = construct_array_builtin(arr, list_length(trftypes_list), OIDOID);
1234 }
1235 else
1236 {
1237 /* store SQL NULL instead of empty array */
1238 trftypes = NULL;
1239 }
1240
1241 interpret_AS_clause(languageOid, language, funcname, as_clause, stmt->sql_body,
1242 parameterTypes_list, inParameterNames_list,
1243 &prosrc_str, &probin_str, &prosqlbody,
1244 pstate->p_sourcetext);
1245
1246 /*
1247 * Set default values for COST and ROWS depending on other parameters;
1248 * reject ROWS if it's not returnsSet. NB: pg_dump knows these default
1249 * values, keep it in sync if you change them.
1250 */
1251 if (procost < 0)
1252 {
1253 /* SQL and PL-language functions are assumed more expensive */
1254 if (languageOid == INTERNALlanguageId ||
1255 languageOid == ClanguageId)
1256 procost = 1;
1257 else
1258 procost = 100;
1259 }
1260 if (prorows < 0)
1261 {
1262 if (returnsSet)
1263 prorows = 1000;
1264 else
1265 prorows = 0; /* dummy value if not returnsSet */
1266 }
1267 else if (!returnsSet)
1268 ereport(ERROR,
1269 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1270 errmsg("ROWS is not applicable when function does not return a set")));
1271
1272 /*
1273 * And now that we have all the parameters, and know we're permitted to do
1274 * so, go ahead and create the function.
1275 */
1277 namespaceId,
1278 stmt->replace,
1279 returnsSet,
1280 prorettype,
1281 GetUserId(),
1282 languageOid,
1283 languageValidator,
1284 prosrc_str, /* converted to text later */
1285 probin_str, /* converted to text later */
1286 prosqlbody,
1287 stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION),
1288 security,
1289 isLeakProof,
1290 isStrict,
1291 volatility,
1292 parallel,
1293 parameterTypes,
1294 PointerGetDatum(allParameterTypes),
1295 PointerGetDatum(parameterModes),
1296 PointerGetDatum(parameterNames),
1297 parameterDefaults,
1298 PointerGetDatum(trftypes),
1299 trfoids_list,
1300 PointerGetDatum(proconfig),
1301 prosupport,
1302 procost,
1303 prorows);
1304}
1305
1306/*
1307 * Guts of function deletion.
1308 *
1309 * Note: this is also used for aggregate deletion, since the OIDs of
1310 * both functions and aggregates point to pg_proc.
1311 */
1312void
1314{
1315 Relation relation;
1316 HeapTuple tup;
1317 char prokind;
1318
1319 /*
1320 * Delete the pg_proc tuple.
1321 */
1322 relation = table_open(ProcedureRelationId, RowExclusiveLock);
1323
1324 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
1325 if (!HeapTupleIsValid(tup)) /* should not happen */
1326 elog(ERROR, "cache lookup failed for function %u", funcOid);
1327
1328 prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind;
1329
1330 CatalogTupleDelete(relation, &tup->t_self);
1331
1332 ReleaseSysCache(tup);
1333
1334 table_close(relation, RowExclusiveLock);
1335
1336 pgstat_drop_function(funcOid);
1337
1338 /*
1339 * If there's a pg_aggregate tuple, delete that too.
1340 */
1341 if (prokind == PROKIND_AGGREGATE)
1342 {
1343 relation = table_open(AggregateRelationId, RowExclusiveLock);
1344
1345 tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
1346 if (!HeapTupleIsValid(tup)) /* should not happen */
1347 elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
1348
1349 CatalogTupleDelete(relation, &tup->t_self);
1350
1351 ReleaseSysCache(tup);
1352
1353 table_close(relation, RowExclusiveLock);
1354 }
1355}
1356
1357/*
1358 * Implements the ALTER FUNCTION utility command (except for the
1359 * RENAME and OWNER clauses, which are handled as part of the generic
1360 * ALTER framework).
1361 */
1364{
1365 HeapTuple tup;
1366 Oid funcOid;
1367 Form_pg_proc procForm;
1368 bool is_procedure;
1369 Relation rel;
1370 ListCell *l;
1371 DefElem *volatility_item = NULL;
1372 DefElem *strict_item = NULL;
1373 DefElem *security_def_item = NULL;
1374 DefElem *leakproof_item = NULL;
1375 List *set_items = NIL;
1376 DefElem *cost_item = NULL;
1377 DefElem *rows_item = NULL;
1378 DefElem *support_item = NULL;
1379 DefElem *parallel_item = NULL;
1380 ObjectAddress address;
1381
1382 rel = table_open(ProcedureRelationId, RowExclusiveLock);
1383
1384 funcOid = LookupFuncWithArgs(stmt->objtype, stmt->func, false);
1385
1386 ObjectAddressSet(address, ProcedureRelationId, funcOid);
1387
1388 tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
1389 if (!HeapTupleIsValid(tup)) /* should not happen */
1390 elog(ERROR, "cache lookup failed for function %u", funcOid);
1391
1392 procForm = (Form_pg_proc) GETSTRUCT(tup);
1393
1394 /* Permission check: must own function */
1395 if (!object_ownercheck(ProcedureRelationId, funcOid, GetUserId()))
1397 NameListToString(stmt->func->objname));
1398
1399 if (procForm->prokind == PROKIND_AGGREGATE)
1400 ereport(ERROR,
1401 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1402 errmsg("\"%s\" is an aggregate function",
1403 NameListToString(stmt->func->objname))));
1404
1405 is_procedure = (procForm->prokind == PROKIND_PROCEDURE);
1406
1407 /* Examine requested actions. */
1408 foreach(l, stmt->actions)
1409 {
1410 DefElem *defel = (DefElem *) lfirst(l);
1411
1412 if (compute_common_attribute(pstate,
1413 is_procedure,
1414 defel,
1415 &volatility_item,
1416 &strict_item,
1417 &security_def_item,
1418 &leakproof_item,
1419 &set_items,
1420 &cost_item,
1421 &rows_item,
1422 &support_item,
1423 &parallel_item) == false)
1424 elog(ERROR, "option \"%s\" not recognized", defel->defname);
1425 }
1426
1427 if (volatility_item)
1428 procForm->provolatile = interpret_func_volatility(volatility_item);
1429 if (strict_item)
1430 procForm->proisstrict = boolVal(strict_item->arg);
1431 if (security_def_item)
1432 procForm->prosecdef = boolVal(security_def_item->arg);
1433 if (leakproof_item)
1434 {
1435 procForm->proleakproof = boolVal(leakproof_item->arg);
1436 if (procForm->proleakproof && !superuser())
1437 ereport(ERROR,
1438 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1439 errmsg("only superuser can define a leakproof function")));
1440 }
1441 if (cost_item)
1442 {
1443 procForm->procost = defGetNumeric(cost_item);
1444 if (procForm->procost <= 0)
1445 ereport(ERROR,
1446 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1447 errmsg("COST must be positive")));
1448 }
1449 if (rows_item)
1450 {
1451 procForm->prorows = defGetNumeric(rows_item);
1452 if (procForm->prorows <= 0)
1453 ereport(ERROR,
1454 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1455 errmsg("ROWS must be positive")));
1456 if (!procForm->proretset)
1457 ereport(ERROR,
1458 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1459 errmsg("ROWS is not applicable when function does not return a set")));
1460 }
1461 if (support_item)
1462 {
1463 /* interpret_func_support handles the privilege check */
1464 Oid newsupport = interpret_func_support(support_item);
1465
1466 /* Add or replace dependency on support function */
1467 if (OidIsValid(procForm->prosupport))
1468 {
1469 if (changeDependencyFor(ProcedureRelationId, funcOid,
1470 ProcedureRelationId, procForm->prosupport,
1471 newsupport) != 1)
1472 elog(ERROR, "could not change support dependency for function %s",
1473 get_func_name(funcOid));
1474 }
1475 else
1476 {
1477 ObjectAddress referenced;
1478
1479 referenced.classId = ProcedureRelationId;
1480 referenced.objectId = newsupport;
1481 referenced.objectSubId = 0;
1482 recordDependencyOn(&address, &referenced, DEPENDENCY_NORMAL);
1483 }
1484
1485 procForm->prosupport = newsupport;
1486 }
1487 if (parallel_item)
1488 procForm->proparallel = interpret_func_parallel(parallel_item);
1489 if (set_items)
1490 {
1491 Datum datum;
1492 bool isnull;
1493 ArrayType *a;
1494 Datum repl_val[Natts_pg_proc];
1495 bool repl_null[Natts_pg_proc];
1496 bool repl_repl[Natts_pg_proc];
1497
1498 /* extract existing proconfig setting */
1499 datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
1500 a = isnull ? NULL : DatumGetArrayTypeP(datum);
1501
1502 /* update according to each SET or RESET item, left to right */
1503 a = update_proconfig_value(a, set_items);
1504
1505 /* update the tuple */
1506 memset(repl_repl, false, sizeof(repl_repl));
1507 repl_repl[Anum_pg_proc_proconfig - 1] = true;
1508
1509 if (a == NULL)
1510 {
1511 repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
1512 repl_null[Anum_pg_proc_proconfig - 1] = true;
1513 }
1514 else
1515 {
1516 repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
1517 repl_null[Anum_pg_proc_proconfig - 1] = false;
1518 }
1519
1520 tup = heap_modify_tuple(tup, RelationGetDescr(rel),
1521 repl_val, repl_null, repl_repl);
1522 }
1523 /* DO NOT put more touches of procForm below here; it's now dangling. */
1524
1525 /* Do the update */
1526 CatalogTupleUpdate(rel, &tup->t_self, tup);
1527
1528 InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
1529
1530 table_close(rel, NoLock);
1531 heap_freetuple(tup);
1532
1533 return address;
1534}
1535
1536
1537/*
1538 * CREATE CAST
1539 */
1542{
1543 Oid sourcetypeid;
1544 Oid targettypeid;
1545 char sourcetyptype;
1546 char targettyptype;
1547 Oid funcid;
1548 Oid incastid = InvalidOid;
1549 Oid outcastid = InvalidOid;
1550 int nargs;
1551 char castcontext;
1552 char castmethod;
1553 HeapTuple tuple;
1554 AclResult aclresult;
1555 ObjectAddress myself;
1556
1557 sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
1558 targettypeid = typenameTypeId(NULL, stmt->targettype);
1559 sourcetyptype = get_typtype(sourcetypeid);
1560 targettyptype = get_typtype(targettypeid);
1561
1562 /* No pseudo-types allowed */
1563 if (sourcetyptype == TYPTYPE_PSEUDO)
1564 ereport(ERROR,
1565 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1566 errmsg("source data type %s is a pseudo-type",
1567 TypeNameToString(stmt->sourcetype))));
1568
1569 if (targettyptype == TYPTYPE_PSEUDO)
1570 ereport(ERROR,
1571 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1572 errmsg("target data type %s is a pseudo-type",
1573 TypeNameToString(stmt->targettype))));
1574
1575 /* Permission check */
1576 if (!object_ownercheck(TypeRelationId, sourcetypeid, GetUserId())
1577 && !object_ownercheck(TypeRelationId, targettypeid, GetUserId()))
1578 ereport(ERROR,
1579 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1580 errmsg("must be owner of type %s or type %s",
1581 format_type_be(sourcetypeid),
1582 format_type_be(targettypeid))));
1583
1584 aclresult = object_aclcheck(TypeRelationId, sourcetypeid, GetUserId(), ACL_USAGE);
1585 if (aclresult != ACLCHECK_OK)
1586 aclcheck_error_type(aclresult, sourcetypeid);
1587
1588 aclresult = object_aclcheck(TypeRelationId, targettypeid, GetUserId(), ACL_USAGE);
1589 if (aclresult != ACLCHECK_OK)
1590 aclcheck_error_type(aclresult, targettypeid);
1591
1592 /* Domains are allowed for historical reasons, but we warn */
1593 if (sourcetyptype == TYPTYPE_DOMAIN)
1595 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1596 errmsg("cast will be ignored because the source data type is a domain")));
1597
1598 else if (targettyptype == TYPTYPE_DOMAIN)
1600 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1601 errmsg("cast will be ignored because the target data type is a domain")));
1602
1603 /* Determine the cast method */
1604 if (stmt->func != NULL)
1605 castmethod = COERCION_METHOD_FUNCTION;
1606 else if (stmt->inout)
1607 castmethod = COERCION_METHOD_INOUT;
1608 else
1609 castmethod = COERCION_METHOD_BINARY;
1610
1611 if (castmethod == COERCION_METHOD_FUNCTION)
1612 {
1613 Form_pg_proc procstruct;
1614
1615 funcid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->func, false);
1616
1617 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1618 if (!HeapTupleIsValid(tuple))
1619 elog(ERROR, "cache lookup failed for function %u", funcid);
1620
1621 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1622 nargs = procstruct->pronargs;
1623 if (nargs < 1 || nargs > 3)
1624 ereport(ERROR,
1625 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1626 errmsg("cast function must take one to three arguments")));
1627 if (!IsBinaryCoercibleWithCast(sourcetypeid,
1628 procstruct->proargtypes.values[0],
1629 &incastid))
1630 ereport(ERROR,
1631 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1632 errmsg("argument of cast function must match or be binary-coercible from source data type")));
1633 if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
1634 ereport(ERROR,
1635 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1636 errmsg("second argument of cast function must be type %s",
1637 "integer")));
1638 if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
1639 ereport(ERROR,
1640 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1641 errmsg("third argument of cast function must be type %s",
1642 "boolean")));
1643 if (!IsBinaryCoercibleWithCast(procstruct->prorettype,
1644 targettypeid,
1645 &outcastid))
1646 ereport(ERROR,
1647 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1648 errmsg("return data type of cast function must match or be binary-coercible to target data type")));
1649
1650 /*
1651 * Restricting the volatility of a cast function may or may not be a
1652 * good idea in the abstract, but it definitely breaks many old
1653 * user-defined types. Disable this check --- tgl 2/1/03
1654 */
1655#ifdef NOT_USED
1656 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1657 ereport(ERROR,
1658 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1659 errmsg("cast function must not be volatile")));
1660#endif
1661 if (procstruct->prokind != PROKIND_FUNCTION)
1662 ereport(ERROR,
1663 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1664 errmsg("cast function must be a normal function")));
1665 if (procstruct->proretset)
1666 ereport(ERROR,
1667 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1668 errmsg("cast function must not return a set")));
1669
1670 ReleaseSysCache(tuple);
1671 }
1672 else
1673 {
1674 funcid = InvalidOid;
1675 nargs = 0;
1676 }
1677
1678 if (castmethod == COERCION_METHOD_BINARY)
1679 {
1680 int16 typ1len;
1681 int16 typ2len;
1682 bool typ1byval;
1683 bool typ2byval;
1684 char typ1align;
1685 char typ2align;
1686
1687 /*
1688 * Must be superuser to create binary-compatible casts, since
1689 * erroneous casts can easily crash the backend.
1690 */
1691 if (!superuser())
1692 ereport(ERROR,
1693 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1694 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
1695
1696 /*
1697 * Also, insist that the types match as to size, alignment, and
1698 * pass-by-value attributes; this provides at least a crude check that
1699 * they have similar representations. A pair of types that fail this
1700 * test should certainly not be equated.
1701 */
1702 get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
1703 get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
1704 if (typ1len != typ2len ||
1705 typ1byval != typ2byval ||
1706 typ1align != typ2align)
1707 ereport(ERROR,
1708 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1709 errmsg("source and target data types are not physically compatible")));
1710
1711 /*
1712 * We know that composite, array, range and enum types are never
1713 * binary-compatible with each other. They all have OIDs embedded in
1714 * them.
1715 *
1716 * Theoretically you could build a user-defined base type that is
1717 * binary-compatible with such a type. But we disallow it anyway, as
1718 * in practice such a cast is surely a mistake. You can always work
1719 * around that by writing a cast function.
1720 *
1721 * NOTE: if we ever have a kind of container type that doesn't need to
1722 * be rejected for this reason, we'd likely need to recursively apply
1723 * all of these same checks to the contained type(s).
1724 */
1725 if (sourcetyptype == TYPTYPE_COMPOSITE ||
1726 targettyptype == TYPTYPE_COMPOSITE)
1727 ereport(ERROR,
1728 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1729 errmsg("composite data types are not binary-compatible")));
1730
1731 if (OidIsValid(get_element_type(sourcetypeid)) ||
1732 OidIsValid(get_element_type(targettypeid)))
1733 ereport(ERROR,
1734 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1735 errmsg("array data types are not binary-compatible")));
1736
1737 if (sourcetyptype == TYPTYPE_RANGE ||
1738 targettyptype == TYPTYPE_RANGE ||
1739 sourcetyptype == TYPTYPE_MULTIRANGE ||
1740 targettyptype == TYPTYPE_MULTIRANGE)
1741 ereport(ERROR,
1742 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1743 errmsg("range data types are not binary-compatible")));
1744
1745 if (sourcetyptype == TYPTYPE_ENUM ||
1746 targettyptype == TYPTYPE_ENUM)
1747 ereport(ERROR,
1748 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1749 errmsg("enum data types are not binary-compatible")));
1750
1751 /*
1752 * We also disallow creating binary-compatibility casts involving
1753 * domains. Casting from a domain to its base type is already
1754 * allowed, and casting the other way ought to go through domain
1755 * coercion to permit constraint checking. Again, if you're intent on
1756 * having your own semantics for that, create a no-op cast function.
1757 *
1758 * NOTE: if we were to relax this, the above checks for composites
1759 * etc. would have to be modified to look through domains to their
1760 * base types.
1761 */
1762 if (sourcetyptype == TYPTYPE_DOMAIN ||
1763 targettyptype == TYPTYPE_DOMAIN)
1764 ereport(ERROR,
1765 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1766 errmsg("domain data types must not be marked binary-compatible")));
1767 }
1768
1769 /*
1770 * Allow source and target types to be same only for length coercion
1771 * functions. We assume a multi-arg function does length coercion.
1772 */
1773 if (sourcetypeid == targettypeid && nargs < 2)
1774 ereport(ERROR,
1775 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1776 errmsg("source data type and target data type are the same")));
1777
1778 /* convert CoercionContext enum to char value for castcontext */
1779 switch (stmt->context)
1780 {
1781 case COERCION_IMPLICIT:
1782 castcontext = COERCION_CODE_IMPLICIT;
1783 break;
1785 castcontext = COERCION_CODE_ASSIGNMENT;
1786 break;
1787 /* COERCION_PLPGSQL is intentionally not covered here */
1788 case COERCION_EXPLICIT:
1789 castcontext = COERCION_CODE_EXPLICIT;
1790 break;
1791 default:
1792 elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
1793 castcontext = 0; /* keep compiler quiet */
1794 break;
1795 }
1796
1797 myself = CastCreate(sourcetypeid, targettypeid, funcid, incastid, outcastid,
1798 castcontext, castmethod, DEPENDENCY_NORMAL);
1799 return myself;
1800}
1801
1802
1803static void
1805{
1806 if (procstruct->provolatile == PROVOLATILE_VOLATILE)
1807 ereport(ERROR,
1808 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1809 errmsg("transform function must not be volatile")));
1810 if (procstruct->prokind != PROKIND_FUNCTION)
1811 ereport(ERROR,
1812 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1813 errmsg("transform function must be a normal function")));
1814 if (procstruct->proretset)
1815 ereport(ERROR,
1816 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1817 errmsg("transform function must not return a set")));
1818 if (procstruct->pronargs != 1)
1819 ereport(ERROR,
1820 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1821 errmsg("transform function must take one argument")));
1822 if (procstruct->proargtypes.values[0] != INTERNALOID)
1823 ereport(ERROR,
1824 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1825 errmsg("first argument of transform function must be type %s",
1826 "internal")));
1827}
1828
1829
1830/*
1831 * CREATE TRANSFORM
1832 */
1835{
1836 Oid typeid;
1837 char typtype;
1838 Oid langid;
1839 Oid fromsqlfuncid;
1840 Oid tosqlfuncid;
1841 AclResult aclresult;
1842 Form_pg_proc procstruct;
1843 Datum values[Natts_pg_transform];
1844 bool nulls[Natts_pg_transform] = {0};
1845 bool replaces[Natts_pg_transform] = {0};
1846 Oid transformid;
1847 HeapTuple tuple;
1848 HeapTuple newtuple;
1849 Relation relation;
1850 ObjectAddress myself,
1851 referenced;
1852 ObjectAddresses *addrs;
1853 bool is_replace;
1854
1855 /*
1856 * Get the type
1857 */
1858 typeid = typenameTypeId(NULL, stmt->type_name);
1859 typtype = get_typtype(typeid);
1860
1861 if (typtype == TYPTYPE_PSEUDO)
1862 ereport(ERROR,
1863 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1864 errmsg("data type %s is a pseudo-type",
1865 TypeNameToString(stmt->type_name))));
1866
1867 if (typtype == TYPTYPE_DOMAIN)
1868 ereport(ERROR,
1869 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1870 errmsg("data type %s is a domain",
1871 TypeNameToString(stmt->type_name))));
1872
1873 if (!object_ownercheck(TypeRelationId, typeid, GetUserId()))
1875
1876 aclresult = object_aclcheck(TypeRelationId, typeid, GetUserId(), ACL_USAGE);
1877 if (aclresult != ACLCHECK_OK)
1878 aclcheck_error_type(aclresult, typeid);
1879
1880 /*
1881 * Get the language
1882 */
1883 langid = get_language_oid(stmt->lang, false);
1884
1885 aclresult = object_aclcheck(LanguageRelationId, langid, GetUserId(), ACL_USAGE);
1886 if (aclresult != ACLCHECK_OK)
1887 aclcheck_error(aclresult, OBJECT_LANGUAGE, stmt->lang);
1888
1889 /*
1890 * Get the functions
1891 */
1892 if (stmt->fromsql)
1893 {
1894 fromsqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->fromsql, false);
1895
1896 if (!object_ownercheck(ProcedureRelationId, fromsqlfuncid, GetUserId()))
1898
1899 aclresult = object_aclcheck(ProcedureRelationId, fromsqlfuncid, GetUserId(), ACL_EXECUTE);
1900 if (aclresult != ACLCHECK_OK)
1901 aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->fromsql->objname));
1902
1903 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fromsqlfuncid));
1904 if (!HeapTupleIsValid(tuple))
1905 elog(ERROR, "cache lookup failed for function %u", fromsqlfuncid);
1906 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1907 if (procstruct->prorettype != INTERNALOID)
1908 ereport(ERROR,
1909 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1910 errmsg("return data type of FROM SQL function must be %s",
1911 "internal")));
1912 check_transform_function(procstruct);
1913 ReleaseSysCache(tuple);
1914 }
1915 else
1916 fromsqlfuncid = InvalidOid;
1917
1918 if (stmt->tosql)
1919 {
1920 tosqlfuncid = LookupFuncWithArgs(OBJECT_FUNCTION, stmt->tosql, false);
1921
1922 if (!object_ownercheck(ProcedureRelationId, tosqlfuncid, GetUserId()))
1924
1925 aclresult = object_aclcheck(ProcedureRelationId, tosqlfuncid, GetUserId(), ACL_EXECUTE);
1926 if (aclresult != ACLCHECK_OK)
1927 aclcheck_error(aclresult, OBJECT_FUNCTION, NameListToString(stmt->tosql->objname));
1928
1929 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(tosqlfuncid));
1930 if (!HeapTupleIsValid(tuple))
1931 elog(ERROR, "cache lookup failed for function %u", tosqlfuncid);
1932 procstruct = (Form_pg_proc) GETSTRUCT(tuple);
1933 if (procstruct->prorettype != typeid)
1934 ereport(ERROR,
1935 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1936 errmsg("return data type of TO SQL function must be the transform data type")));
1937 check_transform_function(procstruct);
1938 ReleaseSysCache(tuple);
1939 }
1940 else
1941 tosqlfuncid = InvalidOid;
1942
1943 /*
1944 * Ready to go
1945 */
1946 values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid);
1947 values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid);
1948 values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid);
1949 values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid);
1950
1951 relation = table_open(TransformRelationId, RowExclusiveLock);
1952
1953 tuple = SearchSysCache2(TRFTYPELANG,
1954 ObjectIdGetDatum(typeid),
1955 ObjectIdGetDatum(langid));
1956 if (HeapTupleIsValid(tuple))
1957 {
1959
1960 if (!stmt->replace)
1961 ereport(ERROR,
1963 errmsg("transform for type %s language \"%s\" already exists",
1964 format_type_be(typeid),
1965 stmt->lang)));
1966
1967 replaces[Anum_pg_transform_trffromsql - 1] = true;
1968 replaces[Anum_pg_transform_trftosql - 1] = true;
1969
1970 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
1971 CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1972
1973 transformid = form->oid;
1974 ReleaseSysCache(tuple);
1975 is_replace = true;
1976 }
1977 else
1978 {
1979 transformid = GetNewOidWithIndex(relation, TransformOidIndexId,
1980 Anum_pg_transform_oid);
1981 values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid);
1982 newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1983 CatalogTupleInsert(relation, newtuple);
1984 is_replace = false;
1985 }
1986
1987 if (is_replace)
1988 deleteDependencyRecordsFor(TransformRelationId, transformid, true);
1989
1990 addrs = new_object_addresses();
1991
1992 /* make dependency entries */
1993 ObjectAddressSet(myself, TransformRelationId, transformid);
1994
1995 /* dependency on language */
1996 ObjectAddressSet(referenced, LanguageRelationId, langid);
1997 add_exact_object_address(&referenced, addrs);
1998
1999 /* dependency on type */
2000 ObjectAddressSet(referenced, TypeRelationId, typeid);
2001 add_exact_object_address(&referenced, addrs);
2002
2003 /* dependencies on functions */
2004 if (OidIsValid(fromsqlfuncid))
2005 {
2006 ObjectAddressSet(referenced, ProcedureRelationId, fromsqlfuncid);
2007 add_exact_object_address(&referenced, addrs);
2008 }
2009 if (OidIsValid(tosqlfuncid))
2010 {
2011 ObjectAddressSet(referenced, ProcedureRelationId, tosqlfuncid);
2012 add_exact_object_address(&referenced, addrs);
2013 }
2014
2016 free_object_addresses(addrs);
2017
2018 /* dependency on extension */
2019 recordDependencyOnCurrentExtension(&myself, is_replace);
2020
2021 /* Post creation hook for new transform */
2022 InvokeObjectPostCreateHook(TransformRelationId, transformid, 0);
2023
2024 heap_freetuple(newtuple);
2025
2026 table_close(relation, RowExclusiveLock);
2027
2028 return myself;
2029}
2030
2031
2032/*
2033 * get_transform_oid - given type OID and language OID, look up a transform OID
2034 *
2035 * If missing_ok is false, throw an error if the transform is not found. If
2036 * true, just return InvalidOid.
2037 */
2038Oid
2039get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
2040{
2041 Oid oid;
2042
2043 oid = GetSysCacheOid2(TRFTYPELANG, Anum_pg_transform_oid,
2044 ObjectIdGetDatum(type_id),
2045 ObjectIdGetDatum(lang_id));
2046 if (!OidIsValid(oid) && !missing_ok)
2047 ereport(ERROR,
2048 (errcode(ERRCODE_UNDEFINED_OBJECT),
2049 errmsg("transform for type %s language \"%s\" does not exist",
2050 format_type_be(type_id),
2051 get_language_name(lang_id, false))));
2052 return oid;
2053}
2054
2055
2056/*
2057 * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA/RENAME
2058 *
2059 * Is there a function with the given name and signature already in the given
2060 * namespace? If so, raise an appropriate error message.
2061 */
2062void
2064 oidvector *proargtypes, Oid nspOid)
2065{
2066 /* check for duplicate name (more friendly than unique-index failure) */
2067 if (SearchSysCacheExists3(PROCNAMEARGSNSP,
2069 PointerGetDatum(proargtypes),
2070 ObjectIdGetDatum(nspOid)))
2071 ereport(ERROR,
2072 (errcode(ERRCODE_DUPLICATE_FUNCTION),
2073 errmsg("function %s already exists in schema \"%s\"",
2075 NIL, proargtypes->values),
2076 get_namespace_name(nspOid))));
2077}
2078
2079/*
2080 * ExecuteDoStmt
2081 * Execute inline procedural-language code
2082 *
2083 * See at ExecuteCallStmt() about the atomic argument.
2084 */
2085void
2086ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
2087{
2089 ListCell *arg;
2090 DefElem *as_item = NULL;
2091 DefElem *language_item = NULL;
2092 char *language;
2093 Oid laninline;
2094 HeapTuple languageTuple;
2095 Form_pg_language languageStruct;
2096
2097 /* Process options we got from gram.y */
2098 foreach(arg, stmt->args)
2099 {
2100 DefElem *defel = (DefElem *) lfirst(arg);
2101
2102 if (strcmp(defel->defname, "as") == 0)
2103 {
2104 if (as_item)
2105 errorConflictingDefElem(defel, pstate);
2106 as_item = defel;
2107 }
2108 else if (strcmp(defel->defname, "language") == 0)
2109 {
2110 if (language_item)
2111 errorConflictingDefElem(defel, pstate);
2112 language_item = defel;
2113 }
2114 else
2115 elog(ERROR, "option \"%s\" not recognized",
2116 defel->defname);
2117 }
2118
2119 if (as_item)
2120 codeblock->source_text = strVal(as_item->arg);
2121 else
2122 ereport(ERROR,
2123 (errcode(ERRCODE_SYNTAX_ERROR),
2124 errmsg("no inline code specified")));
2125
2126 /* if LANGUAGE option wasn't specified, use the default */
2127 if (language_item)
2128 language = strVal(language_item->arg);
2129 else
2130 language = "plpgsql";
2131
2132 /* Look up the language and validate permissions */
2133 languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
2134 if (!HeapTupleIsValid(languageTuple))
2135 ereport(ERROR,
2136 (errcode(ERRCODE_UNDEFINED_OBJECT),
2137 errmsg("language \"%s\" does not exist", language),
2138 (extension_file_exists(language) ?
2139 errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
2140
2141 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
2142 codeblock->langOid = languageStruct->oid;
2143 codeblock->langIsTrusted = languageStruct->lanpltrusted;
2144 codeblock->atomic = atomic;
2145
2146 if (languageStruct->lanpltrusted)
2147 {
2148 /* if trusted language, need USAGE privilege */
2149 AclResult aclresult;
2150
2151 aclresult = object_aclcheck(LanguageRelationId, codeblock->langOid, GetUserId(),
2152 ACL_USAGE);
2153 if (aclresult != ACLCHECK_OK)
2155 NameStr(languageStruct->lanname));
2156 }
2157 else
2158 {
2159 /* if untrusted language, must be superuser */
2160 if (!superuser())
2162 NameStr(languageStruct->lanname));
2163 }
2164
2165 /* get the handler function's OID */
2166 laninline = languageStruct->laninline;
2167 if (!OidIsValid(laninline))
2168 ereport(ERROR,
2169 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2170 errmsg("language \"%s\" does not support inline code execution",
2171 NameStr(languageStruct->lanname))));
2172
2173 ReleaseSysCache(languageTuple);
2174
2175 /* execute the inline handler */
2176 OidFunctionCall1(laninline, PointerGetDatum(codeblock));
2177}
2178
2179/*
2180 * Execute CALL statement
2181 *
2182 * Inside a top-level CALL statement, transaction-terminating commands such as
2183 * COMMIT or a PL-specific equivalent are allowed. The terminology in the SQL
2184 * standard is that CALL establishes a non-atomic execution context. Most
2185 * other commands establish an atomic execution context, in which transaction
2186 * control actions are not allowed. If there are nested executions of CALL,
2187 * we want to track the execution context recursively, so that the nested
2188 * CALLs can also do transaction control. Note, however, that for example in
2189 * CALL -> SELECT -> CALL, the second call cannot do transaction control,
2190 * because the SELECT in between establishes an atomic execution context.
2191 *
2192 * So when ExecuteCallStmt() is called from the top level, we pass in atomic =
2193 * false (recall that that means transactions = yes). We then create a
2194 * CallContext node with content atomic = false, which is passed in the
2195 * fcinfo->context field to the procedure invocation. The language
2196 * implementation should then take appropriate measures to allow or prevent
2197 * transaction commands based on that information, e.g., call
2198 * SPI_connect_ext(SPI_OPT_NONATOMIC). The language should also pass on the
2199 * atomic flag to any nested invocations to CALL.
2200 *
2201 * The expression data structures and execution context that we create
2202 * within this function are children of the portalContext of the Portal
2203 * that the CALL utility statement runs in. Therefore, any pass-by-ref
2204 * values that we're passing to the procedure will survive transaction
2205 * commits that might occur inside the procedure.
2206 */
2207void
2209{
2210 LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
2211 ListCell *lc;
2212 FuncExpr *fexpr;
2213 int nargs;
2214 int i;
2215 AclResult aclresult;
2216 FmgrInfo flinfo;
2217 CallContext *callcontext;
2218 EState *estate;
2219 ExprContext *econtext;
2220 HeapTuple tp;
2222 Datum retval;
2223
2224 fexpr = stmt->funcexpr;
2225 Assert(fexpr);
2226 Assert(IsA(fexpr, FuncExpr));
2227
2228 aclresult = object_aclcheck(ProcedureRelationId, fexpr->funcid, GetUserId(), ACL_EXECUTE);
2229 if (aclresult != ACLCHECK_OK)
2231
2232 /* Prep the context object we'll pass to the procedure */
2233 callcontext = makeNode(CallContext);
2234 callcontext->atomic = atomic;
2235
2236 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2237 if (!HeapTupleIsValid(tp))
2238 elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
2239
2240 /*
2241 * If proconfig is set we can't allow transaction commands because of the
2242 * way the GUC stacking works: The transaction boundary would have to pop
2243 * the proconfig setting off the stack. That restriction could be lifted
2244 * by redesigning the GUC nesting mechanism a bit.
2245 */
2246 if (!heap_attisnull(tp, Anum_pg_proc_proconfig, NULL))
2247 callcontext->atomic = true;
2248
2249 /*
2250 * In security definer procedures, we can't allow transaction commands.
2251 * StartTransaction() insists that the security context stack is empty,
2252 * and AbortTransaction() resets the security context. This could be
2253 * reorganized, but right now it doesn't work.
2254 */
2255 if (((Form_pg_proc) GETSTRUCT(tp))->prosecdef)
2256 callcontext->atomic = true;
2257
2258 ReleaseSysCache(tp);
2259
2260 /* safety check; see ExecInitFunc() */
2261 nargs = list_length(fexpr->args);
2262 if (nargs > FUNC_MAX_ARGS)
2263 ereport(ERROR,
2264 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
2265 errmsg_plural("cannot pass more than %d argument to a procedure",
2266 "cannot pass more than %d arguments to a procedure",
2268 FUNC_MAX_ARGS)));
2269
2270 /* Initialize function call structure */
2272 fmgr_info(fexpr->funcid, &flinfo);
2273 fmgr_info_set_expr((Node *) fexpr, &flinfo);
2274 InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid,
2275 (Node *) callcontext, NULL);
2276
2277 /*
2278 * Evaluate procedure arguments inside a suitable execution context. Note
2279 * we can't free this context till the procedure returns.
2280 */
2281 estate = CreateExecutorState();
2282 estate->es_param_list_info = params;
2283 econtext = CreateExprContext(estate);
2284
2285 /*
2286 * If we're called in non-atomic context, we also have to ensure that the
2287 * argument expressions run with an up-to-date snapshot. Our caller will
2288 * have provided a current snapshot in atomic contexts, but not in
2289 * non-atomic contexts, because the possibility of a COMMIT/ROLLBACK
2290 * destroying the snapshot makes higher-level management too complicated.
2291 */
2292 if (!atomic)
2294
2295 i = 0;
2296 foreach(lc, fexpr->args)
2297 {
2298 ExprState *exprstate;
2299 Datum val;
2300 bool isnull;
2301
2302 exprstate = ExecPrepareExpr(lfirst(lc), estate);
2303
2304 val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
2305
2306 fcinfo->args[i].value = val;
2307 fcinfo->args[i].isnull = isnull;
2308
2309 i++;
2310 }
2311
2312 /* Get rid of temporary snapshot for arguments, if we made one */
2313 if (!atomic)
2315
2316 /* Here we actually call the procedure */
2317 pgstat_init_function_usage(fcinfo, &fcusage);
2318 retval = FunctionCallInvoke(fcinfo);
2319 pgstat_end_function_usage(&fcusage, true);
2320
2321 /* Handle the procedure's outputs */
2322 if (fexpr->funcresulttype == VOIDOID)
2323 {
2324 /* do nothing */
2325 }
2326 else if (fexpr->funcresulttype == RECORDOID)
2327 {
2328 /* send tuple to client */
2329 HeapTupleHeader td;
2330 Oid tupType;
2331 int32 tupTypmod;
2332 TupleDesc retdesc;
2333 HeapTupleData rettupdata;
2334 TupOutputState *tstate;
2335 TupleTableSlot *slot;
2336
2337 if (fcinfo->isnull)
2338 elog(ERROR, "procedure returned null record");
2339
2340 /*
2341 * Ensure there's an active snapshot whilst we execute whatever's
2342 * involved here. Note that this is *not* sufficient to make the
2343 * world safe for TOAST pointers to be included in the returned data:
2344 * the referenced data could have gone away while we didn't hold a
2345 * snapshot. Hence, it's incumbent on PLs that can do COMMIT/ROLLBACK
2346 * to not return TOAST pointers, unless those pointers were fetched
2347 * after the last COMMIT/ROLLBACK in the procedure.
2348 *
2349 * XXX that is a really nasty, hard-to-test requirement. Is there a
2350 * way to remove it?
2351 */
2353
2354 td = DatumGetHeapTupleHeader(retval);
2355 tupType = HeapTupleHeaderGetTypeId(td);
2356 tupTypmod = HeapTupleHeaderGetTypMod(td);
2357 retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
2358
2359 tstate = begin_tup_output_tupdesc(dest, retdesc,
2361
2362 rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
2363 ItemPointerSetInvalid(&(rettupdata.t_self));
2364 rettupdata.t_tableOid = InvalidOid;
2365 rettupdata.t_data = td;
2366
2367 slot = ExecStoreHeapTuple(&rettupdata, tstate->slot, false);
2368 tstate->dest->receiveSlot(slot, tstate->dest);
2369
2370 end_tup_output(tstate);
2371
2372 ReleaseTupleDesc(retdesc);
2373 }
2374 else
2375 elog(ERROR, "unexpected result type for procedure: %u",
2376 fexpr->funcresulttype);
2377
2378 FreeExecutorState(estate);
2379}
2380
2381/*
2382 * Construct the tuple descriptor for a CALL statement return
2383 */
2386{
2387 FuncExpr *fexpr;
2388 HeapTuple tuple;
2389 TupleDesc tupdesc;
2390
2391 fexpr = stmt->funcexpr;
2392
2393 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
2394 if (!HeapTupleIsValid(tuple))
2395 elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid);
2396
2397 tupdesc = build_function_result_tupdesc_t(tuple);
2398
2399 ReleaseSysCache(tuple);
2400
2401 /*
2402 * The result of build_function_result_tupdesc_t has the right column
2403 * names, but it just has the declared output argument types, which is the
2404 * wrong thing in polymorphic cases. Get the correct types by examining
2405 * stmt->outargs. We intentionally keep the atttypmod as -1 and the
2406 * attcollation as the type's default, since that's always the appropriate
2407 * thing for function outputs; there's no point in considering any
2408 * additional info available from outargs. Note that tupdesc is null if
2409 * there are no outargs.
2410 */
2411 if (tupdesc)
2412 {
2413 Assert(tupdesc->natts == list_length(stmt->outargs));
2414 for (int i = 0; i < tupdesc->natts; i++)
2415 {
2416 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2417 Node *outarg = (Node *) list_nth(stmt->outargs, i);
2418
2419 TupleDescInitEntry(tupdesc,
2420 i + 1,
2421 NameStr(att->attname),
2422 exprType(outarg),
2423 -1,
2424 0);
2425 }
2426 }
2427
2428 return tupdesc;
2429}
AclResult
Definition: acl.h:182
@ ACLCHECK_NO_PRIV
Definition: acl.h:184
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2652
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3834
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4088
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:2971
#define DatumGetArrayTypeP(X)
Definition: array.h:261
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3382
static Datum values[MAXATTR]
Definition: bootstrap.c:153
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define NameStr(name)
Definition: c.h:756
int16_t int16
Definition: c.h:538
int32_t int32
Definition: c.h:539
float float4
Definition: c.h:639
#define OidIsValid(objectId)
Definition: c.h:779
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:448
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:47
List * defGetQualifiedName(DefElem *def)
Definition: define.c:239
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:371
double defGetNumeric(DefElem *def)
Definition: define.c:68
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2870
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2661
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2615
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2901
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1193
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:150
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:765
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2522
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2444
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1541
ExprContext * CreateExprContext(EState *estate)
Definition: execUtils.c:307
void FreeExecutorState(EState *estate)
Definition: execUtils.c:192
EState * CreateExecutorState(void)
Definition: execUtils.c:88
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:436
bool extension_file_exists(const char *extensionName)
Definition: extension.c:2493
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:128
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:720
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
Definition: funcapi.c:1705
void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
ObjectAddress CreateCast(CreateCastStmt *stmt)
static void compute_return_type(TypeName *returnType, Oid languageOid, Oid *prorettype_p, bool *returnsSet_p)
Definition: functioncmds.c:88
static Oid interpret_func_support(DefElem *defel)
Definition: functioncmds.c:687
static void compute_function_attributes(ParseState *pstate, bool is_procedure, List *options, List **as, char **language, Node **transform, bool *windowfunc_p, char *volatility_p, bool *strict_p, bool *security_definer, bool *leakproof_p, ArrayType **proconfig, float4 *procost, float4 *prorows, Oid *prosupport, char *parallel_p)
Definition: functioncmds.c:731
void interpret_function_parameter_list(ParseState *pstate, List *parameters, Oid languageOid, ObjectType objtype, oidvector **parameterTypes, List **parameterTypes_list, ArrayType **allParameterTypes, ArrayType **parameterModes, ArrayType **parameterNames, List **inParameterNames_list, List **parameterDefaults, Oid *variadicArgType, Oid *requiredResultType)
Definition: functioncmds.c:185
static bool compute_common_attribute(ParseState *pstate, bool is_procedure, DefElem *defel, DefElem **volatility_item, DefElem **strict_item, DefElem **security_item, DefElem **leakproof_item, List **set_items, DefElem **cost_item, DefElem **rows_item, DefElem **support_item, DefElem **parallel_item)
Definition: functioncmds.c:517
static char interpret_func_volatility(DefElem *defel)
Definition: functioncmds.c:619
ObjectAddress CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
void IsThereFunctionInNamespace(const char *proname, int pronargs, oidvector *proargtypes, Oid nspOid)
ObjectAddress AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
TupleDesc CallStmtResultDesc(CallStmt *stmt)
static void interpret_AS_clause(Oid languageOid, const char *languageName, char *funcname, List *as, Node *sql_body_in, List *parameterTypes, List *inParameterNames, char **prosrc_str_p, char **probin_str_p, Node **sql_body_out, const char *queryString)
Definition: functioncmds.c:868
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
static void check_transform_function(Form_pg_proc procstruct)
ObjectAddress CreateTransform(CreateTransformStmt *stmt)
static ArrayType * update_proconfig_value(ArrayType *a, List *set_items)
Definition: functioncmds.c:662
void RemoveFunctionById(Oid funcOid)
static char interpret_func_parallel(DefElem *defel)
Definition: functioncmds.c:637
void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Definition: functions.c:340
SQLFunctionParseInfo * SQLFunctionParseInfoPtr
Definition: functions.h:35
void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
ArrayType * GUCArrayAdd(ArrayType *array, const char *name, const char *value)
Definition: guc.c:6328
ArrayType * GUCArrayDelete(ArrayType *array, const char *name)
Definition: guc.c:6405
char * ExtractSetVariableArgs(VariableSetStmt *stmt)
Definition: guc_funcs.c:167
Assert(PointerIsAligned(start, uint64))
const char * str
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1210
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:456
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
Definition: htup_details.h:516
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
Definition: htup_details.h:492
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
Definition: htup_details.h:504
#define stmt
Definition: indent_codes.h:59
#define funcname
Definition: indent_codes.h:69
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition: indexing.c:365
long val
Definition: informix.c:689
int x
Definition: isn.c:75
int a
Definition: isn.c:73
int i
Definition: isn.c:77
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2926
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2438
char * get_language_name(Oid langoid, bool missing_ok)
Definition: lsyscache.c:1280
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1775
char get_typtype(Oid typid)
Definition: lsyscache.c:2796
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2999
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3533
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1822
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
Oid GetUserId(void)
Definition: miscinit.c:469
char * NameListToString(const List *names)
Definition: namespace.c:3664
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition: namespace.c:3557
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
@ CMD_UTILITY
Definition: nodes.h:280
#define makeNode(_type_)
Definition: nodes.h:161
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:213
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:87
Node * coerce_to_specific_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *constructName)
bool IsBinaryCoercibleWithCast(Oid srctype, Oid targettype, Oid *castoid)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:119
const char * funcname_signature_string(const char *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2116
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2153
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2331
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2269
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:72
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:39
@ EXPR_KIND_FUNCTION_DEFAULT
Definition: parse_node.h:71
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:478
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:38
Oid typeTypeId(Type tp)
Definition: parse_type.c:590
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
#define ACL_USAGE
Definition: parsenodes.h:84
FunctionParameterMode
Definition: parsenodes.h:3575
@ FUNC_PARAM_IN
Definition: parsenodes.h:3577
@ FUNC_PARAM_DEFAULT
Definition: parsenodes.h:3583
@ FUNC_PARAM_OUT
Definition: parsenodes.h:3578
@ FUNC_PARAM_TABLE
Definition: parsenodes.h:3581
@ FUNC_PARAM_VARIADIC
Definition: parsenodes.h:3580
@ VAR_RESET_ALL
Definition: parsenodes.h:2699
ObjectType
Definition: parsenodes.h:2324
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2326
@ OBJECT_SCHEMA
Definition: parsenodes.h:2361
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2354
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2346
@ OBJECT_FUNCTION
Definition: parsenodes.h:2344
#define ACL_EXECUTE
Definition: parsenodes.h:83
#define ACL_CREATE
Definition: parsenodes.h:85
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:324
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
void * arg
ObjectAddress CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, Oid incastid, Oid outcastid, char castcontext, char castmethod, DependencyType behavior)
Definition: pg_cast.c:49
#define FUNC_MAX_ARGS
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:45
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:457
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:301
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:193
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
static Oid list_nth_oid(const List *list, int n)
Definition: pg_list.h:321
#define list_make1(x1)
Definition: pg_list.h:212
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define lfirst_oid(lc)
Definition: pg_list.h:174
ObjectAddress ProcedureCreate(const char *procedureName, Oid procNamespace, bool replace, bool returnsSet, Oid returnType, Oid proowner, Oid languageObjectId, Oid languageValidator, const char *prosrc, const char *probin, Node *prosqlbody, char prokind, bool security_definer, bool isLeakProof, bool isStrict, char volatility, char parallel, oidvector *parameterTypes, Datum allParameterTypes, Datum parameterModes, Datum parameterNames, List *parameterDefaults, Datum trftypes, List *trfoids, Datum proconfig, Oid prosupport, float4 procost, float4 prorows)
Definition: pg_proc.c:99
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
int16 pronargs
Definition: pg_proc.h:81
NameData proname
Definition: pg_proc.h:35
FormData_pg_transform * Form_pg_transform
Definition: pg_transform.h:43
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:57
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
void pgstat_drop_function(Oid proid)
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
uint64_t Datum
Definition: postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:360
static Datum CharGetDatum(char X)
Definition: postgres.h:132
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
void EnsurePortalSnapshotExists(void)
Definition: pquery.c:1760
@ COERCION_ASSIGNMENT
Definition: primnodes.h:747
@ COERCION_EXPLICIT
Definition: primnodes.h:749
@ COERCION_IMPLICIT
Definition: primnodes.h:746
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:227
#define RelationGetDescr(relation)
Definition: rel.h:541
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:272
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:683
void PopActiveSnapshot(void)
Definition: snapmgr.c:776
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
char * defname
Definition: parsenodes.h:843
ParseLoc location
Definition: parsenodes.h:847
Node * arg
Definition: parsenodes.h:844
ParamListInfo es_param_list_info
Definition: execnodes.h:704
Definition: fmgr.h:57
Oid funcid
Definition: primnodes.h:782
List * args
Definition: primnodes.h:800
TypeName * argType
Definition: parsenodes.h:3590
FunctionParameterMode mode
Definition: parsenodes.h:3591
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
char * source_text
Definition: parsenodes.h:3621
Definition: pg_list.h:54
Definition: nodes.h:135
const char * p_sourcetext
Definition: parse_node.h:195
List * p_rtable
Definition: parse_node.h:196
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:141
TupleTableSlot * slot
Definition: executor.h:612
DestReceiver * dest
Definition: executor.h:613
bool setof
Definition: parsenodes.h:287
List * names
Definition: parsenodes.h:285
ParseLoc location
Definition: parsenodes.h:292
List * typmods
Definition: parsenodes.h:289
VariableSetKind kind
Definition: parsenodes.h:2707
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
Definition: c.h:736
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:743
bool superuser(void)
Definition: superuser.c:46
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:595
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:230
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:91
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:104
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:111
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:842
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:219
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1921
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2368
String * makeString(char *str)
Definition: value.c:63
#define boolVal(v)
Definition: value.h:81
#define strVal(v)
Definition: value.h:82
bool contain_var_clause(Node *node)
Definition: var.c:406
void CommandCounterIncrement(void)
Definition: xact.c:1101