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