OSDN Git Service

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