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