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