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