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