Header And Logo

PostgreSQL
| The world's most advanced open source database.

functioncmds.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * functioncmds.c
00004  *
00005  *    Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
00006  *    CAST commands.
00007  *
00008  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00009  * Portions Copyright (c) 1994, Regents of the University of California
00010  *
00011  *
00012  * IDENTIFICATION
00013  *    src/backend/commands/functioncmds.c
00014  *
00015  * DESCRIPTION
00016  *    These routines take the parse tree and pick out the
00017  *    appropriate arguments/flags, and pass the results to the
00018  *    corresponding "FooDefine" routines (in src/catalog) that do
00019  *    the actual catalog-munging.  These routines also verify permission
00020  *    of the user to execute the command.
00021  *
00022  * NOTES
00023  *    These things must be defined and committed in the following order:
00024  *      "create function":
00025  *              input/output, recv/send procedures
00026  *      "create type":
00027  *              type
00028  *      "create operator":
00029  *              operators
00030  *
00031  *-------------------------------------------------------------------------
00032  */
00033 #include "postgres.h"
00034 
00035 #include "access/genam.h"
00036 #include "access/heapam.h"
00037 #include "access/htup_details.h"
00038 #include "access/sysattr.h"
00039 #include "catalog/dependency.h"
00040 #include "catalog/indexing.h"
00041 #include "catalog/objectaccess.h"
00042 #include "catalog/pg_aggregate.h"
00043 #include "catalog/pg_cast.h"
00044 #include "catalog/pg_language.h"
00045 #include "catalog/pg_namespace.h"
00046 #include "catalog/pg_proc.h"
00047 #include "catalog/pg_proc_fn.h"
00048 #include "catalog/pg_type.h"
00049 #include "catalog/pg_type_fn.h"
00050 #include "commands/alter.h"
00051 #include "commands/defrem.h"
00052 #include "commands/proclang.h"
00053 #include "miscadmin.h"
00054 #include "optimizer/var.h"
00055 #include "parser/parse_coerce.h"
00056 #include "parser/parse_collate.h"
00057 #include "parser/parse_expr.h"
00058 #include "parser/parse_func.h"
00059 #include "parser/parse_type.h"
00060 #include "utils/acl.h"
00061 #include "utils/builtins.h"
00062 #include "utils/fmgroids.h"
00063 #include "utils/guc.h"
00064 #include "utils/lsyscache.h"
00065 #include "utils/rel.h"
00066 #include "utils/syscache.h"
00067 #include "utils/tqual.h"
00068 
00069 /*
00070  *   Examine the RETURNS clause of the CREATE FUNCTION statement
00071  *   and return information about it as *prorettype_p and *returnsSet.
00072  *
00073  * This is more complex than the average typename lookup because we want to
00074  * allow a shell type to be used, or even created if the specified return type
00075  * doesn't exist yet.  (Without this, there's no way to define the I/O procs
00076  * for a new type.)  But SQL function creation won't cope, so error out if
00077  * the target language is SQL.  (We do this here, not in the SQL-function
00078  * validator, so as not to produce a NOTICE and then an ERROR for the same
00079  * condition.)
00080  */
00081 static void
00082 compute_return_type(TypeName *returnType, Oid languageOid,
00083                     Oid *prorettype_p, bool *returnsSet_p)
00084 {
00085     Oid         rettype;
00086     Type        typtup;
00087     AclResult   aclresult;
00088 
00089     typtup = LookupTypeName(NULL, returnType, NULL);
00090 
00091 
00092     if (typtup)
00093     {
00094         if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
00095         {
00096             if (languageOid == SQLlanguageId)
00097                 ereport(ERROR,
00098                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00099                          errmsg("SQL function cannot return shell type %s",
00100                                 TypeNameToString(returnType))));
00101             else
00102                 ereport(NOTICE,
00103                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00104                          errmsg("return type %s is only a shell",
00105                                 TypeNameToString(returnType))));
00106         }
00107         rettype = typeTypeId(typtup);
00108         ReleaseSysCache(typtup);
00109     }
00110     else
00111     {
00112         char       *typnam = TypeNameToString(returnType);
00113         Oid         namespaceId;
00114         AclResult   aclresult;
00115         char       *typname;
00116 
00117         /*
00118          * Only C-coded functions can be I/O functions.  We enforce this
00119          * restriction here mainly to prevent littering the catalogs with
00120          * shell types due to simple typos in user-defined function
00121          * definitions.
00122          */
00123         if (languageOid != INTERNALlanguageId &&
00124             languageOid != ClanguageId)
00125             ereport(ERROR,
00126                     (errcode(ERRCODE_UNDEFINED_OBJECT),
00127                      errmsg("type \"%s\" does not exist", typnam)));
00128 
00129         /* Reject if there's typmod decoration, too */
00130         if (returnType->typmods != NIL)
00131             ereport(ERROR,
00132                     (errcode(ERRCODE_SYNTAX_ERROR),
00133             errmsg("type modifier cannot be specified for shell type \"%s\"",
00134                    typnam)));
00135 
00136         /* Otherwise, go ahead and make a shell type */
00137         ereport(NOTICE,
00138                 (errcode(ERRCODE_UNDEFINED_OBJECT),
00139                  errmsg("type \"%s\" is not yet defined", typnam),
00140                  errdetail("Creating a shell type definition.")));
00141         namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
00142                                                         &typname);
00143         aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
00144                                           ACL_CREATE);
00145         if (aclresult != ACLCHECK_OK)
00146             aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00147                            get_namespace_name(namespaceId));
00148         rettype = TypeShellMake(typname, namespaceId, GetUserId());
00149         Assert(OidIsValid(rettype));
00150     }
00151 
00152     aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
00153     if (aclresult != ACLCHECK_OK)
00154         aclcheck_error_type(aclresult, rettype);
00155 
00156     *prorettype_p = rettype;
00157     *returnsSet_p = returnType->setof;
00158 }
00159 
00160 /*
00161  * Interpret the parameter list of the CREATE FUNCTION statement.
00162  *
00163  * Results are stored into output parameters.  parameterTypes must always
00164  * be created, but the other arrays are set to NULL if not needed.
00165  * requiredResultType is set to InvalidOid if there are no OUT parameters,
00166  * else it is set to the OID of the implied result type.
00167  */
00168 static void
00169 examine_parameter_list(List *parameters, Oid languageOid,
00170                        const char *queryString,
00171                        oidvector **parameterTypes,
00172                        ArrayType **allParameterTypes,
00173                        ArrayType **parameterModes,
00174                        ArrayType **parameterNames,
00175                        List **parameterDefaults,
00176                        Oid *requiredResultType)
00177 {
00178     int         parameterCount = list_length(parameters);
00179     Oid        *inTypes;
00180     int         inCount = 0;
00181     Datum      *allTypes;
00182     Datum      *paramModes;
00183     Datum      *paramNames;
00184     int         outCount = 0;
00185     int         varCount = 0;
00186     bool        have_names = false;
00187     bool        have_defaults = false;
00188     ListCell   *x;
00189     int         i;
00190     ParseState *pstate;
00191 
00192     *requiredResultType = InvalidOid;   /* default result */
00193 
00194     inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
00195     allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
00196     paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
00197     paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
00198     *parameterDefaults = NIL;
00199 
00200     /* may need a pstate for parse analysis of default exprs */
00201     pstate = make_parsestate(NULL);
00202     pstate->p_sourcetext = queryString;
00203 
00204     /* Scan the list and extract data into work arrays */
00205     i = 0;
00206     foreach(x, parameters)
00207     {
00208         FunctionParameter *fp = (FunctionParameter *) lfirst(x);
00209         TypeName   *t = fp->argType;
00210         bool        isinput = false;
00211         Oid         toid;
00212         Type        typtup;
00213         AclResult   aclresult;
00214 
00215         typtup = LookupTypeName(NULL, t, NULL);
00216         if (typtup)
00217         {
00218             if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
00219             {
00220                 /* As above, hard error if language is SQL */
00221                 if (languageOid == SQLlanguageId)
00222                     ereport(ERROR,
00223                             (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00224                            errmsg("SQL function cannot accept shell type %s",
00225                                   TypeNameToString(t))));
00226                 else
00227                     ereport(NOTICE,
00228                             (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00229                              errmsg("argument type %s is only a shell",
00230                                     TypeNameToString(t))));
00231             }
00232             toid = typeTypeId(typtup);
00233             ReleaseSysCache(typtup);
00234         }
00235         else
00236         {
00237             ereport(ERROR,
00238                     (errcode(ERRCODE_UNDEFINED_OBJECT),
00239                      errmsg("type %s does not exist",
00240                             TypeNameToString(t))));
00241             toid = InvalidOid;  /* keep compiler quiet */
00242         }
00243 
00244         aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);
00245         if (aclresult != ACLCHECK_OK)
00246             aclcheck_error_type(aclresult, toid);
00247 
00248         if (t->setof)
00249             ereport(ERROR,
00250                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00251                      errmsg("functions cannot accept set arguments")));
00252 
00253         /* handle input parameters */
00254         if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
00255         {
00256             /* other input parameters can't follow a VARIADIC parameter */
00257             if (varCount > 0)
00258                 ereport(ERROR,
00259                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00260                          errmsg("VARIADIC parameter must be the last input parameter")));
00261             inTypes[inCount++] = toid;
00262             isinput = true;
00263         }
00264 
00265         /* handle output parameters */
00266         if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
00267         {
00268             if (outCount == 0)  /* save first output param's type */
00269                 *requiredResultType = toid;
00270             outCount++;
00271         }
00272 
00273         if (fp->mode == FUNC_PARAM_VARIADIC)
00274         {
00275             varCount++;
00276             /* validate variadic parameter type */
00277             switch (toid)
00278             {
00279                 case ANYARRAYOID:
00280                 case ANYOID:
00281                     /* okay */
00282                     break;
00283                 default:
00284                     if (!OidIsValid(get_element_type(toid)))
00285                         ereport(ERROR,
00286                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00287                              errmsg("VARIADIC parameter must be an array")));
00288                     break;
00289             }
00290         }
00291 
00292         allTypes[i] = ObjectIdGetDatum(toid);
00293 
00294         paramModes[i] = CharGetDatum(fp->mode);
00295 
00296         if (fp->name && fp->name[0])
00297         {
00298             ListCell   *px;
00299 
00300             /*
00301              * As of Postgres 9.0 we disallow using the same name for two
00302              * input or two output function parameters.  Depending on the
00303              * function's language, conflicting input and output names might
00304              * be bad too, but we leave it to the PL to complain if so.
00305              */
00306             foreach(px, parameters)
00307             {
00308                 FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
00309 
00310                 if (prevfp == fp)
00311                     break;
00312                 /* pure in doesn't conflict with pure out */
00313                 if ((fp->mode == FUNC_PARAM_IN ||
00314                      fp->mode == FUNC_PARAM_VARIADIC) &&
00315                     (prevfp->mode == FUNC_PARAM_OUT ||
00316                      prevfp->mode == FUNC_PARAM_TABLE))
00317                     continue;
00318                 if ((prevfp->mode == FUNC_PARAM_IN ||
00319                      prevfp->mode == FUNC_PARAM_VARIADIC) &&
00320                     (fp->mode == FUNC_PARAM_OUT ||
00321                      fp->mode == FUNC_PARAM_TABLE))
00322                     continue;
00323                 if (prevfp->name && prevfp->name[0] &&
00324                     strcmp(prevfp->name, fp->name) == 0)
00325                     ereport(ERROR,
00326                             (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00327                           errmsg("parameter name \"%s\" used more than once",
00328                                  fp->name)));
00329             }
00330 
00331             paramNames[i] = CStringGetTextDatum(fp->name);
00332             have_names = true;
00333         }
00334 
00335         if (fp->defexpr)
00336         {
00337             Node       *def;
00338 
00339             if (!isinput)
00340                 ereport(ERROR,
00341                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00342                    errmsg("only input parameters can have default values")));
00343 
00344             def = transformExpr(pstate, fp->defexpr,
00345                                 EXPR_KIND_FUNCTION_DEFAULT);
00346             def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
00347             assign_expr_collations(pstate, def);
00348 
00349             /*
00350              * Make sure no variables are referred to (this is probably dead
00351              * code now that add_missing_from is history).
00352              */
00353             if (list_length(pstate->p_rtable) != 0 ||
00354                 contain_var_clause(def))
00355                 ereport(ERROR,
00356                         (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
00357                          errmsg("cannot use table references in parameter default value")));
00358 
00359             /*
00360              * transformExpr() should have already rejected subqueries,
00361              * aggregates, and window functions, based on the EXPR_KIND_ for a
00362              * default expression.
00363              *
00364              * It can't return a set either --- but coerce_to_specific_type
00365              * already checked that for us.
00366              *
00367              * Note: the point of these restrictions is to ensure that an
00368              * expression that, on its face, hasn't got subplans, aggregates,
00369              * etc cannot suddenly have them after function default arguments
00370              * are inserted.
00371              */
00372 
00373             *parameterDefaults = lappend(*parameterDefaults, def);
00374             have_defaults = true;
00375         }
00376         else
00377         {
00378             if (isinput && have_defaults)
00379                 ereport(ERROR,
00380                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00381                          errmsg("input parameters after one with a default value must also have defaults")));
00382         }
00383 
00384         i++;
00385     }
00386 
00387     free_parsestate(pstate);
00388 
00389     /* Now construct the proper outputs as needed */
00390     *parameterTypes = buildoidvector(inTypes, inCount);
00391 
00392     if (outCount > 0 || varCount > 0)
00393     {
00394         *allParameterTypes = construct_array(allTypes, parameterCount, OIDOID,
00395                                              sizeof(Oid), true, 'i');
00396         *parameterModes = construct_array(paramModes, parameterCount, CHAROID,
00397                                           1, true, 'c');
00398         if (outCount > 1)
00399             *requiredResultType = RECORDOID;
00400         /* otherwise we set requiredResultType correctly above */
00401     }
00402     else
00403     {
00404         *allParameterTypes = NULL;
00405         *parameterModes = NULL;
00406     }
00407 
00408     if (have_names)
00409     {
00410         for (i = 0; i < parameterCount; i++)
00411         {
00412             if (paramNames[i] == PointerGetDatum(NULL))
00413                 paramNames[i] = CStringGetTextDatum("");
00414         }
00415         *parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
00416                                           -1, false, 'i');
00417     }
00418     else
00419         *parameterNames = NULL;
00420 }
00421 
00422 
00423 /*
00424  * Recognize one of the options that can be passed to both CREATE
00425  * FUNCTION and ALTER FUNCTION and return it via one of the out
00426  * parameters. Returns true if the passed option was recognized. If
00427  * the out parameter we were going to assign to points to non-NULL,
00428  * raise a duplicate-clause error.  (We don't try to detect duplicate
00429  * SET parameters though --- if you're redundant, the last one wins.)
00430  */
00431 static bool
00432 compute_common_attribute(DefElem *defel,
00433                          DefElem **volatility_item,
00434                          DefElem **strict_item,
00435                          DefElem **security_item,
00436                          DefElem **leakproof_item,
00437                          List **set_items,
00438                          DefElem **cost_item,
00439                          DefElem **rows_item)
00440 {
00441     if (strcmp(defel->defname, "volatility") == 0)
00442     {
00443         if (*volatility_item)
00444             goto duplicate_error;
00445 
00446         *volatility_item = defel;
00447     }
00448     else if (strcmp(defel->defname, "strict") == 0)
00449     {
00450         if (*strict_item)
00451             goto duplicate_error;
00452 
00453         *strict_item = defel;
00454     }
00455     else if (strcmp(defel->defname, "security") == 0)
00456     {
00457         if (*security_item)
00458             goto duplicate_error;
00459 
00460         *security_item = defel;
00461     }
00462     else if (strcmp(defel->defname, "leakproof") == 0)
00463     {
00464         if (*leakproof_item)
00465             goto duplicate_error;
00466 
00467         *leakproof_item = defel;
00468     }
00469     else if (strcmp(defel->defname, "set") == 0)
00470     {
00471         *set_items = lappend(*set_items, defel->arg);
00472     }
00473     else if (strcmp(defel->defname, "cost") == 0)
00474     {
00475         if (*cost_item)
00476             goto duplicate_error;
00477 
00478         *cost_item = defel;
00479     }
00480     else if (strcmp(defel->defname, "rows") == 0)
00481     {
00482         if (*rows_item)
00483             goto duplicate_error;
00484 
00485         *rows_item = defel;
00486     }
00487     else
00488         return false;
00489 
00490     /* Recognized an option */
00491     return true;
00492 
00493 duplicate_error:
00494     ereport(ERROR,
00495             (errcode(ERRCODE_SYNTAX_ERROR),
00496              errmsg("conflicting or redundant options")));
00497     return false;               /* keep compiler quiet */
00498 }
00499 
00500 static char
00501 interpret_func_volatility(DefElem *defel)
00502 {
00503     char       *str = strVal(defel->arg);
00504 
00505     if (strcmp(str, "immutable") == 0)
00506         return PROVOLATILE_IMMUTABLE;
00507     else if (strcmp(str, "stable") == 0)
00508         return PROVOLATILE_STABLE;
00509     else if (strcmp(str, "volatile") == 0)
00510         return PROVOLATILE_VOLATILE;
00511     else
00512     {
00513         elog(ERROR, "invalid volatility \"%s\"", str);
00514         return 0;               /* keep compiler quiet */
00515     }
00516 }
00517 
00518 /*
00519  * Update a proconfig value according to a list of VariableSetStmt items.
00520  *
00521  * The input and result may be NULL to signify a null entry.
00522  */
00523 static ArrayType *
00524 update_proconfig_value(ArrayType *a, List *set_items)
00525 {
00526     ListCell   *l;
00527 
00528     foreach(l, set_items)
00529     {
00530         VariableSetStmt *sstmt = (VariableSetStmt *) lfirst(l);
00531 
00532         Assert(IsA(sstmt, VariableSetStmt));
00533         if (sstmt->kind == VAR_RESET_ALL)
00534             a = NULL;
00535         else
00536         {
00537             char       *valuestr = ExtractSetVariableArgs(sstmt);
00538 
00539             if (valuestr)
00540                 a = GUCArrayAdd(a, sstmt->name, valuestr);
00541             else    /* RESET */
00542                 a = GUCArrayDelete(a, sstmt->name);
00543         }
00544     }
00545 
00546     return a;
00547 }
00548 
00549 
00550 /*
00551  * Dissect the list of options assembled in gram.y into function
00552  * attributes.
00553  */
00554 static void
00555 compute_attributes_sql_style(List *options,
00556                              List **as,
00557                              char **language,
00558                              bool *windowfunc_p,
00559                              char *volatility_p,
00560                              bool *strict_p,
00561                              bool *security_definer,
00562                              bool *leakproof_p,
00563                              ArrayType **proconfig,
00564                              float4 *procost,
00565                              float4 *prorows)
00566 {
00567     ListCell   *option;
00568     DefElem    *as_item = NULL;
00569     DefElem    *language_item = NULL;
00570     DefElem    *windowfunc_item = NULL;
00571     DefElem    *volatility_item = NULL;
00572     DefElem    *strict_item = NULL;
00573     DefElem    *security_item = NULL;
00574     DefElem    *leakproof_item = NULL;
00575     List       *set_items = NIL;
00576     DefElem    *cost_item = NULL;
00577     DefElem    *rows_item = NULL;
00578 
00579     foreach(option, options)
00580     {
00581         DefElem    *defel = (DefElem *) lfirst(option);
00582 
00583         if (strcmp(defel->defname, "as") == 0)
00584         {
00585             if (as_item)
00586                 ereport(ERROR,
00587                         (errcode(ERRCODE_SYNTAX_ERROR),
00588                          errmsg("conflicting or redundant options")));
00589             as_item = defel;
00590         }
00591         else if (strcmp(defel->defname, "language") == 0)
00592         {
00593             if (language_item)
00594                 ereport(ERROR,
00595                         (errcode(ERRCODE_SYNTAX_ERROR),
00596                          errmsg("conflicting or redundant options")));
00597             language_item = defel;
00598         }
00599         else if (strcmp(defel->defname, "window") == 0)
00600         {
00601             if (windowfunc_item)
00602                 ereport(ERROR,
00603                         (errcode(ERRCODE_SYNTAX_ERROR),
00604                          errmsg("conflicting or redundant options")));
00605             windowfunc_item = defel;
00606         }
00607         else if (compute_common_attribute(defel,
00608                                           &volatility_item,
00609                                           &strict_item,
00610                                           &security_item,
00611                                           &leakproof_item,
00612                                           &set_items,
00613                                           &cost_item,
00614                                           &rows_item))
00615         {
00616             /* recognized common option */
00617             continue;
00618         }
00619         else
00620             elog(ERROR, "option \"%s\" not recognized",
00621                  defel->defname);
00622     }
00623 
00624     /* process required items */
00625     if (as_item)
00626         *as = (List *) as_item->arg;
00627     else
00628     {
00629         ereport(ERROR,
00630                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00631                  errmsg("no function body specified")));
00632         *as = NIL;              /* keep compiler quiet */
00633     }
00634 
00635     if (language_item)
00636         *language = strVal(language_item->arg);
00637     else
00638     {
00639         ereport(ERROR,
00640                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00641                  errmsg("no language specified")));
00642         *language = NULL;       /* keep compiler quiet */
00643     }
00644 
00645     /* process optional items */
00646     if (windowfunc_item)
00647         *windowfunc_p = intVal(windowfunc_item->arg);
00648     if (volatility_item)
00649         *volatility_p = interpret_func_volatility(volatility_item);
00650     if (strict_item)
00651         *strict_p = intVal(strict_item->arg);
00652     if (security_item)
00653         *security_definer = intVal(security_item->arg);
00654     if (leakproof_item)
00655         *leakproof_p = intVal(leakproof_item->arg);
00656     if (set_items)
00657         *proconfig = update_proconfig_value(NULL, set_items);
00658     if (cost_item)
00659     {
00660         *procost = defGetNumeric(cost_item);
00661         if (*procost <= 0)
00662             ereport(ERROR,
00663                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00664                      errmsg("COST must be positive")));
00665     }
00666     if (rows_item)
00667     {
00668         *prorows = defGetNumeric(rows_item);
00669         if (*prorows <= 0)
00670             ereport(ERROR,
00671                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00672                      errmsg("ROWS must be positive")));
00673     }
00674 }
00675 
00676 
00677 /*-------------
00678  *   Interpret the parameters *parameters and return their contents via
00679  *   *isStrict_p and *volatility_p.
00680  *
00681  *  These parameters supply optional information about a function.
00682  *  All have defaults if not specified. Parameters:
00683  *
00684  *   * isStrict means the function should not be called when any NULL
00685  *     inputs are present; instead a NULL result value should be assumed.
00686  *
00687  *   * volatility tells the optimizer whether the function's result can
00688  *     be assumed to be repeatable over multiple evaluations.
00689  *------------
00690  */
00691 static void
00692 compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatility_p)
00693 {
00694     ListCell   *pl;
00695 
00696     foreach(pl, parameters)
00697     {
00698         DefElem    *param = (DefElem *) lfirst(pl);
00699 
00700         if (pg_strcasecmp(param->defname, "isstrict") == 0)
00701             *isStrict_p = defGetBoolean(param);
00702         else if (pg_strcasecmp(param->defname, "iscachable") == 0)
00703         {
00704             /* obsolete spelling of isImmutable */
00705             if (defGetBoolean(param))
00706                 *volatility_p = PROVOLATILE_IMMUTABLE;
00707         }
00708         else
00709             ereport(WARNING,
00710                     (errcode(ERRCODE_SYNTAX_ERROR),
00711                      errmsg("unrecognized function attribute \"%s\" ignored",
00712                             param->defname)));
00713     }
00714 }
00715 
00716 
00717 /*
00718  * For a dynamically linked C language object, the form of the clause is
00719  *
00720  *     AS <object file name> [, <link symbol name> ]
00721  *
00722  * In all other cases
00723  *
00724  *     AS <object reference, or sql code>
00725  */
00726 static void
00727 interpret_AS_clause(Oid languageOid, const char *languageName,
00728                     char *funcname, List *as,
00729                     char **prosrc_str_p, char **probin_str_p)
00730 {
00731     Assert(as != NIL);
00732 
00733     if (languageOid == ClanguageId)
00734     {
00735         /*
00736          * For "C" language, store the file name in probin and, when given,
00737          * the link symbol name in prosrc.  If link symbol is omitted,
00738          * substitute procedure name.  We also allow link symbol to be
00739          * specified as "-", since that was the habit in PG versions before
00740          * 8.4, and there might be dump files out there that don't translate
00741          * that back to "omitted".
00742          */
00743         *probin_str_p = strVal(linitial(as));
00744         if (list_length(as) == 1)
00745             *prosrc_str_p = funcname;
00746         else
00747         {
00748             *prosrc_str_p = strVal(lsecond(as));
00749             if (strcmp(*prosrc_str_p, "-") == 0)
00750                 *prosrc_str_p = funcname;
00751         }
00752     }
00753     else
00754     {
00755         /* Everything else wants the given string in prosrc. */
00756         *prosrc_str_p = strVal(linitial(as));
00757         *probin_str_p = NULL;
00758 
00759         if (list_length(as) != 1)
00760             ereport(ERROR,
00761                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00762                      errmsg("only one AS item needed for language \"%s\"",
00763                             languageName)));
00764 
00765         if (languageOid == INTERNALlanguageId)
00766         {
00767             /*
00768              * In PostgreSQL versions before 6.5, the SQL name of the created
00769              * function could not be different from the internal name, and
00770              * "prosrc" wasn't used.  So there is code out there that does
00771              * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some
00772              * modicum of backwards compatibility, accept an empty "prosrc"
00773              * value as meaning the supplied SQL function name.
00774              */
00775             if (strlen(*prosrc_str_p) == 0)
00776                 *prosrc_str_p = funcname;
00777         }
00778     }
00779 }
00780 
00781 
00782 
00783 /*
00784  * CreateFunction
00785  *   Execute a CREATE FUNCTION utility statement.
00786  */
00787 Oid
00788 CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
00789 {
00790     char       *probin_str;
00791     char       *prosrc_str;
00792     Oid         prorettype;
00793     bool        returnsSet;
00794     char       *language;
00795     Oid         languageOid;
00796     Oid         languageValidator;
00797     char       *funcname;
00798     Oid         namespaceId;
00799     AclResult   aclresult;
00800     oidvector  *parameterTypes;
00801     ArrayType  *allParameterTypes;
00802     ArrayType  *parameterModes;
00803     ArrayType  *parameterNames;
00804     List       *parameterDefaults;
00805     Oid         requiredResultType;
00806     bool        isWindowFunc,
00807                 isStrict,
00808                 security,
00809                 isLeakProof;
00810     char        volatility;
00811     ArrayType  *proconfig;
00812     float4      procost;
00813     float4      prorows;
00814     HeapTuple   languageTuple;
00815     Form_pg_language languageStruct;
00816     List       *as_clause;
00817 
00818     /* Convert list of names to a name and namespace */
00819     namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
00820                                                     &funcname);
00821 
00822     /* Check we have creation rights in target namespace */
00823     aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
00824     if (aclresult != ACLCHECK_OK)
00825         aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00826                        get_namespace_name(namespaceId));
00827 
00828     /* default attributes */
00829     isWindowFunc = false;
00830     isStrict = false;
00831     security = false;
00832     isLeakProof = false;
00833     volatility = PROVOLATILE_VOLATILE;
00834     proconfig = NULL;
00835     procost = -1;               /* indicates not set */
00836     prorows = -1;               /* indicates not set */
00837 
00838     /* override attributes from explicit list */
00839     compute_attributes_sql_style(stmt->options,
00840                                  &as_clause, &language,
00841                                  &isWindowFunc, &volatility,
00842                                  &isStrict, &security, &isLeakProof,
00843                                  &proconfig, &procost, &prorows);
00844 
00845     /* Look up the language and validate permissions */
00846     languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
00847     if (!HeapTupleIsValid(languageTuple))
00848         ereport(ERROR,
00849                 (errcode(ERRCODE_UNDEFINED_OBJECT),
00850                  errmsg("language \"%s\" does not exist", language),
00851                  (PLTemplateExists(language) ?
00852                   errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
00853 
00854     languageOid = HeapTupleGetOid(languageTuple);
00855     languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
00856 
00857     if (languageStruct->lanpltrusted)
00858     {
00859         /* if trusted language, need USAGE privilege */
00860         AclResult   aclresult;
00861 
00862         aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
00863         if (aclresult != ACLCHECK_OK)
00864             aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
00865                            NameStr(languageStruct->lanname));
00866     }
00867     else
00868     {
00869         /* if untrusted language, must be superuser */
00870         if (!superuser())
00871             aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
00872                            NameStr(languageStruct->lanname));
00873     }
00874 
00875     languageValidator = languageStruct->lanvalidator;
00876 
00877     ReleaseSysCache(languageTuple);
00878 
00879     /*
00880      * Only superuser is allowed to create leakproof functions because it
00881      * possibly allows unprivileged users to reference invisible tuples to be
00882      * filtered out using views for row-level security.
00883      */
00884     if (isLeakProof && !superuser())
00885         ereport(ERROR,
00886                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00887                  errmsg("only superuser can define a leakproof function")));
00888 
00889     /*
00890      * Convert remaining parameters of CREATE to form wanted by
00891      * ProcedureCreate.
00892      */
00893     examine_parameter_list(stmt->parameters, languageOid, queryString,
00894                            &parameterTypes,
00895                            &allParameterTypes,
00896                            &parameterModes,
00897                            &parameterNames,
00898                            &parameterDefaults,
00899                            &requiredResultType);
00900 
00901     if (stmt->returnType)
00902     {
00903         /* explicit RETURNS clause */
00904         compute_return_type(stmt->returnType, languageOid,
00905                             &prorettype, &returnsSet);
00906         if (OidIsValid(requiredResultType) && prorettype != requiredResultType)
00907             ereport(ERROR,
00908                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00909                      errmsg("function result type must be %s because of OUT parameters",
00910                             format_type_be(requiredResultType))));
00911     }
00912     else if (OidIsValid(requiredResultType))
00913     {
00914         /* default RETURNS clause from OUT parameters */
00915         prorettype = requiredResultType;
00916         returnsSet = false;
00917     }
00918     else
00919     {
00920         ereport(ERROR,
00921                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00922                  errmsg("function result type must be specified")));
00923         /* Alternative possibility: default to RETURNS VOID */
00924         prorettype = VOIDOID;
00925         returnsSet = false;
00926     }
00927 
00928     compute_attributes_with_style(stmt->withClause, &isStrict, &volatility);
00929 
00930     interpret_AS_clause(languageOid, language, funcname, as_clause,
00931                         &prosrc_str, &probin_str);
00932 
00933     /*
00934      * Set default values for COST and ROWS depending on other parameters;
00935      * reject ROWS if it's not returnsSet.  NB: pg_dump knows these default
00936      * values, keep it in sync if you change them.
00937      */
00938     if (procost < 0)
00939     {
00940         /* SQL and PL-language functions are assumed more expensive */
00941         if (languageOid == INTERNALlanguageId ||
00942             languageOid == ClanguageId)
00943             procost = 1;
00944         else
00945             procost = 100;
00946     }
00947     if (prorows < 0)
00948     {
00949         if (returnsSet)
00950             prorows = 1000;
00951         else
00952             prorows = 0;        /* dummy value if not returnsSet */
00953     }
00954     else if (!returnsSet)
00955         ereport(ERROR,
00956                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00957                  errmsg("ROWS is not applicable when function does not return a set")));
00958 
00959     /*
00960      * And now that we have all the parameters, and know we're permitted to do
00961      * so, go ahead and create the function.
00962      */
00963     return ProcedureCreate(funcname,
00964                            namespaceId,
00965                            stmt->replace,
00966                            returnsSet,
00967                            prorettype,
00968                            GetUserId(),
00969                            languageOid,
00970                            languageValidator,
00971                            prosrc_str, /* converted to text later */
00972                            probin_str, /* converted to text later */
00973                            false,       /* not an aggregate */
00974                            isWindowFunc,
00975                            security,
00976                            isLeakProof,
00977                            isStrict,
00978                            volatility,
00979                            parameterTypes,
00980                            PointerGetDatum(allParameterTypes),
00981                            PointerGetDatum(parameterModes),
00982                            PointerGetDatum(parameterNames),
00983                            parameterDefaults,
00984                            PointerGetDatum(proconfig),
00985                            procost,
00986                            prorows);
00987 }
00988 
00989 
00990 /*
00991  * Guts of function deletion.
00992  *
00993  * Note: this is also used for aggregate deletion, since the OIDs of
00994  * both functions and aggregates point to pg_proc.
00995  */
00996 void
00997 RemoveFunctionById(Oid funcOid)
00998 {
00999     Relation    relation;
01000     HeapTuple   tup;
01001     bool        isagg;
01002 
01003     /*
01004      * Delete the pg_proc tuple.
01005      */
01006     relation = heap_open(ProcedureRelationId, RowExclusiveLock);
01007 
01008     tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
01009     if (!HeapTupleIsValid(tup)) /* should not happen */
01010         elog(ERROR, "cache lookup failed for function %u", funcOid);
01011 
01012     isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
01013 
01014     simple_heap_delete(relation, &tup->t_self);
01015 
01016     ReleaseSysCache(tup);
01017 
01018     heap_close(relation, RowExclusiveLock);
01019 
01020     /*
01021      * If there's a pg_aggregate tuple, delete that too.
01022      */
01023     if (isagg)
01024     {
01025         relation = heap_open(AggregateRelationId, RowExclusiveLock);
01026 
01027         tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
01028         if (!HeapTupleIsValid(tup))     /* should not happen */
01029             elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
01030 
01031         simple_heap_delete(relation, &tup->t_self);
01032 
01033         ReleaseSysCache(tup);
01034 
01035         heap_close(relation, RowExclusiveLock);
01036     }
01037 }
01038 
01039 /*
01040  * Implements the ALTER FUNCTION utility command (except for the
01041  * RENAME and OWNER clauses, which are handled as part of the generic
01042  * ALTER framework).
01043  */
01044 Oid
01045 AlterFunction(AlterFunctionStmt *stmt)
01046 {
01047     HeapTuple   tup;
01048     Oid         funcOid;
01049     Form_pg_proc procForm;
01050     Relation    rel;
01051     ListCell   *l;
01052     DefElem    *volatility_item = NULL;
01053     DefElem    *strict_item = NULL;
01054     DefElem    *security_def_item = NULL;
01055     DefElem    *leakproof_item = NULL;
01056     List       *set_items = NIL;
01057     DefElem    *cost_item = NULL;
01058     DefElem    *rows_item = NULL;
01059 
01060     rel = heap_open(ProcedureRelationId, RowExclusiveLock);
01061 
01062     funcOid = LookupFuncNameTypeNames(stmt->func->funcname,
01063                                       stmt->func->funcargs,
01064                                       false);
01065 
01066     tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
01067     if (!HeapTupleIsValid(tup)) /* should not happen */
01068         elog(ERROR, "cache lookup failed for function %u", funcOid);
01069 
01070     procForm = (Form_pg_proc) GETSTRUCT(tup);
01071 
01072     /* Permission check: must own function */
01073     if (!pg_proc_ownercheck(funcOid, GetUserId()))
01074         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
01075                        NameListToString(stmt->func->funcname));
01076 
01077     if (procForm->proisagg)
01078         ereport(ERROR,
01079                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01080                  errmsg("\"%s\" is an aggregate function",
01081                         NameListToString(stmt->func->funcname))));
01082 
01083     /* Examine requested actions. */
01084     foreach(l, stmt->actions)
01085     {
01086         DefElem    *defel = (DefElem *) lfirst(l);
01087 
01088         if (compute_common_attribute(defel,
01089                                      &volatility_item,
01090                                      &strict_item,
01091                                      &security_def_item,
01092                                      &leakproof_item,
01093                                      &set_items,
01094                                      &cost_item,
01095                                      &rows_item) == false)
01096             elog(ERROR, "option \"%s\" not recognized", defel->defname);
01097     }
01098 
01099     if (volatility_item)
01100         procForm->provolatile = interpret_func_volatility(volatility_item);
01101     if (strict_item)
01102         procForm->proisstrict = intVal(strict_item->arg);
01103     if (security_def_item)
01104         procForm->prosecdef = intVal(security_def_item->arg);
01105     if (leakproof_item)
01106     {
01107         if (intVal(leakproof_item->arg) && !superuser())
01108             ereport(ERROR,
01109                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01110                   errmsg("only superuser can define a leakproof function")));
01111         procForm->proleakproof = intVal(leakproof_item->arg);
01112     }
01113     if (cost_item)
01114     {
01115         procForm->procost = defGetNumeric(cost_item);
01116         if (procForm->procost <= 0)
01117             ereport(ERROR,
01118                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01119                      errmsg("COST must be positive")));
01120     }
01121     if (rows_item)
01122     {
01123         procForm->prorows = defGetNumeric(rows_item);
01124         if (procForm->prorows <= 0)
01125             ereport(ERROR,
01126                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01127                      errmsg("ROWS must be positive")));
01128         if (!procForm->proretset)
01129             ereport(ERROR,
01130                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01131                      errmsg("ROWS is not applicable when function does not return a set")));
01132     }
01133     if (set_items)
01134     {
01135         Datum       datum;
01136         bool        isnull;
01137         ArrayType  *a;
01138         Datum       repl_val[Natts_pg_proc];
01139         bool        repl_null[Natts_pg_proc];
01140         bool        repl_repl[Natts_pg_proc];
01141 
01142         /* extract existing proconfig setting */
01143         datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
01144         a = isnull ? NULL : DatumGetArrayTypeP(datum);
01145 
01146         /* update according to each SET or RESET item, left to right */
01147         a = update_proconfig_value(a, set_items);
01148 
01149         /* update the tuple */
01150         memset(repl_repl, false, sizeof(repl_repl));
01151         repl_repl[Anum_pg_proc_proconfig - 1] = true;
01152 
01153         if (a == NULL)
01154         {
01155             repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
01156             repl_null[Anum_pg_proc_proconfig - 1] = true;
01157         }
01158         else
01159         {
01160             repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a);
01161             repl_null[Anum_pg_proc_proconfig - 1] = false;
01162         }
01163 
01164         tup = heap_modify_tuple(tup, RelationGetDescr(rel),
01165                                 repl_val, repl_null, repl_repl);
01166     }
01167 
01168     /* Do the update */
01169     simple_heap_update(rel, &tup->t_self, tup);
01170     CatalogUpdateIndexes(rel, tup);
01171 
01172     InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
01173 
01174     heap_close(rel, NoLock);
01175     heap_freetuple(tup);
01176 
01177     return funcOid;
01178 }
01179 
01180 /*
01181  * SetFunctionReturnType - change declared return type of a function
01182  *
01183  * This is presently only used for adjusting legacy functions that return
01184  * OPAQUE to return whatever we find their correct definition should be.
01185  * The caller should emit a suitable warning explaining what we did.
01186  */
01187 void
01188 SetFunctionReturnType(Oid funcOid, Oid newRetType)
01189 {
01190     Relation    pg_proc_rel;
01191     HeapTuple   tup;
01192     Form_pg_proc procForm;
01193 
01194     pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
01195 
01196     tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
01197     if (!HeapTupleIsValid(tup)) /* should not happen */
01198         elog(ERROR, "cache lookup failed for function %u", funcOid);
01199     procForm = (Form_pg_proc) GETSTRUCT(tup);
01200 
01201     if (procForm->prorettype != OPAQUEOID)      /* caller messed up */
01202         elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
01203 
01204     /* okay to overwrite copied tuple */
01205     procForm->prorettype = newRetType;
01206 
01207     /* update the catalog and its indexes */
01208     simple_heap_update(pg_proc_rel, &tup->t_self, tup);
01209 
01210     CatalogUpdateIndexes(pg_proc_rel, tup);
01211 
01212     heap_close(pg_proc_rel, RowExclusiveLock);
01213 }
01214 
01215 
01216 /*
01217  * SetFunctionArgType - change declared argument type of a function
01218  *
01219  * As above, but change an argument's type.
01220  */
01221 void
01222 SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
01223 {
01224     Relation    pg_proc_rel;
01225     HeapTuple   tup;
01226     Form_pg_proc procForm;
01227 
01228     pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
01229 
01230     tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
01231     if (!HeapTupleIsValid(tup)) /* should not happen */
01232         elog(ERROR, "cache lookup failed for function %u", funcOid);
01233     procForm = (Form_pg_proc) GETSTRUCT(tup);
01234 
01235     if (argIndex < 0 || argIndex >= procForm->pronargs ||
01236         procForm->proargtypes.values[argIndex] != OPAQUEOID)
01237         elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
01238 
01239     /* okay to overwrite copied tuple */
01240     procForm->proargtypes.values[argIndex] = newArgType;
01241 
01242     /* update the catalog and its indexes */
01243     simple_heap_update(pg_proc_rel, &tup->t_self, tup);
01244 
01245     CatalogUpdateIndexes(pg_proc_rel, tup);
01246 
01247     heap_close(pg_proc_rel, RowExclusiveLock);
01248 }
01249 
01250 
01251 
01252 /*
01253  * CREATE CAST
01254  */
01255 Oid
01256 CreateCast(CreateCastStmt *stmt)
01257 {
01258     Oid         sourcetypeid;
01259     Oid         targettypeid;
01260     char        sourcetyptype;
01261     char        targettyptype;
01262     Oid         funcid;
01263     Oid         castid;
01264     int         nargs;
01265     char        castcontext;
01266     char        castmethod;
01267     Relation    relation;
01268     HeapTuple   tuple;
01269     Datum       values[Natts_pg_cast];
01270     bool        nulls[Natts_pg_cast];
01271     ObjectAddress myself,
01272                 referenced;
01273     AclResult   aclresult;
01274 
01275     sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
01276     targettypeid = typenameTypeId(NULL, stmt->targettype);
01277     sourcetyptype = get_typtype(sourcetypeid);
01278     targettyptype = get_typtype(targettypeid);
01279 
01280     /* No pseudo-types allowed */
01281     if (sourcetyptype == TYPTYPE_PSEUDO)
01282         ereport(ERROR,
01283                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01284                  errmsg("source data type %s is a pseudo-type",
01285                         TypeNameToString(stmt->sourcetype))));
01286 
01287     if (targettyptype == TYPTYPE_PSEUDO)
01288         ereport(ERROR,
01289                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01290                  errmsg("target data type %s is a pseudo-type",
01291                         TypeNameToString(stmt->targettype))));
01292 
01293     /* Permission check */
01294     if (!pg_type_ownercheck(sourcetypeid, GetUserId())
01295         && !pg_type_ownercheck(targettypeid, GetUserId()))
01296         ereport(ERROR,
01297                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01298                  errmsg("must be owner of type %s or type %s",
01299                         format_type_be(sourcetypeid),
01300                         format_type_be(targettypeid))));
01301 
01302     aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
01303     if (aclresult != ACLCHECK_OK)
01304         aclcheck_error_type(aclresult, sourcetypeid);
01305 
01306     aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
01307     if (aclresult != ACLCHECK_OK)
01308         aclcheck_error_type(aclresult, targettypeid);
01309 
01310     /* Domains are allowed for historical reasons, but we warn */
01311     if (sourcetyptype == TYPTYPE_DOMAIN)
01312         ereport(WARNING,
01313                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01314                  errmsg("cast will be ignored because the source data type is a domain")));
01315 
01316     else if (targettyptype == TYPTYPE_DOMAIN)
01317         ereport(WARNING,
01318                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01319                  errmsg("cast will be ignored because the target data type is a domain")));
01320 
01321     /* Detemine the cast method */
01322     if (stmt->func != NULL)
01323         castmethod = COERCION_METHOD_FUNCTION;
01324     else if (stmt->inout)
01325         castmethod = COERCION_METHOD_INOUT;
01326     else
01327         castmethod = COERCION_METHOD_BINARY;
01328 
01329     if (castmethod == COERCION_METHOD_FUNCTION)
01330     {
01331         Form_pg_proc procstruct;
01332 
01333         funcid = LookupFuncNameTypeNames(stmt->func->funcname,
01334                                          stmt->func->funcargs,
01335                                          false);
01336 
01337         tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01338         if (!HeapTupleIsValid(tuple))
01339             elog(ERROR, "cache lookup failed for function %u", funcid);
01340 
01341         procstruct = (Form_pg_proc) GETSTRUCT(tuple);
01342         nargs = procstruct->pronargs;
01343         if (nargs < 1 || nargs > 3)
01344             ereport(ERROR,
01345                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01346                   errmsg("cast function must take one to three arguments")));
01347         if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
01348             ereport(ERROR,
01349                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01350                      errmsg("argument of cast function must match or be binary-coercible from source data type")));
01351         if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
01352             ereport(ERROR,
01353                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01354             errmsg("second argument of cast function must be type integer")));
01355         if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)
01356             ereport(ERROR,
01357                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01358             errmsg("third argument of cast function must be type boolean")));
01359         if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
01360             ereport(ERROR,
01361                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01362                      errmsg("return data type of cast function must match or be binary-coercible to target data type")));
01363 
01364         /*
01365          * Restricting the volatility of a cast function may or may not be a
01366          * good idea in the abstract, but it definitely breaks many old
01367          * user-defined types.  Disable this check --- tgl 2/1/03
01368          */
01369 #ifdef NOT_USED
01370         if (procstruct->provolatile == PROVOLATILE_VOLATILE)
01371             ereport(ERROR,
01372                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01373                      errmsg("cast function must not be volatile")));
01374 #endif
01375         if (procstruct->proisagg)
01376             ereport(ERROR,
01377                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01378                  errmsg("cast function must not be an aggregate function")));
01379         if (procstruct->proiswindow)
01380             ereport(ERROR,
01381                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01382                      errmsg("cast function must not be a window function")));
01383         if (procstruct->proretset)
01384             ereport(ERROR,
01385                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01386                      errmsg("cast function must not return a set")));
01387 
01388         ReleaseSysCache(tuple);
01389     }
01390     else
01391     {
01392         funcid = InvalidOid;
01393         nargs = 0;
01394     }
01395 
01396     if (castmethod == COERCION_METHOD_BINARY)
01397     {
01398         int16       typ1len;
01399         int16       typ2len;
01400         bool        typ1byval;
01401         bool        typ2byval;
01402         char        typ1align;
01403         char        typ2align;
01404 
01405         /*
01406          * Must be superuser to create binary-compatible casts, since
01407          * erroneous casts can easily crash the backend.
01408          */
01409         if (!superuser())
01410             ereport(ERROR,
01411                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01412              errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
01413 
01414         /*
01415          * Also, insist that the types match as to size, alignment, and
01416          * pass-by-value attributes; this provides at least a crude check that
01417          * they have similar representations.  A pair of types that fail this
01418          * test should certainly not be equated.
01419          */
01420         get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);
01421         get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);
01422         if (typ1len != typ2len ||
01423             typ1byval != typ2byval ||
01424             typ1align != typ2align)
01425             ereport(ERROR,
01426                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01427                      errmsg("source and target data types are not physically compatible")));
01428 
01429         /*
01430          * We know that composite, enum and array types are never binary-
01431          * compatible with each other.  They all have OIDs embedded in them.
01432          *
01433          * Theoretically you could build a user-defined base type that is
01434          * binary-compatible with a composite, enum, or array type.  But we
01435          * disallow that too, as in practice such a cast is surely a mistake.
01436          * You can always work around that by writing a cast function.
01437          */
01438         if (sourcetyptype == TYPTYPE_COMPOSITE ||
01439             targettyptype == TYPTYPE_COMPOSITE)
01440             ereport(ERROR,
01441                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01442                   errmsg("composite data types are not binary-compatible")));
01443 
01444         if (sourcetyptype == TYPTYPE_ENUM ||
01445             targettyptype == TYPTYPE_ENUM)
01446             ereport(ERROR,
01447                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01448                      errmsg("enum data types are not binary-compatible")));
01449 
01450         if (OidIsValid(get_element_type(sourcetypeid)) ||
01451             OidIsValid(get_element_type(targettypeid)))
01452             ereport(ERROR,
01453                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01454                      errmsg("array data types are not binary-compatible")));
01455 
01456         /*
01457          * We also disallow creating binary-compatibility casts involving
01458          * domains.  Casting from a domain to its base type is already
01459          * allowed, and casting the other way ought to go through domain
01460          * coercion to permit constraint checking.  Again, if you're intent on
01461          * having your own semantics for that, create a no-op cast function.
01462          *
01463          * NOTE: if we were to relax this, the above checks for composites
01464          * etc. would have to be modified to look through domains to their
01465          * base types.
01466          */
01467         if (sourcetyptype == TYPTYPE_DOMAIN ||
01468             targettyptype == TYPTYPE_DOMAIN)
01469             ereport(ERROR,
01470                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01471                      errmsg("domain data types must not be marked binary-compatible")));
01472     }
01473 
01474     /*
01475      * Allow source and target types to be same only for length coercion
01476      * functions.  We assume a multi-arg function does length coercion.
01477      */
01478     if (sourcetypeid == targettypeid && nargs < 2)
01479         ereport(ERROR,
01480                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
01481               errmsg("source data type and target data type are the same")));
01482 
01483     /* convert CoercionContext enum to char value for castcontext */
01484     switch (stmt->context)
01485     {
01486         case COERCION_IMPLICIT:
01487             castcontext = COERCION_CODE_IMPLICIT;
01488             break;
01489         case COERCION_ASSIGNMENT:
01490             castcontext = COERCION_CODE_ASSIGNMENT;
01491             break;
01492         case COERCION_EXPLICIT:
01493             castcontext = COERCION_CODE_EXPLICIT;
01494             break;
01495         default:
01496             elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
01497             castcontext = 0;    /* keep compiler quiet */
01498             break;
01499     }
01500 
01501     relation = heap_open(CastRelationId, RowExclusiveLock);
01502 
01503     /*
01504      * Check for duplicate.  This is just to give a friendly error message,
01505      * the unique index would catch it anyway (so no need to sweat about race
01506      * conditions).
01507      */
01508     tuple = SearchSysCache2(CASTSOURCETARGET,
01509                             ObjectIdGetDatum(sourcetypeid),
01510                             ObjectIdGetDatum(targettypeid));
01511     if (HeapTupleIsValid(tuple))
01512         ereport(ERROR,
01513                 (errcode(ERRCODE_DUPLICATE_OBJECT),
01514                  errmsg("cast from type %s to type %s already exists",
01515                         format_type_be(sourcetypeid),
01516                         format_type_be(targettypeid))));
01517 
01518     /* ready to go */
01519     values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
01520     values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
01521     values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
01522     values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
01523     values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
01524 
01525     MemSet(nulls, false, sizeof(nulls));
01526 
01527     tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
01528 
01529     castid = simple_heap_insert(relation, tuple);
01530 
01531     CatalogUpdateIndexes(relation, tuple);
01532 
01533     /* make dependency entries */
01534     myself.classId = CastRelationId;
01535     myself.objectId = castid;
01536     myself.objectSubId = 0;
01537 
01538     /* dependency on source type */
01539     referenced.classId = TypeRelationId;
01540     referenced.objectId = sourcetypeid;
01541     referenced.objectSubId = 0;
01542     recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01543 
01544     /* dependency on target type */
01545     referenced.classId = TypeRelationId;
01546     referenced.objectId = targettypeid;
01547     referenced.objectSubId = 0;
01548     recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01549 
01550     /* dependency on function */
01551     if (OidIsValid(funcid))
01552     {
01553         referenced.classId = ProcedureRelationId;
01554         referenced.objectId = funcid;
01555         referenced.objectSubId = 0;
01556         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01557     }
01558 
01559     /* dependency on extension */
01560     recordDependencyOnCurrentExtension(&myself, false);
01561 
01562     /* Post creation hook for new cast */
01563     InvokeObjectPostCreateHook(CastRelationId, castid, 0);
01564 
01565     heap_freetuple(tuple);
01566 
01567     heap_close(relation, RowExclusiveLock);
01568 
01569     return castid;
01570 }
01571 
01572 /*
01573  * get_cast_oid - given two type OIDs, look up a cast OID
01574  *
01575  * If missing_ok is false, throw an error if the cast is not found.  If
01576  * true, just return InvalidOid.
01577  */
01578 Oid
01579 get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
01580 {
01581     Oid         oid;
01582 
01583     oid = GetSysCacheOid2(CASTSOURCETARGET,
01584                           ObjectIdGetDatum(sourcetypeid),
01585                           ObjectIdGetDatum(targettypeid));
01586     if (!OidIsValid(oid) && !missing_ok)
01587         ereport(ERROR,
01588                 (errcode(ERRCODE_UNDEFINED_OBJECT),
01589                  errmsg("cast from type %s to type %s does not exist",
01590                         format_type_be(sourcetypeid),
01591                         format_type_be(targettypeid))));
01592     return oid;
01593 }
01594 
01595 void
01596 DropCastById(Oid castOid)
01597 {
01598     Relation    relation;
01599     ScanKeyData scankey;
01600     SysScanDesc scan;
01601     HeapTuple   tuple;
01602 
01603     relation = heap_open(CastRelationId, RowExclusiveLock);
01604 
01605     ScanKeyInit(&scankey,
01606                 ObjectIdAttributeNumber,
01607                 BTEqualStrategyNumber, F_OIDEQ,
01608                 ObjectIdGetDatum(castOid));
01609     scan = systable_beginscan(relation, CastOidIndexId, true,
01610                               SnapshotNow, 1, &scankey);
01611 
01612     tuple = systable_getnext(scan);
01613     if (!HeapTupleIsValid(tuple))
01614         elog(ERROR, "could not find tuple for cast %u", castOid);
01615     simple_heap_delete(relation, &tuple->t_self);
01616 
01617     systable_endscan(scan);
01618     heap_close(relation, RowExclusiveLock);
01619 }
01620 
01621 /*
01622  * Subroutine for ALTER FUNCTION/AGGREGATE SET SCHEMA/RENAME
01623  *
01624  * Is there a function with the given name and signature already in the given
01625  * namespace?  If so, raise an appropriate error message.
01626  */
01627 void
01628 IsThereFunctionInNamespace(const char *proname, int pronargs,
01629                            oidvector proargtypes, Oid nspOid)
01630 {
01631     /* check for duplicate name (more friendly than unique-index failure) */
01632     if (SearchSysCacheExists3(PROCNAMEARGSNSP,
01633                               CStringGetDatum(proname),
01634                               PointerGetDatum(&proargtypes),
01635                               ObjectIdGetDatum(nspOid)))
01636         ereport(ERROR,
01637                 (errcode(ERRCODE_DUPLICATE_FUNCTION),
01638                  errmsg("function %s already exists in schema \"%s\"",
01639                         funcname_signature_string(proname, pronargs,
01640                                                   NIL, proargtypes.values),
01641                         get_namespace_name(nspOid))));
01642 }
01643 
01644 /*
01645  * ExecuteDoStmt
01646  *      Execute inline procedural-language code
01647  */
01648 void
01649 ExecuteDoStmt(DoStmt *stmt)
01650 {
01651     InlineCodeBlock *codeblock = makeNode(InlineCodeBlock);
01652     ListCell   *arg;
01653     DefElem    *as_item = NULL;
01654     DefElem    *language_item = NULL;
01655     char       *language;
01656     Oid         laninline;
01657     HeapTuple   languageTuple;
01658     Form_pg_language languageStruct;
01659 
01660     /* Process options we got from gram.y */
01661     foreach(arg, stmt->args)
01662     {
01663         DefElem    *defel = (DefElem *) lfirst(arg);
01664 
01665         if (strcmp(defel->defname, "as") == 0)
01666         {
01667             if (as_item)
01668                 ereport(ERROR,
01669                         (errcode(ERRCODE_SYNTAX_ERROR),
01670                          errmsg("conflicting or redundant options")));
01671             as_item = defel;
01672         }
01673         else if (strcmp(defel->defname, "language") == 0)
01674         {
01675             if (language_item)
01676                 ereport(ERROR,
01677                         (errcode(ERRCODE_SYNTAX_ERROR),
01678                          errmsg("conflicting or redundant options")));
01679             language_item = defel;
01680         }
01681         else
01682             elog(ERROR, "option \"%s\" not recognized",
01683                  defel->defname);
01684     }
01685 
01686     if (as_item)
01687         codeblock->source_text = strVal(as_item->arg);
01688     else
01689         ereport(ERROR,
01690                 (errcode(ERRCODE_SYNTAX_ERROR),
01691                  errmsg("no inline code specified")));
01692 
01693     /* if LANGUAGE option wasn't specified, use the default */
01694     if (language_item)
01695         language = strVal(language_item->arg);
01696     else
01697         language = "plpgsql";
01698 
01699     /* Look up the language and validate permissions */
01700     languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
01701     if (!HeapTupleIsValid(languageTuple))
01702         ereport(ERROR,
01703                 (errcode(ERRCODE_UNDEFINED_OBJECT),
01704                  errmsg("language \"%s\" does not exist", language),
01705                  (PLTemplateExists(language) ?
01706                   errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
01707 
01708     codeblock->langOid = HeapTupleGetOid(languageTuple);
01709     languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
01710     codeblock->langIsTrusted = languageStruct->lanpltrusted;
01711 
01712     if (languageStruct->lanpltrusted)
01713     {
01714         /* if trusted language, need USAGE privilege */
01715         AclResult   aclresult;
01716 
01717         aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
01718                                          ACL_USAGE);
01719         if (aclresult != ACLCHECK_OK)
01720             aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
01721                            NameStr(languageStruct->lanname));
01722     }
01723     else
01724     {
01725         /* if untrusted language, must be superuser */
01726         if (!superuser())
01727             aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
01728                            NameStr(languageStruct->lanname));
01729     }
01730 
01731     /* get the handler function's OID */
01732     laninline = languageStruct->laninline;
01733     if (!OidIsValid(laninline))
01734         ereport(ERROR,
01735                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01736              errmsg("language \"%s\" does not support inline code execution",
01737                     NameStr(languageStruct->lanname))));
01738 
01739     ReleaseSysCache(languageTuple);
01740 
01741     /* execute the inline handler */
01742     OidFunctionCall1(laninline, PointerGetDatum(codeblock));
01743 }