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