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