1 /*------------------------------------------------------------------------- 2 * 3 * pg_proc.c 4 * routines to support manipulation of the pg_proc relation 5 * 6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group 7 * Portions Copyright (c) 1994, Regents of the University of California 8 * 9 * 10 * IDENTIFICATION 11 * src/backend/catalog/pg_proc.c 12 * 13 *------------------------------------------------------------------------- 14 */ 15 #include "postgres.h" 16 17 #include "access/htup_details.h" 18 #include "access/table.h" 19 #include "access/xact.h" 20 #include "catalog/catalog.h" 21 #include "catalog/dependency.h" 22 #include "catalog/indexing.h" 23 #include "catalog/objectaccess.h" 24 #include "catalog/pg_language.h" 25 #include "catalog/pg_namespace.h" 26 #include "catalog/pg_proc.h" 27 #include "catalog/pg_transform.h" 28 #include "catalog/pg_type.h" 29 #include "commands/defrem.h" 30 #include "executor/functions.h" 31 #include "funcapi.h" 32 #include "mb/pg_wchar.h" 33 #include "miscadmin.h" 34 #include "nodes/nodeFuncs.h" 35 #include "parser/parse_type.h" 36 #include "tcop/pquery.h" 37 #include "tcop/tcopprot.h" 38 #include "utils/acl.h" 39 #include "utils/builtins.h" 40 #include "utils/lsyscache.h" 41 #include "utils/regproc.h" 42 #include "utils/rel.h" 43 #include "utils/syscache.h" 44 45 46 typedef struct 47 { 48 char *proname; 49 char *prosrc; 50 } parse_error_callback_arg; 51 52 static void sql_function_parse_error_callback(void *arg); 53 static int match_prosrc_to_query(const char *prosrc, const char *queryText, 54 int cursorpos); 55 static bool match_prosrc_to_literal(const char *prosrc, const char *literal, 56 int cursorpos, int *newcursorpos); 57 58 59 /* ---------------------------------------------------------------- 60 * ProcedureCreate 61 * 62 * Note: allParameterTypes, parameterModes, parameterNames, trftypes, and proconfig 63 * are either arrays of the proper types or NULL. We declare them Datum, 64 * not "ArrayType *", to avoid importing array.h into pg_proc.h. 65 * ---------------------------------------------------------------- 66 */ 67 ObjectAddress 68 ProcedureCreate(const char *procedureName, 69 Oid procNamespace, 70 bool replace, 71 bool returnsSet, 72 Oid returnType, 73 Oid proowner, 74 Oid languageObjectId, 75 Oid languageValidator, 76 const char *prosrc, 77 const char *probin, 78 char prokind, 79 bool security_definer, 80 bool isLeakProof, 81 bool isStrict, 82 char volatility, 83 char parallel, 84 oidvector *parameterTypes, 85 Datum allParameterTypes, 86 Datum parameterModes, 87 Datum parameterNames, 88 List *parameterDefaults, 89 Datum trftypes, 90 Datum proconfig, 91 Oid prosupport, 92 float4 procost, 93 float4 prorows) 94 { 95 Oid retval; 96 int parameterCount; 97 int allParamCount; 98 Oid *allParams; 99 char *paramModes = NULL; 100 bool genericInParam = false; 101 bool genericOutParam = false; 102 bool anyrangeInParam = false; 103 bool anyrangeOutParam = false; 104 bool internalInParam = false; 105 bool internalOutParam = false; 106 Oid variadicType = InvalidOid; 107 Acl *proacl = NULL; 108 Relation rel; 109 HeapTuple tup; 110 HeapTuple oldtup; 111 bool nulls[Natts_pg_proc]; 112 Datum values[Natts_pg_proc]; 113 bool replaces[Natts_pg_proc]; 114 NameData procname; 115 TupleDesc tupDesc; 116 bool is_update; 117 ObjectAddress myself, 118 referenced; 119 int i; 120 Oid trfid; 121 122 /* 123 * sanity checks 124 */ 125 Assert(PointerIsValid(prosrc)); 126 127 parameterCount = parameterTypes->dim1; 128 if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS) 129 ereport(ERROR, 130 (errcode(ERRCODE_TOO_MANY_ARGUMENTS), 131 errmsg_plural("functions cannot have more than %d argument", 132 "functions cannot have more than %d arguments", 133 FUNC_MAX_ARGS, 134 FUNC_MAX_ARGS))); 135 /* note: the above is correct, we do NOT count output arguments */ 136 137 /* Deconstruct array inputs */ 138 if (allParameterTypes != PointerGetDatum(NULL)) 139 { 140 /* 141 * We expect the array to be a 1-D OID array; verify that. We don't 142 * need to use deconstruct_array() since the array data is just going 143 * to look like a C array of OID values. 144 */ 145 ArrayType *allParamArray = (ArrayType *) DatumGetPointer(allParameterTypes); 146 147 allParamCount = ARR_DIMS(allParamArray)[0]; 148 if (ARR_NDIM(allParamArray) != 1 || 149 allParamCount <= 0 || 150 ARR_HASNULL(allParamArray) || 151 ARR_ELEMTYPE(allParamArray) != OIDOID) 152 elog(ERROR, "allParameterTypes is not a 1-D Oid array"); 153 allParams = (Oid *) ARR_DATA_PTR(allParamArray); 154 Assert(allParamCount >= parameterCount); 155 /* we assume caller got the contents right */ 156 } 157 else 158 { 159 allParamCount = parameterCount; 160 allParams = parameterTypes->values; 161 } 162 163 if (parameterModes != PointerGetDatum(NULL)) 164 { 165 /* 166 * We expect the array to be a 1-D CHAR array; verify that. We don't 167 * need to use deconstruct_array() since the array data is just going 168 * to look like a C array of char values. 169 */ 170 ArrayType *modesArray = (ArrayType *) DatumGetPointer(parameterModes); 171 172 if (ARR_NDIM(modesArray) != 1 || 173 ARR_DIMS(modesArray)[0] != allParamCount || 174 ARR_HASNULL(modesArray) || 175 ARR_ELEMTYPE(modesArray) != CHAROID) 176 elog(ERROR, "parameterModes is not a 1-D char array"); 177 paramModes = (char *) ARR_DATA_PTR(modesArray); 178 } 179 180 /* 181 * Detect whether we have polymorphic or INTERNAL arguments. The first 182 * loop checks input arguments, the second output arguments. 183 */ 184 for (i = 0; i < parameterCount; i++) 185 { 186 switch (parameterTypes->values[i]) 187 { 188 case ANYARRAYOID: 189 case ANYELEMENTOID: 190 case ANYNONARRAYOID: 191 case ANYENUMOID: 192 genericInParam = true; 193 break; 194 case ANYRANGEOID: 195 genericInParam = true; 196 anyrangeInParam = true; 197 break; 198 case INTERNALOID: 199 internalInParam = true; 200 break; 201 } 202 } 203 204 if (allParameterTypes != PointerGetDatum(NULL)) 205 { 206 for (i = 0; i < allParamCount; i++) 207 { 208 if (paramModes == NULL || 209 paramModes[i] == PROARGMODE_IN || 210 paramModes[i] == PROARGMODE_VARIADIC) 211 continue; /* ignore input-only params */ 212 213 switch (allParams[i]) 214 { 215 case ANYARRAYOID: 216 case ANYELEMENTOID: 217 case ANYNONARRAYOID: 218 case ANYENUMOID: 219 genericOutParam = true; 220 break; 221 case ANYRANGEOID: 222 genericOutParam = true; 223 anyrangeOutParam = true; 224 break; 225 case INTERNALOID: 226 internalOutParam = true; 227 break; 228 } 229 } 230 } 231 232 /* 233 * Do not allow polymorphic return type unless at least one input argument 234 * is polymorphic. ANYRANGE return type is even stricter: must have an 235 * ANYRANGE input (since we can't deduce the specific range type from 236 * ANYELEMENT). Also, do not allow return type INTERNAL unless at least 237 * one input argument is INTERNAL. 238 */ 239 if ((IsPolymorphicType(returnType) || genericOutParam) 240 && !genericInParam) 241 ereport(ERROR, 242 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 243 errmsg("cannot determine result data type"), 244 errdetail("A function returning a polymorphic type must have at least one polymorphic argument."))); 245 246 if ((returnType == ANYRANGEOID || anyrangeOutParam) && 247 !anyrangeInParam) 248 ereport(ERROR, 249 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 250 errmsg("cannot determine result data type"), 251 errdetail("A function returning \"anyrange\" must have at least one \"anyrange\" argument."))); 252 253 if ((returnType == INTERNALOID || internalOutParam) && !internalInParam) 254 ereport(ERROR, 255 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 256 errmsg("unsafe use of pseudo-type \"internal\""), 257 errdetail("A function returning \"internal\" must have at least one \"internal\" argument."))); 258 259 if (paramModes != NULL) 260 { 261 /* 262 * Only the last input parameter can be variadic; if it is, save its 263 * element type. Errors here are just elog since caller should have 264 * checked this already. 265 */ 266 for (i = 0; i < allParamCount; i++) 267 { 268 switch (paramModes[i]) 269 { 270 case PROARGMODE_IN: 271 case PROARGMODE_INOUT: 272 if (OidIsValid(variadicType)) 273 elog(ERROR, "variadic parameter must be last"); 274 break; 275 case PROARGMODE_OUT: 276 case PROARGMODE_TABLE: 277 /* okay */ 278 break; 279 case PROARGMODE_VARIADIC: 280 if (OidIsValid(variadicType)) 281 elog(ERROR, "variadic parameter must be last"); 282 switch (allParams[i]) 283 { 284 case ANYOID: 285 variadicType = ANYOID; 286 break; 287 case ANYARRAYOID: 288 variadicType = ANYELEMENTOID; 289 break; 290 default: 291 variadicType = get_element_type(allParams[i]); 292 if (!OidIsValid(variadicType)) 293 elog(ERROR, "variadic parameter is not an array"); 294 break; 295 } 296 break; 297 default: 298 elog(ERROR, "invalid parameter mode '%c'", paramModes[i]); 299 break; 300 } 301 } 302 } 303 304 /* 305 * All seems OK; prepare the data to be inserted into pg_proc. 306 */ 307 308 for (i = 0; i < Natts_pg_proc; ++i) 309 { 310 nulls[i] = false; 311 values[i] = (Datum) 0; 312 replaces[i] = true; 313 } 314 315 namestrcpy(&procname, procedureName); 316 values[Anum_pg_proc_proname - 1] = NameGetDatum(&procname); 317 values[Anum_pg_proc_pronamespace - 1] = ObjectIdGetDatum(procNamespace); 318 values[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(proowner); 319 values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId); 320 values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost); 321 values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows); 322 values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType); 323 values[Anum_pg_proc_prosupport - 1] = ObjectIdGetDatum(prosupport); 324 values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind); 325 values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer); 326 values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof); 327 values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict); 328 values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet); 329 values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility); 330 values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel); 331 values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount); 332 values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults)); 333 values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType); 334 values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes); 335 if (allParameterTypes != PointerGetDatum(NULL)) 336 values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes; 337 else 338 nulls[Anum_pg_proc_proallargtypes - 1] = true; 339 if (parameterModes != PointerGetDatum(NULL)) 340 values[Anum_pg_proc_proargmodes - 1] = parameterModes; 341 else 342 nulls[Anum_pg_proc_proargmodes - 1] = true; 343 if (parameterNames != PointerGetDatum(NULL)) 344 values[Anum_pg_proc_proargnames - 1] = parameterNames; 345 else 346 nulls[Anum_pg_proc_proargnames - 1] = true; 347 if (parameterDefaults != NIL) 348 values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults)); 349 else 350 nulls[Anum_pg_proc_proargdefaults - 1] = true; 351 if (trftypes != PointerGetDatum(NULL)) 352 values[Anum_pg_proc_protrftypes - 1] = trftypes; 353 else 354 nulls[Anum_pg_proc_protrftypes - 1] = true; 355 values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc); 356 if (probin) 357 values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin); 358 else 359 nulls[Anum_pg_proc_probin - 1] = true; 360 if (proconfig != PointerGetDatum(NULL)) 361 values[Anum_pg_proc_proconfig - 1] = proconfig; 362 else 363 nulls[Anum_pg_proc_proconfig - 1] = true; 364 /* proacl will be determined later */ 365 366 rel = table_open(ProcedureRelationId, RowExclusiveLock); 367 tupDesc = RelationGetDescr(rel); 368 369 /* Check for pre-existing definition */ 370 oldtup = SearchSysCache3(PROCNAMEARGSNSP, 371 PointerGetDatum(procedureName), 372 PointerGetDatum(parameterTypes), 373 ObjectIdGetDatum(procNamespace)); 374 375 if (HeapTupleIsValid(oldtup)) 376 { 377 /* There is one; okay to replace it? */ 378 Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup); 379 Datum proargnames; 380 bool isnull; 381 const char *dropcmd; 382 383 if (!replace) 384 ereport(ERROR, 385 (errcode(ERRCODE_DUPLICATE_FUNCTION), 386 errmsg("function \"%s\" already exists with same argument types", 387 procedureName))); 388 if (!pg_proc_ownercheck(oldproc->oid, proowner)) 389 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION, 390 procedureName); 391 392 /* Not okay to change routine kind */ 393 if (oldproc->prokind != prokind) 394 ereport(ERROR, 395 (errcode(ERRCODE_WRONG_OBJECT_TYPE), 396 errmsg("cannot change routine kind"), 397 (oldproc->prokind == PROKIND_AGGREGATE ? 398 errdetail("\"%s\" is an aggregate function.", procedureName) : 399 oldproc->prokind == PROKIND_FUNCTION ? 400 errdetail("\"%s\" is a function.", procedureName) : 401 oldproc->prokind == PROKIND_PROCEDURE ? 402 errdetail("\"%s\" is a procedure.", procedureName) : 403 oldproc->prokind == PROKIND_WINDOW ? 404 errdetail("\"%s\" is a window function.", procedureName) : 405 0))); 406 407 dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" : 408 prokind == PROKIND_AGGREGATE ? "DROP AGGREGATE" : 409 "DROP FUNCTION"); 410 411 /* 412 * Not okay to change the return type of the existing proc, since 413 * existing rules, views, etc may depend on the return type. 414 * 415 * In case of a procedure, a changing return type means that whether 416 * the procedure has output parameters was changed. Since there is no 417 * user visible return type, we produce a more specific error message. 418 */ 419 if (returnType != oldproc->prorettype || 420 returnsSet != oldproc->proretset) 421 ereport(ERROR, 422 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 423 prokind == PROKIND_PROCEDURE 424 ? errmsg("cannot change whether a procedure has output parameters") 425 : errmsg("cannot change return type of existing function"), 426 427 /* 428 * translator: first %s is DROP FUNCTION, DROP PROCEDURE, or DROP 429 * AGGREGATE 430 */ 431 errhint("Use %s %s first.", 432 dropcmd, 433 format_procedure(oldproc->oid)))); 434 435 /* 436 * If it returns RECORD, check for possible change of record type 437 * implied by OUT parameters 438 */ 439 if (returnType == RECORDOID) 440 { 441 TupleDesc olddesc; 442 TupleDesc newdesc; 443 444 olddesc = build_function_result_tupdesc_t(oldtup); 445 newdesc = build_function_result_tupdesc_d(prokind, 446 allParameterTypes, 447 parameterModes, 448 parameterNames); 449 if (olddesc == NULL && newdesc == NULL) 450 /* ok, both are runtime-defined RECORDs */ ; 451 else if (olddesc == NULL || newdesc == NULL || 452 !equalTupleDescs(olddesc, newdesc)) 453 ereport(ERROR, 454 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 455 errmsg("cannot change return type of existing function"), 456 errdetail("Row type defined by OUT parameters is different."), 457 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ 458 errhint("Use %s %s first.", 459 dropcmd, 460 format_procedure(oldproc->oid)))); 461 } 462 463 /* 464 * If there were any named input parameters, check to make sure the 465 * names have not been changed, as this could break existing calls. We 466 * allow adding names to formerly unnamed parameters, though. 467 */ 468 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, 469 Anum_pg_proc_proargnames, 470 &isnull); 471 if (!isnull) 472 { 473 Datum proargmodes; 474 char **old_arg_names; 475 char **new_arg_names; 476 int n_old_arg_names; 477 int n_new_arg_names; 478 int j; 479 480 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, 481 Anum_pg_proc_proargmodes, 482 &isnull); 483 if (isnull) 484 proargmodes = PointerGetDatum(NULL); /* just to be sure */ 485 486 n_old_arg_names = get_func_input_arg_names(proargnames, 487 proargmodes, 488 &old_arg_names); 489 n_new_arg_names = get_func_input_arg_names(parameterNames, 490 parameterModes, 491 &new_arg_names); 492 for (j = 0; j < n_old_arg_names; j++) 493 { 494 if (old_arg_names[j] == NULL) 495 continue; 496 if (j >= n_new_arg_names || new_arg_names[j] == NULL || 497 strcmp(old_arg_names[j], new_arg_names[j]) != 0) 498 ereport(ERROR, 499 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 500 errmsg("cannot change name of input parameter \"%s\"", 501 old_arg_names[j]), 502 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ 503 errhint("Use %s %s first.", 504 dropcmd, 505 format_procedure(oldproc->oid)))); 506 } 507 } 508 509 /* 510 * If there are existing defaults, check compatibility: redefinition 511 * must not remove any defaults nor change their types. (Removing a 512 * default might cause a function to fail to satisfy an existing call. 513 * Changing type would only be possible if the associated parameter is 514 * polymorphic, and in such cases a change of default type might alter 515 * the resolved output type of existing calls.) 516 */ 517 if (oldproc->pronargdefaults != 0) 518 { 519 Datum proargdefaults; 520 List *oldDefaults; 521 ListCell *oldlc; 522 ListCell *newlc; 523 524 if (list_length(parameterDefaults) < oldproc->pronargdefaults) 525 ereport(ERROR, 526 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 527 errmsg("cannot remove parameter defaults from existing function"), 528 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ 529 errhint("Use %s %s first.", 530 dropcmd, 531 format_procedure(oldproc->oid)))); 532 533 proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, 534 Anum_pg_proc_proargdefaults, 535 &isnull); 536 Assert(!isnull); 537 oldDefaults = castNode(List, stringToNode(TextDatumGetCString(proargdefaults))); 538 Assert(list_length(oldDefaults) == oldproc->pronargdefaults); 539 540 /* new list can have more defaults than old, advance over 'em */ 541 newlc = list_head(parameterDefaults); 542 for (i = list_length(parameterDefaults) - oldproc->pronargdefaults; 543 i > 0; 544 i--) 545 newlc = lnext(newlc); 546 547 foreach(oldlc, oldDefaults) 548 { 549 Node *oldDef = (Node *) lfirst(oldlc); 550 Node *newDef = (Node *) lfirst(newlc); 551 552 if (exprType(oldDef) != exprType(newDef)) 553 ereport(ERROR, 554 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 555 errmsg("cannot change data type of existing parameter default value"), 556 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */ 557 errhint("Use %s %s first.", 558 dropcmd, 559 format_procedure(oldproc->oid)))); 560 newlc = lnext(newlc); 561 } 562 } 563 564 /* 565 * Do not change existing oid, ownership or permissions, either. Note 566 * dependency-update code below has to agree with this decision. 567 */ 568 replaces[Anum_pg_proc_oid - 1] = false; 569 replaces[Anum_pg_proc_proowner - 1] = false; 570 replaces[Anum_pg_proc_proacl - 1] = false; 571 572 /* Okay, do it... */ 573 tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); 574 CatalogTupleUpdate(rel, &tup->t_self, tup); 575 576 ReleaseSysCache(oldtup); 577 is_update = true; 578 } 579 else 580 { 581 /* Creating a new procedure */ 582 Oid newOid; 583 584 /* First, get default permissions and set up proacl */ 585 proacl = get_user_default_acl(OBJECT_FUNCTION, proowner, 586 procNamespace); 587 if (proacl != NULL) 588 values[Anum_pg_proc_proacl - 1] = PointerGetDatum(proacl); 589 else 590 nulls[Anum_pg_proc_proacl - 1] = true; 591 592 newOid = GetNewOidWithIndex(rel, ProcedureOidIndexId, 593 Anum_pg_proc_oid); 594 values[Anum_pg_proc_oid - 1] = ObjectIdGetDatum(newOid); 595 tup = heap_form_tuple(tupDesc, values, nulls); 596 CatalogTupleInsert(rel, tup); 597 is_update = false; 598 } 599 600 601 retval = ((Form_pg_proc) GETSTRUCT(tup))->oid; 602 603 /* 604 * Create dependencies for the new function. If we are updating an 605 * existing function, first delete any existing pg_depend entries. 606 * (However, since we are not changing ownership or permissions, the 607 * shared dependencies do *not* need to change, and we leave them alone.) 608 */ 609 if (is_update) 610 deleteDependencyRecordsFor(ProcedureRelationId, retval, true); 611 612 myself.classId = ProcedureRelationId; 613 myself.objectId = retval; 614 myself.objectSubId = 0; 615 616 /* dependency on namespace */ 617 referenced.classId = NamespaceRelationId; 618 referenced.objectId = procNamespace; 619 referenced.objectSubId = 0; 620 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 621 622 /* dependency on implementation language */ 623 referenced.classId = LanguageRelationId; 624 referenced.objectId = languageObjectId; 625 referenced.objectSubId = 0; 626 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 627 628 /* dependency on return type */ 629 referenced.classId = TypeRelationId; 630 referenced.objectId = returnType; 631 referenced.objectSubId = 0; 632 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 633 634 /* dependency on transform used by return type, if any */ 635 if ((trfid = get_transform_oid(returnType, languageObjectId, true))) 636 { 637 referenced.classId = TransformRelationId; 638 referenced.objectId = trfid; 639 referenced.objectSubId = 0; 640 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 641 } 642 643 /* dependency on parameter types */ 644 for (i = 0; i < allParamCount; i++) 645 { 646 referenced.classId = TypeRelationId; 647 referenced.objectId = allParams[i]; 648 referenced.objectSubId = 0; 649 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 650 651 /* dependency on transform used by parameter type, if any */ 652 if ((trfid = get_transform_oid(allParams[i], languageObjectId, true))) 653 { 654 referenced.classId = TransformRelationId; 655 referenced.objectId = trfid; 656 referenced.objectSubId = 0; 657 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 658 } 659 } 660 661 /* dependency on parameter default expressions */ 662 if (parameterDefaults) 663 recordDependencyOnExpr(&myself, (Node *) parameterDefaults, 664 NIL, DEPENDENCY_NORMAL); 665 666 /* dependency on support function, if any */ 667 if (OidIsValid(prosupport)) 668 { 669 referenced.classId = ProcedureRelationId; 670 referenced.objectId = prosupport; 671 referenced.objectSubId = 0; 672 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); 673 } 674 675 /* dependency on owner */ 676 if (!is_update) 677 recordDependencyOnOwner(ProcedureRelationId, retval, proowner); 678 679 /* dependency on any roles mentioned in ACL */ 680 if (!is_update) 681 recordDependencyOnNewAcl(ProcedureRelationId, retval, 0, 682 proowner, proacl); 683 684 /* dependency on extension */ 685 recordDependencyOnCurrentExtension(&myself, is_update); 686 687 heap_freetuple(tup); 688 689 /* Post creation hook for new function */ 690 InvokeObjectPostCreateHook(ProcedureRelationId, retval, 0); 691 692 table_close(rel, RowExclusiveLock); 693 694 /* Verify function body */ 695 if (OidIsValid(languageValidator)) 696 { 697 ArrayType *set_items = NULL; 698 int save_nestlevel = 0; 699 700 /* Advance command counter so new tuple can be seen by validator */ 701 CommandCounterIncrement(); 702 703 /* 704 * Set per-function configuration parameters so that the validation is 705 * done with the environment the function expects. However, if 706 * check_function_bodies is off, we don't do this, because that would 707 * create dump ordering hazards that pg_dump doesn't know how to deal 708 * with. (For example, a SET clause might refer to a not-yet-created 709 * text search configuration.) This means that the validator 710 * shouldn't complain about anything that might depend on a GUC 711 * parameter when check_function_bodies is off. 712 */ 713 if (check_function_bodies) 714 { 715 set_items = (ArrayType *) DatumGetPointer(proconfig); 716 if (set_items) /* Need a new GUC nesting level */ 717 { 718 save_nestlevel = NewGUCNestLevel(); 719 ProcessGUCArray(set_items, 720 (superuser() ? PGC_SUSET : PGC_USERSET), 721 PGC_S_SESSION, 722 GUC_ACTION_SAVE); 723 } 724 } 725 726 OidFunctionCall1(languageValidator, ObjectIdGetDatum(retval)); 727 728 if (set_items) 729 AtEOXact_GUC(true, save_nestlevel); 730 } 731 732 return myself; 733 } 734 735 736 737 /* 738 * Validator for internal functions 739 * 740 * Check that the given internal function name (the "prosrc" value) is 741 * a known builtin function. 742 */ 743 Datum 744 fmgr_internal_validator(PG_FUNCTION_ARGS) 745 { 746 Oid funcoid = PG_GETARG_OID(0); 747 HeapTuple tuple; 748 bool isnull; 749 Datum tmp; 750 char *prosrc; 751 752 if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) 753 PG_RETURN_VOID(); 754 755 /* 756 * We do not honor check_function_bodies since it's unlikely the function 757 * name will be found later if it isn't there now. 758 */ 759 760 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); 761 if (!HeapTupleIsValid(tuple)) 762 elog(ERROR, "cache lookup failed for function %u", funcoid); 763 764 tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); 765 if (isnull) 766 elog(ERROR, "null prosrc"); 767 prosrc = TextDatumGetCString(tmp); 768 769 if (fmgr_internal_function(prosrc) == InvalidOid) 770 ereport(ERROR, 771 (errcode(ERRCODE_UNDEFINED_FUNCTION), 772 errmsg("there is no built-in function named \"%s\"", 773 prosrc))); 774 775 ReleaseSysCache(tuple); 776 777 PG_RETURN_VOID(); 778 } 779 780 781 782 /* 783 * Validator for C language functions 784 * 785 * Make sure that the library file exists, is loadable, and contains 786 * the specified link symbol. Also check for a valid function 787 * information record. 788 */ 789 Datum 790 fmgr_c_validator(PG_FUNCTION_ARGS) 791 { 792 Oid funcoid = PG_GETARG_OID(0); 793 void *libraryhandle; 794 HeapTuple tuple; 795 bool isnull; 796 Datum tmp; 797 char *prosrc; 798 char *probin; 799 800 if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) 801 PG_RETURN_VOID(); 802 803 /* 804 * It'd be most consistent to skip the check if !check_function_bodies, 805 * but the purpose of that switch is to be helpful for pg_dump loading, 806 * and for pg_dump loading it's much better if we *do* check. 807 */ 808 809 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); 810 if (!HeapTupleIsValid(tuple)) 811 elog(ERROR, "cache lookup failed for function %u", funcoid); 812 813 tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); 814 if (isnull) 815 elog(ERROR, "null prosrc for C function %u", funcoid); 816 prosrc = TextDatumGetCString(tmp); 817 818 tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull); 819 if (isnull) 820 elog(ERROR, "null probin for C function %u", funcoid); 821 probin = TextDatumGetCString(tmp); 822 823 (void) load_external_function(probin, prosrc, true, &libraryhandle); 824 (void) fetch_finfo_record(libraryhandle, prosrc); 825 826 ReleaseSysCache(tuple); 827 828 PG_RETURN_VOID(); 829 } 830 831 832 /* 833 * Validator for SQL language functions 834 * 835 * Parse it here in order to be sure that it contains no syntax errors. 836 */ 837 Datum 838 fmgr_sql_validator(PG_FUNCTION_ARGS) 839 { 840 Oid funcoid = PG_GETARG_OID(0); 841 HeapTuple tuple; 842 Form_pg_proc proc; 843 List *raw_parsetree_list; 844 List *querytree_list; 845 ListCell *lc; 846 bool isnull; 847 Datum tmp; 848 char *prosrc; 849 parse_error_callback_arg callback_arg; 850 ErrorContextCallback sqlerrcontext; 851 bool haspolyarg; 852 int i; 853 854 if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid)) 855 PG_RETURN_VOID(); 856 857 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid)); 858 if (!HeapTupleIsValid(tuple)) 859 elog(ERROR, "cache lookup failed for function %u", funcoid); 860 proc = (Form_pg_proc) GETSTRUCT(tuple); 861 862 /* Disallow pseudotype result */ 863 /* except for RECORD, VOID, or polymorphic */ 864 if (get_typtype(proc->prorettype) == TYPTYPE_PSEUDO && 865 proc->prorettype != RECORDOID && 866 proc->prorettype != VOIDOID && 867 !IsPolymorphicType(proc->prorettype)) 868 ereport(ERROR, 869 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 870 errmsg("SQL functions cannot return type %s", 871 format_type_be(proc->prorettype)))); 872 873 /* Disallow pseudotypes in arguments */ 874 /* except for polymorphic */ 875 haspolyarg = false; 876 for (i = 0; i < proc->pronargs; i++) 877 { 878 if (get_typtype(proc->proargtypes.values[i]) == TYPTYPE_PSEUDO) 879 { 880 if (IsPolymorphicType(proc->proargtypes.values[i])) 881 haspolyarg = true; 882 else 883 ereport(ERROR, 884 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), 885 errmsg("SQL functions cannot have arguments of type %s", 886 format_type_be(proc->proargtypes.values[i])))); 887 } 888 } 889 890 /* Postpone body checks if !check_function_bodies */ 891 if (check_function_bodies) 892 { 893 tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); 894 if (isnull) 895 elog(ERROR, "null prosrc"); 896 897 prosrc = TextDatumGetCString(tmp); 898 899 /* 900 * Setup error traceback support for ereport(). 901 */ 902 callback_arg.proname = NameStr(proc->proname); 903 callback_arg.prosrc = prosrc; 904 905 sqlerrcontext.callback = sql_function_parse_error_callback; 906 sqlerrcontext.arg = (void *) &callback_arg; 907 sqlerrcontext.previous = error_context_stack; 908 error_context_stack = &sqlerrcontext; 909 910 /* 911 * We can't do full prechecking of the function definition if there 912 * are any polymorphic input types, because actual datatypes of 913 * expression results will be unresolvable. The check will be done at 914 * runtime instead. 915 * 916 * We can run the text through the raw parser though; this will at 917 * least catch silly syntactic errors. 918 */ 919 raw_parsetree_list = pg_parse_query(prosrc); 920 921 if (!haspolyarg) 922 { 923 /* 924 * OK to do full precheck: analyze and rewrite the queries, then 925 * verify the result type. 926 */ 927 SQLFunctionParseInfoPtr pinfo; 928 929 /* But first, set up parameter information */ 930 pinfo = prepare_sql_fn_parse_info(tuple, NULL, InvalidOid); 931 932 querytree_list = NIL; 933 foreach(lc, raw_parsetree_list) 934 { 935 RawStmt *parsetree = lfirst_node(RawStmt, lc); 936 List *querytree_sublist; 937 938 querytree_sublist = pg_analyze_and_rewrite_params(parsetree, 939 prosrc, 940 (ParserSetupHook) sql_fn_parser_setup, 941 pinfo, 942 NULL); 943 querytree_list = list_concat(querytree_list, 944 querytree_sublist); 945 } 946 947 check_sql_fn_statements(querytree_list); 948 (void) check_sql_fn_retval(funcoid, proc->prorettype, 949 querytree_list, 950 NULL, NULL); 951 } 952 953 error_context_stack = sqlerrcontext.previous; 954 } 955 956 ReleaseSysCache(tuple); 957 958 PG_RETURN_VOID(); 959 } 960 961 /* 962 * Error context callback for handling errors in SQL function definitions 963 */ 964 static void 965 sql_function_parse_error_callback(void *arg) 966 { 967 parse_error_callback_arg *callback_arg = (parse_error_callback_arg *) arg; 968 969 /* See if it's a syntax error; if so, transpose to CREATE FUNCTION */ 970 if (!function_parse_error_transpose(callback_arg->prosrc)) 971 { 972 /* If it's not a syntax error, push info onto context stack */ 973 errcontext("SQL function \"%s\"", callback_arg->proname); 974 } 975 } 976 977 /* 978 * Adjust a syntax error occurring inside the function body of a CREATE 979 * FUNCTION or DO command. This can be used by any function validator or 980 * anonymous-block handler, not only for SQL-language functions. 981 * It is assumed that the syntax error position is initially relative to the 982 * function body string (as passed in). If possible, we adjust the position 983 * to reference the original command text; if we can't manage that, we set 984 * up an "internal query" syntax error instead. 985 * 986 * Returns true if a syntax error was processed, false if not. 987 */ 988 bool 989 function_parse_error_transpose(const char *prosrc) 990 { 991 int origerrposition; 992 int newerrposition; 993 const char *queryText; 994 995 /* 996 * Nothing to do unless we are dealing with a syntax error that has a 997 * cursor position. 998 * 999 * Some PLs may prefer to report the error position as an internal error 1000 * to begin with, so check that too. 1001 */ 1002 origerrposition = geterrposition(); 1003 if (origerrposition <= 0) 1004 { 1005 origerrposition = getinternalerrposition(); 1006 if (origerrposition <= 0) 1007 return false; 1008 } 1009 1010 /* We can get the original query text from the active portal (hack...) */ 1011 Assert(ActivePortal && ActivePortal->status == PORTAL_ACTIVE); 1012 queryText = ActivePortal->sourceText; 1013 1014 /* Try to locate the prosrc in the original text */ 1015 newerrposition = match_prosrc_to_query(prosrc, queryText, origerrposition); 1016 1017 if (newerrposition > 0) 1018 { 1019 /* Successful, so fix error position to reference original query */ 1020 errposition(newerrposition); 1021 /* Get rid of any report of the error as an "internal query" */ 1022 internalerrposition(0); 1023 internalerrquery(NULL); 1024 } 1025 else 1026 { 1027 /* 1028 * If unsuccessful, convert the position to an internal position 1029 * marker and give the function text as the internal query. 1030 */ 1031 errposition(0); 1032 internalerrposition(origerrposition); 1033 internalerrquery(prosrc); 1034 } 1035 1036 return true; 1037 } 1038 1039 /* 1040 * Try to locate the string literal containing the function body in the 1041 * given text of the CREATE FUNCTION or DO command. If successful, return 1042 * the character (not byte) index within the command corresponding to the 1043 * given character index within the literal. If not successful, return 0. 1044 */ 1045 static int 1046 match_prosrc_to_query(const char *prosrc, const char *queryText, 1047 int cursorpos) 1048 { 1049 /* 1050 * Rather than fully parsing the original command, we just scan the 1051 * command looking for $prosrc$ or 'prosrc'. This could be fooled (though 1052 * not in any very probable scenarios), so fail if we find more than one 1053 * match. 1054 */ 1055 int prosrclen = strlen(prosrc); 1056 int querylen = strlen(queryText); 1057 int matchpos = 0; 1058 int curpos; 1059 int newcursorpos; 1060 1061 for (curpos = 0; curpos < querylen - prosrclen; curpos++) 1062 { 1063 if (queryText[curpos] == '$' && 1064 strncmp(prosrc, &queryText[curpos + 1], prosrclen) == 0 && 1065 queryText[curpos + 1 + prosrclen] == '$') 1066 { 1067 /* 1068 * Found a $foo$ match. Since there are no embedded quoting 1069 * characters in a dollar-quoted literal, we don't have to do any 1070 * fancy arithmetic; just offset by the starting position. 1071 */ 1072 if (matchpos) 1073 return 0; /* multiple matches, fail */ 1074 matchpos = pg_mbstrlen_with_len(queryText, curpos + 1) 1075 + cursorpos; 1076 } 1077 else if (queryText[curpos] == '\'' && 1078 match_prosrc_to_literal(prosrc, &queryText[curpos + 1], 1079 cursorpos, &newcursorpos)) 1080 { 1081 /* 1082 * Found a 'foo' match. match_prosrc_to_literal() has adjusted 1083 * for any quotes or backslashes embedded in the literal. 1084 */ 1085 if (matchpos) 1086 return 0; /* multiple matches, fail */ 1087 matchpos = pg_mbstrlen_with_len(queryText, curpos + 1) 1088 + newcursorpos; 1089 } 1090 } 1091 1092 return matchpos; 1093 } 1094 1095 /* 1096 * Try to match the given source text to a single-quoted literal. 1097 * If successful, adjust newcursorpos to correspond to the character 1098 * (not byte) index corresponding to cursorpos in the source text. 1099 * 1100 * At entry, literal points just past a ' character. We must check for the 1101 * trailing quote. 1102 */ 1103 static bool 1104 match_prosrc_to_literal(const char *prosrc, const char *literal, 1105 int cursorpos, int *newcursorpos) 1106 { 1107 int newcp = cursorpos; 1108 int chlen; 1109 1110 /* 1111 * This implementation handles backslashes and doubled quotes in the 1112 * string literal. It does not handle the SQL syntax for literals 1113 * continued across line boundaries. 1114 * 1115 * We do the comparison a character at a time, not a byte at a time, so 1116 * that we can do the correct cursorpos math. 1117 */ 1118 while (*prosrc) 1119 { 1120 cursorpos--; /* characters left before cursor */ 1121 1122 /* 1123 * Check for backslashes and doubled quotes in the literal; adjust 1124 * newcp when one is found before the cursor. 1125 */ 1126 if (*literal == '\\') 1127 { 1128 literal++; 1129 if (cursorpos > 0) 1130 newcp++; 1131 } 1132 else if (*literal == '\'') 1133 { 1134 if (literal[1] != '\'') 1135 goto fail; 1136 literal++; 1137 if (cursorpos > 0) 1138 newcp++; 1139 } 1140 chlen = pg_mblen(prosrc); 1141 if (strncmp(prosrc, literal, chlen) != 0) 1142 goto fail; 1143 prosrc += chlen; 1144 literal += chlen; 1145 } 1146 1147 if (*literal == '\'' && literal[1] != '\'') 1148 { 1149 /* success */ 1150 *newcursorpos = newcp; 1151 return true; 1152 } 1153 1154 fail: 1155 /* Must set *newcursorpos to suppress compiler warning */ 1156 *newcursorpos = newcp; 1157 return false; 1158 } 1159 1160 List * 1161 oid_array_to_list(Datum datum) 1162 { 1163 ArrayType *array = DatumGetArrayTypeP(datum); 1164 Datum *values; 1165 int nelems; 1166 int i; 1167 List *result = NIL; 1168 1169 deconstruct_array(array, 1170 OIDOID, 1171 sizeof(Oid), true, 'i', 1172 &values, NULL, &nelems); 1173 for (i = 0; i < nelems; i++) 1174 result = lappend_oid(result, values[i]); 1175 return result; 1176 } 1177