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