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