00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00071
00072
00073
00074
00075
00076
00077
00078
00079
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
00119
00120
00121
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
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
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
00162
00163
00164
00165
00166
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;
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
00201 pstate = make_parsestate(NULL);
00202 pstate->p_sourcetext = queryString;
00203
00204
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
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;
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
00254 if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
00255 {
00256
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
00266 if (fp->mode != FUNC_PARAM_IN && fp->mode != FUNC_PARAM_VARIADIC)
00267 {
00268 if (outCount == 0)
00269 *requiredResultType = toid;
00270 outCount++;
00271 }
00272
00273 if (fp->mode == FUNC_PARAM_VARIADIC)
00274 {
00275 varCount++;
00276
00277 switch (toid)
00278 {
00279 case ANYARRAYOID:
00280 case ANYOID:
00281
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
00302
00303
00304
00305
00306 foreach(px, parameters)
00307 {
00308 FunctionParameter *prevfp = (FunctionParameter *) lfirst(px);
00309
00310 if (prevfp == fp)
00311 break;
00312
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
00351
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
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
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
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
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
00425
00426
00427
00428
00429
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
00491 return true;
00492
00493 duplicate_error:
00494 ereport(ERROR,
00495 (errcode(ERRCODE_SYNTAX_ERROR),
00496 errmsg("conflicting or redundant options")));
00497 return false;
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;
00515 }
00516 }
00517
00518
00519
00520
00521
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
00542 a = GUCArrayDelete(a, sstmt->name);
00543 }
00544 }
00545
00546 return a;
00547 }
00548
00549
00550
00551
00552
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
00617 continue;
00618 }
00619 else
00620 elog(ERROR, "option \"%s\" not recognized",
00621 defel->defname);
00622 }
00623
00624
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;
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;
00643 }
00644
00645
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
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
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
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
00719
00720
00721
00722
00723
00724
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
00737
00738
00739
00740
00741
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
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
00769
00770
00771
00772
00773
00774
00775 if (strlen(*prosrc_str_p) == 0)
00776 *prosrc_str_p = funcname;
00777 }
00778 }
00779 }
00780
00781
00782
00783
00784
00785
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
00819 namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
00820 &funcname);
00821
00822
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
00829 isWindowFunc = false;
00830 isStrict = false;
00831 security = false;
00832 isLeakProof = false;
00833 volatility = PROVOLATILE_VOLATILE;
00834 proconfig = NULL;
00835 procost = -1;
00836 prorows = -1;
00837
00838
00839 compute_attributes_sql_style(stmt->options,
00840 &as_clause, &language,
00841 &isWindowFunc, &volatility,
00842 &isStrict, &security, &isLeakProof,
00843 &proconfig, &procost, &prorows);
00844
00845
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
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
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
00881
00882
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
00891
00892
00893 examine_parameter_list(stmt->parameters, languageOid, queryString,
00894 ¶meterTypes,
00895 &allParameterTypes,
00896 ¶meterModes,
00897 ¶meterNames,
00898 ¶meterDefaults,
00899 &requiredResultType);
00900
00901 if (stmt->returnType)
00902 {
00903
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
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
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
00935
00936
00937
00938 if (procost < 0)
00939 {
00940
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;
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
00961
00962
00963 return ProcedureCreate(funcname,
00964 namespaceId,
00965 stmt->replace,
00966 returnsSet,
00967 prorettype,
00968 GetUserId(),
00969 languageOid,
00970 languageValidator,
00971 prosrc_str,
00972 probin_str,
00973 false,
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
00992
00993
00994
00995
00996 void
00997 RemoveFunctionById(Oid funcOid)
00998 {
00999 Relation relation;
01000 HeapTuple tup;
01001 bool isagg;
01002
01003
01004
01005
01006 relation = heap_open(ProcedureRelationId, RowExclusiveLock);
01007
01008 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
01009 if (!HeapTupleIsValid(tup))
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
01022
01023 if (isagg)
01024 {
01025 relation = heap_open(AggregateRelationId, RowExclusiveLock);
01026
01027 tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcOid));
01028 if (!HeapTupleIsValid(tup))
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
01041
01042
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))
01068 elog(ERROR, "cache lookup failed for function %u", funcOid);
01069
01070 procForm = (Form_pg_proc) GETSTRUCT(tup);
01071
01072
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
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
01143 datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull);
01144 a = isnull ? NULL : DatumGetArrayTypeP(datum);
01145
01146
01147 a = update_proconfig_value(a, set_items);
01148
01149
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
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
01182
01183
01184
01185
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))
01198 elog(ERROR, "cache lookup failed for function %u", funcOid);
01199 procForm = (Form_pg_proc) GETSTRUCT(tup);
01200
01201 if (procForm->prorettype != OPAQUEOID)
01202 elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
01203
01204
01205 procForm->prorettype = newRetType;
01206
01207
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
01218
01219
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))
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
01240 procForm->proargtypes.values[argIndex] = newArgType;
01241
01242
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
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
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
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
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
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
01366
01367
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
01407
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
01416
01417
01418
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
01431
01432
01433
01434
01435
01436
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
01458
01459
01460
01461
01462
01463
01464
01465
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
01476
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
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;
01498 break;
01499 }
01500
01501 relation = heap_open(CastRelationId, RowExclusiveLock);
01502
01503
01504
01505
01506
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
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
01534 myself.classId = CastRelationId;
01535 myself.objectId = castid;
01536 myself.objectSubId = 0;
01537
01538
01539 referenced.classId = TypeRelationId;
01540 referenced.objectId = sourcetypeid;
01541 referenced.objectSubId = 0;
01542 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01543
01544
01545 referenced.classId = TypeRelationId;
01546 referenced.objectId = targettypeid;
01547 referenced.objectSubId = 0;
01548 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
01549
01550
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
01560 recordDependencyOnCurrentExtension(&myself, false);
01561
01562
01563 InvokeObjectPostCreateHook(CastRelationId, castid, 0);
01564
01565 heap_freetuple(tuple);
01566
01567 heap_close(relation, RowExclusiveLock);
01568
01569 return castid;
01570 }
01571
01572
01573
01574
01575
01576
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
01623
01624
01625
01626
01627 void
01628 IsThereFunctionInNamespace(const char *proname, int pronargs,
01629 oidvector proargtypes, Oid nspOid)
01630 {
01631
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
01646
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
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
01694 if (language_item)
01695 language = strVal(language_item->arg);
01696 else
01697 language = "plpgsql";
01698
01699
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
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
01726 if (!superuser())
01727 aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
01728 NameStr(languageStruct->lanname));
01729 }
01730
01731
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
01742 OidFunctionCall1(laninline, PointerGetDatum(codeblock));
01743 }