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