00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "access/tuptoaster.h"
00019 #include "catalog/pg_language.h"
00020 #include "catalog/pg_proc.h"
00021 #include "executor/functions.h"
00022 #include "executor/spi.h"
00023 #include "lib/stringinfo.h"
00024 #include "miscadmin.h"
00025 #include "nodes/nodeFuncs.h"
00026 #include "pgstat.h"
00027 #include "utils/builtins.h"
00028 #include "utils/fmgrtab.h"
00029 #include "utils/guc.h"
00030 #include "utils/lsyscache.h"
00031 #include "utils/syscache.h"
00032
00033
00034
00035
00036 PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook = NULL;
00037 PGDLLIMPORT fmgr_hook_type fmgr_hook = NULL;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #if (defined(__mc68000__) || (defined(__m68k__))) && defined(__ELF__)
00055 typedef int32 (*func_ptr) ();
00056 #else
00057 typedef char *(*func_ptr) ();
00058 #endif
00059
00060
00061
00062
00063 typedef struct
00064 {
00065 func_ptr func;
00066 bool arg_toastable[FUNC_MAX_ARGS];
00067
00068 } Oldstyle_fnextra;
00069
00070
00071
00072
00073 typedef struct
00074 {
00075
00076 Oid fn_oid;
00077 TransactionId fn_xmin;
00078 ItemPointerData fn_tid;
00079 PGFunction user_fn;
00080 const Pg_finfo_record *inforec;
00081 } CFuncHashTabEntry;
00082
00083 static HTAB *CFuncHash = NULL;
00084
00085
00086 static void fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
00087 bool ignore_security);
00088 static void fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
00089 static void fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
00090 static CFuncHashTabEntry *lookup_C_func(HeapTuple procedureTuple);
00091 static void record_C_func(HeapTuple procedureTuple,
00092 PGFunction user_fn, const Pg_finfo_record *inforec);
00093 static Datum fmgr_oldstyle(PG_FUNCTION_ARGS);
00094 static Datum fmgr_security_definer(PG_FUNCTION_ARGS);
00095
00096
00097
00098
00099
00100
00101
00102 static const FmgrBuiltin *
00103 fmgr_isbuiltin(Oid id)
00104 {
00105 int low = 0;
00106 int high = fmgr_nbuiltins - 1;
00107
00108
00109
00110
00111
00112 while (low <= high)
00113 {
00114 int i = (high + low) / 2;
00115 const FmgrBuiltin *ptr = &fmgr_builtins[i];
00116
00117 if (id == ptr->foid)
00118 return ptr;
00119 else if (id > ptr->foid)
00120 low = i + 1;
00121 else
00122 high = i - 1;
00123 }
00124 return NULL;
00125 }
00126
00127
00128
00129
00130
00131
00132 static const FmgrBuiltin *
00133 fmgr_lookupByName(const char *name)
00134 {
00135 int i;
00136
00137 for (i = 0; i < fmgr_nbuiltins; i++)
00138 {
00139 if (strcmp(name, fmgr_builtins[i].funcName) == 0)
00140 return fmgr_builtins + i;
00141 }
00142 return NULL;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 void
00159 fmgr_info(Oid functionId, FmgrInfo *finfo)
00160 {
00161 fmgr_info_cxt_security(functionId, finfo, CurrentMemoryContext, false);
00162 }
00163
00164
00165
00166
00167
00168 void
00169 fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
00170 {
00171 fmgr_info_cxt_security(functionId, finfo, mcxt, false);
00172 }
00173
00174
00175
00176
00177
00178 static void
00179 fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
00180 bool ignore_security)
00181 {
00182 const FmgrBuiltin *fbp;
00183 HeapTuple procedureTuple;
00184 Form_pg_proc procedureStruct;
00185 Datum prosrcdatum;
00186 bool isnull;
00187 char *prosrc;
00188
00189
00190
00191
00192
00193
00194 finfo->fn_oid = InvalidOid;
00195 finfo->fn_extra = NULL;
00196 finfo->fn_mcxt = mcxt;
00197 finfo->fn_expr = NULL;
00198
00199 if ((fbp = fmgr_isbuiltin(functionId)) != NULL)
00200 {
00201
00202
00203
00204 finfo->fn_nargs = fbp->nargs;
00205 finfo->fn_strict = fbp->strict;
00206 finfo->fn_retset = fbp->retset;
00207 finfo->fn_stats = TRACK_FUNC_ALL;
00208 finfo->fn_addr = fbp->func;
00209 finfo->fn_oid = functionId;
00210 return;
00211 }
00212
00213
00214 procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
00215 if (!HeapTupleIsValid(procedureTuple))
00216 elog(ERROR, "cache lookup failed for function %u", functionId);
00217 procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
00218
00219 finfo->fn_nargs = procedureStruct->pronargs;
00220 finfo->fn_strict = procedureStruct->proisstrict;
00221 finfo->fn_retset = procedureStruct->proretset;
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 if (!ignore_security &&
00238 (procedureStruct->prosecdef ||
00239 !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig) ||
00240 FmgrHookIsNeeded(functionId)))
00241 {
00242 finfo->fn_addr = fmgr_security_definer;
00243 finfo->fn_stats = TRACK_FUNC_ALL;
00244 finfo->fn_oid = functionId;
00245 ReleaseSysCache(procedureTuple);
00246 return;
00247 }
00248
00249 switch (procedureStruct->prolang)
00250 {
00251 case INTERNALlanguageId:
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 prosrcdatum = SysCacheGetAttr(PROCOID, procedureTuple,
00263 Anum_pg_proc_prosrc, &isnull);
00264 if (isnull)
00265 elog(ERROR, "null prosrc");
00266 prosrc = TextDatumGetCString(prosrcdatum);
00267 fbp = fmgr_lookupByName(prosrc);
00268 if (fbp == NULL)
00269 ereport(ERROR,
00270 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00271 errmsg("internal function \"%s\" is not in internal lookup table",
00272 prosrc)));
00273 pfree(prosrc);
00274
00275 finfo->fn_addr = fbp->func;
00276
00277 finfo->fn_stats = TRACK_FUNC_ALL;
00278 break;
00279
00280 case ClanguageId:
00281 fmgr_info_C_lang(functionId, finfo, procedureTuple);
00282 finfo->fn_stats = TRACK_FUNC_PL;
00283 break;
00284
00285 case SQLlanguageId:
00286 finfo->fn_addr = fmgr_sql;
00287 finfo->fn_stats = TRACK_FUNC_PL;
00288 break;
00289
00290 default:
00291 fmgr_info_other_lang(functionId, finfo, procedureTuple);
00292 finfo->fn_stats = TRACK_FUNC_OFF;
00293 break;
00294 }
00295
00296 finfo->fn_oid = functionId;
00297 ReleaseSysCache(procedureTuple);
00298 }
00299
00300
00301
00302
00303
00304 static void
00305 fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
00306 {
00307 Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
00308 CFuncHashTabEntry *hashentry;
00309 PGFunction user_fn;
00310 const Pg_finfo_record *inforec;
00311 Oldstyle_fnextra *fnextra;
00312 bool isnull;
00313 int i;
00314
00315
00316
00317
00318 hashentry = lookup_C_func(procedureTuple);
00319 if (hashentry)
00320 {
00321 user_fn = hashentry->user_fn;
00322 inforec = hashentry->inforec;
00323 }
00324 else
00325 {
00326 Datum prosrcattr,
00327 probinattr;
00328 char *prosrcstring,
00329 *probinstring;
00330 void *libraryhandle;
00331
00332
00333
00334
00335
00336
00337 prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
00338 Anum_pg_proc_prosrc, &isnull);
00339 if (isnull)
00340 elog(ERROR, "null prosrc for C function %u", functionId);
00341 prosrcstring = TextDatumGetCString(prosrcattr);
00342
00343 probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
00344 Anum_pg_proc_probin, &isnull);
00345 if (isnull)
00346 elog(ERROR, "null probin for C function %u", functionId);
00347 probinstring = TextDatumGetCString(probinattr);
00348
00349
00350 user_fn = load_external_function(probinstring, prosrcstring, true,
00351 &libraryhandle);
00352
00353
00354 inforec = fetch_finfo_record(libraryhandle, prosrcstring);
00355
00356
00357 record_C_func(procedureTuple, user_fn, inforec);
00358
00359 pfree(prosrcstring);
00360 pfree(probinstring);
00361 }
00362
00363 switch (inforec->api_version)
00364 {
00365 case 0:
00366
00367 finfo->fn_addr = fmgr_oldstyle;
00368 fnextra = (Oldstyle_fnextra *)
00369 MemoryContextAllocZero(finfo->fn_mcxt,
00370 sizeof(Oldstyle_fnextra));
00371 finfo->fn_extra = (void *) fnextra;
00372 fnextra->func = (func_ptr) user_fn;
00373 for (i = 0; i < procedureStruct->pronargs; i++)
00374 {
00375 fnextra->arg_toastable[i] =
00376 TypeIsToastable(procedureStruct->proargtypes.values[i]);
00377 }
00378 break;
00379 case 1:
00380
00381 finfo->fn_addr = user_fn;
00382 break;
00383 default:
00384
00385 elog(ERROR, "unrecognized function API version: %d",
00386 inforec->api_version);
00387 break;
00388 }
00389 }
00390
00391
00392
00393
00394
00395 static void
00396 fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
00397 {
00398 Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
00399 Oid language = procedureStruct->prolang;
00400 HeapTuple languageTuple;
00401 Form_pg_language languageStruct;
00402 FmgrInfo plfinfo;
00403
00404 languageTuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(language));
00405 if (!HeapTupleIsValid(languageTuple))
00406 elog(ERROR, "cache lookup failed for language %u", language);
00407 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
00408
00409
00410
00411
00412
00413
00414 fmgr_info_cxt_security(languageStruct->lanplcallfoid, &plfinfo,
00415 CurrentMemoryContext, true);
00416 finfo->fn_addr = plfinfo.fn_addr;
00417
00418
00419
00420
00421
00422
00423 if (plfinfo.fn_extra != NULL)
00424 elog(ERROR, "language %u has old-style handler", language);
00425
00426 ReleaseSysCache(languageTuple);
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 const Pg_finfo_record *
00444 fetch_finfo_record(void *filehandle, char *funcname)
00445 {
00446 char *infofuncname;
00447 PGFInfoFunction infofunc;
00448 const Pg_finfo_record *inforec;
00449 static Pg_finfo_record default_inforec = {0};
00450
00451
00452 infofuncname = (char *) palloc(strlen(funcname) + 10);
00453 strcpy(infofuncname, "pg_finfo_");
00454 strcat(infofuncname, funcname);
00455
00456
00457 infofunc = (PGFInfoFunction) lookup_external_function(filehandle,
00458 infofuncname);
00459 if (infofunc == NULL)
00460 {
00461
00462 pfree(infofuncname);
00463 return &default_inforec;
00464 }
00465
00466
00467 inforec = (*infofunc) ();
00468
00469
00470 if (inforec == NULL)
00471 elog(ERROR, "null result from info function \"%s\"", infofuncname);
00472 switch (inforec->api_version)
00473 {
00474 case 0:
00475 case 1:
00476
00477 break;
00478 default:
00479 ereport(ERROR,
00480 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00481 errmsg("unrecognized API version %d reported by info function \"%s\"",
00482 inforec->api_version, infofuncname)));
00483 break;
00484 }
00485
00486 pfree(infofuncname);
00487 return inforec;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 static CFuncHashTabEntry *
00506 lookup_C_func(HeapTuple procedureTuple)
00507 {
00508 Oid fn_oid = HeapTupleGetOid(procedureTuple);
00509 CFuncHashTabEntry *entry;
00510
00511 if (CFuncHash == NULL)
00512 return NULL;
00513 entry = (CFuncHashTabEntry *)
00514 hash_search(CFuncHash,
00515 &fn_oid,
00516 HASH_FIND,
00517 NULL);
00518 if (entry == NULL)
00519 return NULL;
00520 if (entry->fn_xmin == HeapTupleHeaderGetXmin(procedureTuple->t_data) &&
00521 ItemPointerEquals(&entry->fn_tid, &procedureTuple->t_self))
00522 return entry;
00523 return NULL;
00524 }
00525
00526
00527
00528
00529 static void
00530 record_C_func(HeapTuple procedureTuple,
00531 PGFunction user_fn, const Pg_finfo_record *inforec)
00532 {
00533 Oid fn_oid = HeapTupleGetOid(procedureTuple);
00534 CFuncHashTabEntry *entry;
00535 bool found;
00536
00537
00538 if (CFuncHash == NULL)
00539 {
00540 HASHCTL hash_ctl;
00541
00542 MemSet(&hash_ctl, 0, sizeof(hash_ctl));
00543 hash_ctl.keysize = sizeof(Oid);
00544 hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
00545 hash_ctl.hash = oid_hash;
00546 CFuncHash = hash_create("CFuncHash",
00547 100,
00548 &hash_ctl,
00549 HASH_ELEM | HASH_FUNCTION);
00550 }
00551
00552 entry = (CFuncHashTabEntry *)
00553 hash_search(CFuncHash,
00554 &fn_oid,
00555 HASH_ENTER,
00556 &found);
00557
00558 entry->fn_xmin = HeapTupleHeaderGetXmin(procedureTuple->t_data);
00559 entry->fn_tid = procedureTuple->t_self;
00560 entry->user_fn = user_fn;
00561 entry->inforec = inforec;
00562 }
00563
00564
00565
00566
00567
00568
00569
00570 void
00571 clear_external_function_hash(void *filehandle)
00572 {
00573 if (CFuncHash)
00574 hash_destroy(CFuncHash);
00575 CFuncHash = NULL;
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 void
00587 fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
00588 MemoryContext destcxt)
00589 {
00590 memcpy(dstinfo, srcinfo, sizeof(FmgrInfo));
00591 dstinfo->fn_mcxt = destcxt;
00592 if (dstinfo->fn_addr == fmgr_oldstyle)
00593 {
00594
00595 Oldstyle_fnextra *fnextra;
00596
00597 fnextra = (Oldstyle_fnextra *)
00598 MemoryContextAlloc(destcxt, sizeof(Oldstyle_fnextra));
00599 memcpy(fnextra, srcinfo->fn_extra, sizeof(Oldstyle_fnextra));
00600 dstinfo->fn_extra = (void *) fnextra;
00601 }
00602 else
00603 dstinfo->fn_extra = NULL;
00604 }
00605
00606
00607
00608
00609
00610
00611
00612 Oid
00613 fmgr_internal_function(const char *proname)
00614 {
00615 const FmgrBuiltin *fbp = fmgr_lookupByName(proname);
00616
00617 if (fbp == NULL)
00618 return InvalidOid;
00619 return fbp->foid;
00620 }
00621
00622
00623
00624
00625
00626 static Datum
00627 fmgr_oldstyle(PG_FUNCTION_ARGS)
00628 {
00629 Oldstyle_fnextra *fnextra;
00630 int n_arguments = fcinfo->nargs;
00631 int i;
00632 bool isnull;
00633 func_ptr user_fn;
00634 char *returnValue;
00635
00636 if (fcinfo->flinfo == NULL || fcinfo->flinfo->fn_extra == NULL)
00637 elog(ERROR, "fmgr_oldstyle received NULL pointer");
00638 fnextra = (Oldstyle_fnextra *) fcinfo->flinfo->fn_extra;
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 isnull = false;
00650 for (i = 0; i < n_arguments; i++)
00651 {
00652 if (PG_ARGISNULL(i))
00653 isnull = true;
00654 else if (fnextra->arg_toastable[i])
00655 fcinfo->arg[i] = PointerGetDatum(PG_DETOAST_DATUM(fcinfo->arg[i]));
00656 }
00657 fcinfo->isnull = isnull;
00658
00659 user_fn = fnextra->func;
00660
00661 switch (n_arguments)
00662 {
00663 case 0:
00664 returnValue = (char *) (*user_fn) ();
00665 break;
00666 case 1:
00667
00668
00669
00670
00671
00672
00673 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00674 &fcinfo->isnull);
00675 break;
00676 case 2:
00677 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00678 fcinfo->arg[1]);
00679 break;
00680 case 3:
00681 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00682 fcinfo->arg[1],
00683 fcinfo->arg[2]);
00684 break;
00685 case 4:
00686 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00687 fcinfo->arg[1],
00688 fcinfo->arg[2],
00689 fcinfo->arg[3]);
00690 break;
00691 case 5:
00692 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00693 fcinfo->arg[1],
00694 fcinfo->arg[2],
00695 fcinfo->arg[3],
00696 fcinfo->arg[4]);
00697 break;
00698 case 6:
00699 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00700 fcinfo->arg[1],
00701 fcinfo->arg[2],
00702 fcinfo->arg[3],
00703 fcinfo->arg[4],
00704 fcinfo->arg[5]);
00705 break;
00706 case 7:
00707 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00708 fcinfo->arg[1],
00709 fcinfo->arg[2],
00710 fcinfo->arg[3],
00711 fcinfo->arg[4],
00712 fcinfo->arg[5],
00713 fcinfo->arg[6]);
00714 break;
00715 case 8:
00716 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00717 fcinfo->arg[1],
00718 fcinfo->arg[2],
00719 fcinfo->arg[3],
00720 fcinfo->arg[4],
00721 fcinfo->arg[5],
00722 fcinfo->arg[6],
00723 fcinfo->arg[7]);
00724 break;
00725 case 9:
00726 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00727 fcinfo->arg[1],
00728 fcinfo->arg[2],
00729 fcinfo->arg[3],
00730 fcinfo->arg[4],
00731 fcinfo->arg[5],
00732 fcinfo->arg[6],
00733 fcinfo->arg[7],
00734 fcinfo->arg[8]);
00735 break;
00736 case 10:
00737 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00738 fcinfo->arg[1],
00739 fcinfo->arg[2],
00740 fcinfo->arg[3],
00741 fcinfo->arg[4],
00742 fcinfo->arg[5],
00743 fcinfo->arg[6],
00744 fcinfo->arg[7],
00745 fcinfo->arg[8],
00746 fcinfo->arg[9]);
00747 break;
00748 case 11:
00749 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00750 fcinfo->arg[1],
00751 fcinfo->arg[2],
00752 fcinfo->arg[3],
00753 fcinfo->arg[4],
00754 fcinfo->arg[5],
00755 fcinfo->arg[6],
00756 fcinfo->arg[7],
00757 fcinfo->arg[8],
00758 fcinfo->arg[9],
00759 fcinfo->arg[10]);
00760 break;
00761 case 12:
00762 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00763 fcinfo->arg[1],
00764 fcinfo->arg[2],
00765 fcinfo->arg[3],
00766 fcinfo->arg[4],
00767 fcinfo->arg[5],
00768 fcinfo->arg[6],
00769 fcinfo->arg[7],
00770 fcinfo->arg[8],
00771 fcinfo->arg[9],
00772 fcinfo->arg[10],
00773 fcinfo->arg[11]);
00774 break;
00775 case 13:
00776 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00777 fcinfo->arg[1],
00778 fcinfo->arg[2],
00779 fcinfo->arg[3],
00780 fcinfo->arg[4],
00781 fcinfo->arg[5],
00782 fcinfo->arg[6],
00783 fcinfo->arg[7],
00784 fcinfo->arg[8],
00785 fcinfo->arg[9],
00786 fcinfo->arg[10],
00787 fcinfo->arg[11],
00788 fcinfo->arg[12]);
00789 break;
00790 case 14:
00791 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00792 fcinfo->arg[1],
00793 fcinfo->arg[2],
00794 fcinfo->arg[3],
00795 fcinfo->arg[4],
00796 fcinfo->arg[5],
00797 fcinfo->arg[6],
00798 fcinfo->arg[7],
00799 fcinfo->arg[8],
00800 fcinfo->arg[9],
00801 fcinfo->arg[10],
00802 fcinfo->arg[11],
00803 fcinfo->arg[12],
00804 fcinfo->arg[13]);
00805 break;
00806 case 15:
00807 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00808 fcinfo->arg[1],
00809 fcinfo->arg[2],
00810 fcinfo->arg[3],
00811 fcinfo->arg[4],
00812 fcinfo->arg[5],
00813 fcinfo->arg[6],
00814 fcinfo->arg[7],
00815 fcinfo->arg[8],
00816 fcinfo->arg[9],
00817 fcinfo->arg[10],
00818 fcinfo->arg[11],
00819 fcinfo->arg[12],
00820 fcinfo->arg[13],
00821 fcinfo->arg[14]);
00822 break;
00823 case 16:
00824 returnValue = (char *) (*user_fn) (fcinfo->arg[0],
00825 fcinfo->arg[1],
00826 fcinfo->arg[2],
00827 fcinfo->arg[3],
00828 fcinfo->arg[4],
00829 fcinfo->arg[5],
00830 fcinfo->arg[6],
00831 fcinfo->arg[7],
00832 fcinfo->arg[8],
00833 fcinfo->arg[9],
00834 fcinfo->arg[10],
00835 fcinfo->arg[11],
00836 fcinfo->arg[12],
00837 fcinfo->arg[13],
00838 fcinfo->arg[14],
00839 fcinfo->arg[15]);
00840 break;
00841 default:
00842
00843
00844
00845
00846
00847
00848
00849
00850 ereport(ERROR,
00851 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
00852 errmsg("function %u has too many arguments (%d, maximum is %d)",
00853 fcinfo->flinfo->fn_oid, n_arguments, 16)));
00854 returnValue = NULL;
00855 break;
00856 }
00857
00858 return PointerGetDatum(returnValue);
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868 struct fmgr_security_definer_cache
00869 {
00870 FmgrInfo flinfo;
00871 Oid userid;
00872 ArrayType *proconfig;
00873 Datum arg;
00874 };
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 static Datum
00887 fmgr_security_definer(PG_FUNCTION_ARGS)
00888 {
00889 Datum result;
00890 struct fmgr_security_definer_cache *volatile fcache;
00891 FmgrInfo *save_flinfo;
00892 Oid save_userid;
00893 int save_sec_context;
00894 volatile int save_nestlevel;
00895 PgStat_FunctionCallUsage fcusage;
00896
00897 if (!fcinfo->flinfo->fn_extra)
00898 {
00899 HeapTuple tuple;
00900 Form_pg_proc procedureStruct;
00901 Datum datum;
00902 bool isnull;
00903 MemoryContext oldcxt;
00904
00905 fcache = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
00906 sizeof(*fcache));
00907
00908 fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo,
00909 fcinfo->flinfo->fn_mcxt, true);
00910 fcache->flinfo.fn_expr = fcinfo->flinfo->fn_expr;
00911
00912 tuple = SearchSysCache1(PROCOID,
00913 ObjectIdGetDatum(fcinfo->flinfo->fn_oid));
00914 if (!HeapTupleIsValid(tuple))
00915 elog(ERROR, "cache lookup failed for function %u",
00916 fcinfo->flinfo->fn_oid);
00917 procedureStruct = (Form_pg_proc) GETSTRUCT(tuple);
00918
00919 if (procedureStruct->prosecdef)
00920 fcache->userid = procedureStruct->proowner;
00921
00922 datum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proconfig,
00923 &isnull);
00924 if (!isnull)
00925 {
00926 oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
00927 fcache->proconfig = DatumGetArrayTypePCopy(datum);
00928 MemoryContextSwitchTo(oldcxt);
00929 }
00930
00931 ReleaseSysCache(tuple);
00932
00933 fcinfo->flinfo->fn_extra = fcache;
00934 }
00935 else
00936 fcache = fcinfo->flinfo->fn_extra;
00937
00938
00939 GetUserIdAndSecContext(&save_userid, &save_sec_context);
00940 if (fcache->proconfig)
00941 save_nestlevel = NewGUCNestLevel();
00942 else
00943 save_nestlevel = 0;
00944
00945 if (OidIsValid(fcache->userid))
00946 SetUserIdAndSecContext(fcache->userid,
00947 save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
00948
00949 if (fcache->proconfig)
00950 {
00951 ProcessGUCArray(fcache->proconfig,
00952 (superuser() ? PGC_SUSET : PGC_USERSET),
00953 PGC_S_SESSION,
00954 GUC_ACTION_SAVE);
00955 }
00956
00957
00958 if (fmgr_hook)
00959 (*fmgr_hook) (FHET_START, &fcache->flinfo, &fcache->arg);
00960
00961
00962
00963
00964
00965
00966 save_flinfo = fcinfo->flinfo;
00967
00968 PG_TRY();
00969 {
00970 fcinfo->flinfo = &fcache->flinfo;
00971
00972
00973 pgstat_init_function_usage(fcinfo, &fcusage);
00974
00975 result = FunctionCallInvoke(fcinfo);
00976
00977
00978
00979
00980
00981 pgstat_end_function_usage(&fcusage,
00982 (fcinfo->resultinfo == NULL ||
00983 !IsA(fcinfo->resultinfo, ReturnSetInfo) ||
00984 ((ReturnSetInfo *) fcinfo->resultinfo)->isDone != ExprMultipleResult));
00985 }
00986 PG_CATCH();
00987 {
00988 fcinfo->flinfo = save_flinfo;
00989 if (fmgr_hook)
00990 (*fmgr_hook) (FHET_ABORT, &fcache->flinfo, &fcache->arg);
00991 PG_RE_THROW();
00992 }
00993 PG_END_TRY();
00994
00995 fcinfo->flinfo = save_flinfo;
00996
00997 if (fcache->proconfig)
00998 AtEOXact_GUC(true, save_nestlevel);
00999 if (OidIsValid(fcache->userid))
01000 SetUserIdAndSecContext(save_userid, save_sec_context);
01001 if (fmgr_hook)
01002 (*fmgr_hook) (FHET_END, &fcache->flinfo, &fcache->arg);
01003
01004 return result;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 Datum
01020 DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
01021 {
01022 FunctionCallInfoData fcinfo;
01023 Datum result;
01024
01025 InitFunctionCallInfoData(fcinfo, NULL, 1, collation, NULL, NULL);
01026
01027 fcinfo.arg[0] = arg1;
01028 fcinfo.argnull[0] = false;
01029
01030 result = (*func) (&fcinfo);
01031
01032
01033 if (fcinfo.isnull)
01034 elog(ERROR, "function %p returned NULL", (void *) func);
01035
01036 return result;
01037 }
01038
01039 Datum
01040 DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
01041 {
01042 FunctionCallInfoData fcinfo;
01043 Datum result;
01044
01045 InitFunctionCallInfoData(fcinfo, NULL, 2, collation, NULL, NULL);
01046
01047 fcinfo.arg[0] = arg1;
01048 fcinfo.arg[1] = arg2;
01049 fcinfo.argnull[0] = false;
01050 fcinfo.argnull[1] = false;
01051
01052 result = (*func) (&fcinfo);
01053
01054
01055 if (fcinfo.isnull)
01056 elog(ERROR, "function %p returned NULL", (void *) func);
01057
01058 return result;
01059 }
01060
01061 Datum
01062 DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
01063 Datum arg3)
01064 {
01065 FunctionCallInfoData fcinfo;
01066 Datum result;
01067
01068 InitFunctionCallInfoData(fcinfo, NULL, 3, collation, NULL, NULL);
01069
01070 fcinfo.arg[0] = arg1;
01071 fcinfo.arg[1] = arg2;
01072 fcinfo.arg[2] = arg3;
01073 fcinfo.argnull[0] = false;
01074 fcinfo.argnull[1] = false;
01075 fcinfo.argnull[2] = false;
01076
01077 result = (*func) (&fcinfo);
01078
01079
01080 if (fcinfo.isnull)
01081 elog(ERROR, "function %p returned NULL", (void *) func);
01082
01083 return result;
01084 }
01085
01086 Datum
01087 DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
01088 Datum arg3, Datum arg4)
01089 {
01090 FunctionCallInfoData fcinfo;
01091 Datum result;
01092
01093 InitFunctionCallInfoData(fcinfo, NULL, 4, collation, NULL, NULL);
01094
01095 fcinfo.arg[0] = arg1;
01096 fcinfo.arg[1] = arg2;
01097 fcinfo.arg[2] = arg3;
01098 fcinfo.arg[3] = arg4;
01099 fcinfo.argnull[0] = false;
01100 fcinfo.argnull[1] = false;
01101 fcinfo.argnull[2] = false;
01102 fcinfo.argnull[3] = false;
01103
01104 result = (*func) (&fcinfo);
01105
01106
01107 if (fcinfo.isnull)
01108 elog(ERROR, "function %p returned NULL", (void *) func);
01109
01110 return result;
01111 }
01112
01113 Datum
01114 DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
01115 Datum arg3, Datum arg4, Datum arg5)
01116 {
01117 FunctionCallInfoData fcinfo;
01118 Datum result;
01119
01120 InitFunctionCallInfoData(fcinfo, NULL, 5, collation, NULL, NULL);
01121
01122 fcinfo.arg[0] = arg1;
01123 fcinfo.arg[1] = arg2;
01124 fcinfo.arg[2] = arg3;
01125 fcinfo.arg[3] = arg4;
01126 fcinfo.arg[4] = arg5;
01127 fcinfo.argnull[0] = false;
01128 fcinfo.argnull[1] = false;
01129 fcinfo.argnull[2] = false;
01130 fcinfo.argnull[3] = false;
01131 fcinfo.argnull[4] = false;
01132
01133 result = (*func) (&fcinfo);
01134
01135
01136 if (fcinfo.isnull)
01137 elog(ERROR, "function %p returned NULL", (void *) func);
01138
01139 return result;
01140 }
01141
01142 Datum
01143 DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
01144 Datum arg3, Datum arg4, Datum arg5,
01145 Datum arg6)
01146 {
01147 FunctionCallInfoData fcinfo;
01148 Datum result;
01149
01150 InitFunctionCallInfoData(fcinfo, NULL, 6, collation, NULL, NULL);
01151
01152 fcinfo.arg[0] = arg1;
01153 fcinfo.arg[1] = arg2;
01154 fcinfo.arg[2] = arg3;
01155 fcinfo.arg[3] = arg4;
01156 fcinfo.arg[4] = arg5;
01157 fcinfo.arg[5] = arg6;
01158 fcinfo.argnull[0] = false;
01159 fcinfo.argnull[1] = false;
01160 fcinfo.argnull[2] = false;
01161 fcinfo.argnull[3] = false;
01162 fcinfo.argnull[4] = false;
01163 fcinfo.argnull[5] = false;
01164
01165 result = (*func) (&fcinfo);
01166
01167
01168 if (fcinfo.isnull)
01169 elog(ERROR, "function %p returned NULL", (void *) func);
01170
01171 return result;
01172 }
01173
01174 Datum
01175 DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
01176 Datum arg3, Datum arg4, Datum arg5,
01177 Datum arg6, Datum arg7)
01178 {
01179 FunctionCallInfoData fcinfo;
01180 Datum result;
01181
01182 InitFunctionCallInfoData(fcinfo, NULL, 7, collation, NULL, NULL);
01183
01184 fcinfo.arg[0] = arg1;
01185 fcinfo.arg[1] = arg2;
01186 fcinfo.arg[2] = arg3;
01187 fcinfo.arg[3] = arg4;
01188 fcinfo.arg[4] = arg5;
01189 fcinfo.arg[5] = arg6;
01190 fcinfo.arg[6] = arg7;
01191 fcinfo.argnull[0] = false;
01192 fcinfo.argnull[1] = false;
01193 fcinfo.argnull[2] = false;
01194 fcinfo.argnull[3] = false;
01195 fcinfo.argnull[4] = false;
01196 fcinfo.argnull[5] = false;
01197 fcinfo.argnull[6] = false;
01198
01199 result = (*func) (&fcinfo);
01200
01201
01202 if (fcinfo.isnull)
01203 elog(ERROR, "function %p returned NULL", (void *) func);
01204
01205 return result;
01206 }
01207
01208 Datum
01209 DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
01210 Datum arg3, Datum arg4, Datum arg5,
01211 Datum arg6, Datum arg7, Datum arg8)
01212 {
01213 FunctionCallInfoData fcinfo;
01214 Datum result;
01215
01216 InitFunctionCallInfoData(fcinfo, NULL, 8, collation, NULL, NULL);
01217
01218 fcinfo.arg[0] = arg1;
01219 fcinfo.arg[1] = arg2;
01220 fcinfo.arg[2] = arg3;
01221 fcinfo.arg[3] = arg4;
01222 fcinfo.arg[4] = arg5;
01223 fcinfo.arg[5] = arg6;
01224 fcinfo.arg[6] = arg7;
01225 fcinfo.arg[7] = arg8;
01226 fcinfo.argnull[0] = false;
01227 fcinfo.argnull[1] = false;
01228 fcinfo.argnull[2] = false;
01229 fcinfo.argnull[3] = false;
01230 fcinfo.argnull[4] = false;
01231 fcinfo.argnull[5] = false;
01232 fcinfo.argnull[6] = false;
01233 fcinfo.argnull[7] = false;
01234
01235 result = (*func) (&fcinfo);
01236
01237
01238 if (fcinfo.isnull)
01239 elog(ERROR, "function %p returned NULL", (void *) func);
01240
01241 return result;
01242 }
01243
01244 Datum
01245 DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
01246 Datum arg3, Datum arg4, Datum arg5,
01247 Datum arg6, Datum arg7, Datum arg8,
01248 Datum arg9)
01249 {
01250 FunctionCallInfoData fcinfo;
01251 Datum result;
01252
01253 InitFunctionCallInfoData(fcinfo, NULL, 9, collation, NULL, NULL);
01254
01255 fcinfo.arg[0] = arg1;
01256 fcinfo.arg[1] = arg2;
01257 fcinfo.arg[2] = arg3;
01258 fcinfo.arg[3] = arg4;
01259 fcinfo.arg[4] = arg5;
01260 fcinfo.arg[5] = arg6;
01261 fcinfo.arg[6] = arg7;
01262 fcinfo.arg[7] = arg8;
01263 fcinfo.arg[8] = arg9;
01264 fcinfo.argnull[0] = false;
01265 fcinfo.argnull[1] = false;
01266 fcinfo.argnull[2] = false;
01267 fcinfo.argnull[3] = false;
01268 fcinfo.argnull[4] = false;
01269 fcinfo.argnull[5] = false;
01270 fcinfo.argnull[6] = false;
01271 fcinfo.argnull[7] = false;
01272 fcinfo.argnull[8] = false;
01273
01274 result = (*func) (&fcinfo);
01275
01276
01277 if (fcinfo.isnull)
01278 elog(ERROR, "function %p returned NULL", (void *) func);
01279
01280 return result;
01281 }
01282
01283
01284
01285
01286
01287
01288
01289 Datum
01290 FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
01291 {
01292 FunctionCallInfoData fcinfo;
01293 Datum result;
01294
01295 InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
01296
01297 fcinfo.arg[0] = arg1;
01298 fcinfo.argnull[0] = false;
01299
01300 result = FunctionCallInvoke(&fcinfo);
01301
01302
01303 if (fcinfo.isnull)
01304 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01305
01306 return result;
01307 }
01308
01309 Datum
01310 FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
01311 {
01312
01313
01314
01315
01316 FunctionCallInfoData fcinfo;
01317 Datum result;
01318
01319 InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
01320
01321 fcinfo.arg[0] = arg1;
01322 fcinfo.arg[1] = arg2;
01323 fcinfo.argnull[0] = false;
01324 fcinfo.argnull[1] = false;
01325
01326 result = FunctionCallInvoke(&fcinfo);
01327
01328
01329 if (fcinfo.isnull)
01330 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01331
01332 return result;
01333 }
01334
01335 Datum
01336 FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
01337 Datum arg3)
01338 {
01339 FunctionCallInfoData fcinfo;
01340 Datum result;
01341
01342 InitFunctionCallInfoData(fcinfo, flinfo, 3, collation, NULL, NULL);
01343
01344 fcinfo.arg[0] = arg1;
01345 fcinfo.arg[1] = arg2;
01346 fcinfo.arg[2] = arg3;
01347 fcinfo.argnull[0] = false;
01348 fcinfo.argnull[1] = false;
01349 fcinfo.argnull[2] = false;
01350
01351 result = FunctionCallInvoke(&fcinfo);
01352
01353
01354 if (fcinfo.isnull)
01355 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01356
01357 return result;
01358 }
01359
01360 Datum
01361 FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
01362 Datum arg3, Datum arg4)
01363 {
01364 FunctionCallInfoData fcinfo;
01365 Datum result;
01366
01367 InitFunctionCallInfoData(fcinfo, flinfo, 4, collation, NULL, NULL);
01368
01369 fcinfo.arg[0] = arg1;
01370 fcinfo.arg[1] = arg2;
01371 fcinfo.arg[2] = arg3;
01372 fcinfo.arg[3] = arg4;
01373 fcinfo.argnull[0] = false;
01374 fcinfo.argnull[1] = false;
01375 fcinfo.argnull[2] = false;
01376 fcinfo.argnull[3] = false;
01377
01378 result = FunctionCallInvoke(&fcinfo);
01379
01380
01381 if (fcinfo.isnull)
01382 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01383
01384 return result;
01385 }
01386
01387 Datum
01388 FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
01389 Datum arg3, Datum arg4, Datum arg5)
01390 {
01391 FunctionCallInfoData fcinfo;
01392 Datum result;
01393
01394 InitFunctionCallInfoData(fcinfo, flinfo, 5, collation, NULL, NULL);
01395
01396 fcinfo.arg[0] = arg1;
01397 fcinfo.arg[1] = arg2;
01398 fcinfo.arg[2] = arg3;
01399 fcinfo.arg[3] = arg4;
01400 fcinfo.arg[4] = arg5;
01401 fcinfo.argnull[0] = false;
01402 fcinfo.argnull[1] = false;
01403 fcinfo.argnull[2] = false;
01404 fcinfo.argnull[3] = false;
01405 fcinfo.argnull[4] = false;
01406
01407 result = FunctionCallInvoke(&fcinfo);
01408
01409
01410 if (fcinfo.isnull)
01411 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01412
01413 return result;
01414 }
01415
01416 Datum
01417 FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
01418 Datum arg3, Datum arg4, Datum arg5,
01419 Datum arg6)
01420 {
01421 FunctionCallInfoData fcinfo;
01422 Datum result;
01423
01424 InitFunctionCallInfoData(fcinfo, flinfo, 6, collation, NULL, NULL);
01425
01426 fcinfo.arg[0] = arg1;
01427 fcinfo.arg[1] = arg2;
01428 fcinfo.arg[2] = arg3;
01429 fcinfo.arg[3] = arg4;
01430 fcinfo.arg[4] = arg5;
01431 fcinfo.arg[5] = arg6;
01432 fcinfo.argnull[0] = false;
01433 fcinfo.argnull[1] = false;
01434 fcinfo.argnull[2] = false;
01435 fcinfo.argnull[3] = false;
01436 fcinfo.argnull[4] = false;
01437 fcinfo.argnull[5] = false;
01438
01439 result = FunctionCallInvoke(&fcinfo);
01440
01441
01442 if (fcinfo.isnull)
01443 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01444
01445 return result;
01446 }
01447
01448 Datum
01449 FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
01450 Datum arg3, Datum arg4, Datum arg5,
01451 Datum arg6, Datum arg7)
01452 {
01453 FunctionCallInfoData fcinfo;
01454 Datum result;
01455
01456 InitFunctionCallInfoData(fcinfo, flinfo, 7, collation, NULL, NULL);
01457
01458 fcinfo.arg[0] = arg1;
01459 fcinfo.arg[1] = arg2;
01460 fcinfo.arg[2] = arg3;
01461 fcinfo.arg[3] = arg4;
01462 fcinfo.arg[4] = arg5;
01463 fcinfo.arg[5] = arg6;
01464 fcinfo.arg[6] = arg7;
01465 fcinfo.argnull[0] = false;
01466 fcinfo.argnull[1] = false;
01467 fcinfo.argnull[2] = false;
01468 fcinfo.argnull[3] = false;
01469 fcinfo.argnull[4] = false;
01470 fcinfo.argnull[5] = false;
01471 fcinfo.argnull[6] = false;
01472
01473 result = FunctionCallInvoke(&fcinfo);
01474
01475
01476 if (fcinfo.isnull)
01477 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01478
01479 return result;
01480 }
01481
01482 Datum
01483 FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
01484 Datum arg3, Datum arg4, Datum arg5,
01485 Datum arg6, Datum arg7, Datum arg8)
01486 {
01487 FunctionCallInfoData fcinfo;
01488 Datum result;
01489
01490 InitFunctionCallInfoData(fcinfo, flinfo, 8, collation, NULL, NULL);
01491
01492 fcinfo.arg[0] = arg1;
01493 fcinfo.arg[1] = arg2;
01494 fcinfo.arg[2] = arg3;
01495 fcinfo.arg[3] = arg4;
01496 fcinfo.arg[4] = arg5;
01497 fcinfo.arg[5] = arg6;
01498 fcinfo.arg[6] = arg7;
01499 fcinfo.arg[7] = arg8;
01500 fcinfo.argnull[0] = false;
01501 fcinfo.argnull[1] = false;
01502 fcinfo.argnull[2] = false;
01503 fcinfo.argnull[3] = false;
01504 fcinfo.argnull[4] = false;
01505 fcinfo.argnull[5] = false;
01506 fcinfo.argnull[6] = false;
01507 fcinfo.argnull[7] = false;
01508
01509 result = FunctionCallInvoke(&fcinfo);
01510
01511
01512 if (fcinfo.isnull)
01513 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01514
01515 return result;
01516 }
01517
01518 Datum
01519 FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
01520 Datum arg3, Datum arg4, Datum arg5,
01521 Datum arg6, Datum arg7, Datum arg8,
01522 Datum arg9)
01523 {
01524 FunctionCallInfoData fcinfo;
01525 Datum result;
01526
01527 InitFunctionCallInfoData(fcinfo, flinfo, 9, collation, NULL, NULL);
01528
01529 fcinfo.arg[0] = arg1;
01530 fcinfo.arg[1] = arg2;
01531 fcinfo.arg[2] = arg3;
01532 fcinfo.arg[3] = arg4;
01533 fcinfo.arg[4] = arg5;
01534 fcinfo.arg[5] = arg6;
01535 fcinfo.arg[6] = arg7;
01536 fcinfo.arg[7] = arg8;
01537 fcinfo.arg[8] = arg9;
01538 fcinfo.argnull[0] = false;
01539 fcinfo.argnull[1] = false;
01540 fcinfo.argnull[2] = false;
01541 fcinfo.argnull[3] = false;
01542 fcinfo.argnull[4] = false;
01543 fcinfo.argnull[5] = false;
01544 fcinfo.argnull[6] = false;
01545 fcinfo.argnull[7] = false;
01546 fcinfo.argnull[8] = false;
01547
01548 result = FunctionCallInvoke(&fcinfo);
01549
01550
01551 if (fcinfo.isnull)
01552 elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
01553
01554 return result;
01555 }
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565 Datum
01566 OidFunctionCall0Coll(Oid functionId, Oid collation)
01567 {
01568 FmgrInfo flinfo;
01569 FunctionCallInfoData fcinfo;
01570 Datum result;
01571
01572 fmgr_info(functionId, &flinfo);
01573
01574 InitFunctionCallInfoData(fcinfo, &flinfo, 0, collation, NULL, NULL);
01575
01576 result = FunctionCallInvoke(&fcinfo);
01577
01578
01579 if (fcinfo.isnull)
01580 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01581
01582 return result;
01583 }
01584
01585 Datum
01586 OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
01587 {
01588 FmgrInfo flinfo;
01589 FunctionCallInfoData fcinfo;
01590 Datum result;
01591
01592 fmgr_info(functionId, &flinfo);
01593
01594 InitFunctionCallInfoData(fcinfo, &flinfo, 1, collation, NULL, NULL);
01595
01596 fcinfo.arg[0] = arg1;
01597 fcinfo.argnull[0] = false;
01598
01599 result = FunctionCallInvoke(&fcinfo);
01600
01601
01602 if (fcinfo.isnull)
01603 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01604
01605 return result;
01606 }
01607
01608 Datum
01609 OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
01610 {
01611 FmgrInfo flinfo;
01612 FunctionCallInfoData fcinfo;
01613 Datum result;
01614
01615 fmgr_info(functionId, &flinfo);
01616
01617 InitFunctionCallInfoData(fcinfo, &flinfo, 2, collation, NULL, NULL);
01618
01619 fcinfo.arg[0] = arg1;
01620 fcinfo.arg[1] = arg2;
01621 fcinfo.argnull[0] = false;
01622 fcinfo.argnull[1] = false;
01623
01624 result = FunctionCallInvoke(&fcinfo);
01625
01626
01627 if (fcinfo.isnull)
01628 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01629
01630 return result;
01631 }
01632
01633 Datum
01634 OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
01635 Datum arg3)
01636 {
01637 FmgrInfo flinfo;
01638 FunctionCallInfoData fcinfo;
01639 Datum result;
01640
01641 fmgr_info(functionId, &flinfo);
01642
01643 InitFunctionCallInfoData(fcinfo, &flinfo, 3, collation, NULL, NULL);
01644
01645 fcinfo.arg[0] = arg1;
01646 fcinfo.arg[1] = arg2;
01647 fcinfo.arg[2] = arg3;
01648 fcinfo.argnull[0] = false;
01649 fcinfo.argnull[1] = false;
01650 fcinfo.argnull[2] = false;
01651
01652 result = FunctionCallInvoke(&fcinfo);
01653
01654
01655 if (fcinfo.isnull)
01656 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01657
01658 return result;
01659 }
01660
01661 Datum
01662 OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
01663 Datum arg3, Datum arg4)
01664 {
01665 FmgrInfo flinfo;
01666 FunctionCallInfoData fcinfo;
01667 Datum result;
01668
01669 fmgr_info(functionId, &flinfo);
01670
01671 InitFunctionCallInfoData(fcinfo, &flinfo, 4, collation, NULL, NULL);
01672
01673 fcinfo.arg[0] = arg1;
01674 fcinfo.arg[1] = arg2;
01675 fcinfo.arg[2] = arg3;
01676 fcinfo.arg[3] = arg4;
01677 fcinfo.argnull[0] = false;
01678 fcinfo.argnull[1] = false;
01679 fcinfo.argnull[2] = false;
01680 fcinfo.argnull[3] = false;
01681
01682 result = FunctionCallInvoke(&fcinfo);
01683
01684
01685 if (fcinfo.isnull)
01686 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01687
01688 return result;
01689 }
01690
01691 Datum
01692 OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
01693 Datum arg3, Datum arg4, Datum arg5)
01694 {
01695 FmgrInfo flinfo;
01696 FunctionCallInfoData fcinfo;
01697 Datum result;
01698
01699 fmgr_info(functionId, &flinfo);
01700
01701 InitFunctionCallInfoData(fcinfo, &flinfo, 5, collation, NULL, NULL);
01702
01703 fcinfo.arg[0] = arg1;
01704 fcinfo.arg[1] = arg2;
01705 fcinfo.arg[2] = arg3;
01706 fcinfo.arg[3] = arg4;
01707 fcinfo.arg[4] = arg5;
01708 fcinfo.argnull[0] = false;
01709 fcinfo.argnull[1] = false;
01710 fcinfo.argnull[2] = false;
01711 fcinfo.argnull[3] = false;
01712 fcinfo.argnull[4] = false;
01713
01714 result = FunctionCallInvoke(&fcinfo);
01715
01716
01717 if (fcinfo.isnull)
01718 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01719
01720 return result;
01721 }
01722
01723 Datum
01724 OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
01725 Datum arg3, Datum arg4, Datum arg5,
01726 Datum arg6)
01727 {
01728 FmgrInfo flinfo;
01729 FunctionCallInfoData fcinfo;
01730 Datum result;
01731
01732 fmgr_info(functionId, &flinfo);
01733
01734 InitFunctionCallInfoData(fcinfo, &flinfo, 6, collation, NULL, NULL);
01735
01736 fcinfo.arg[0] = arg1;
01737 fcinfo.arg[1] = arg2;
01738 fcinfo.arg[2] = arg3;
01739 fcinfo.arg[3] = arg4;
01740 fcinfo.arg[4] = arg5;
01741 fcinfo.arg[5] = arg6;
01742 fcinfo.argnull[0] = false;
01743 fcinfo.argnull[1] = false;
01744 fcinfo.argnull[2] = false;
01745 fcinfo.argnull[3] = false;
01746 fcinfo.argnull[4] = false;
01747 fcinfo.argnull[5] = false;
01748
01749 result = FunctionCallInvoke(&fcinfo);
01750
01751
01752 if (fcinfo.isnull)
01753 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01754
01755 return result;
01756 }
01757
01758 Datum
01759 OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
01760 Datum arg3, Datum arg4, Datum arg5,
01761 Datum arg6, Datum arg7)
01762 {
01763 FmgrInfo flinfo;
01764 FunctionCallInfoData fcinfo;
01765 Datum result;
01766
01767 fmgr_info(functionId, &flinfo);
01768
01769 InitFunctionCallInfoData(fcinfo, &flinfo, 7, collation, NULL, NULL);
01770
01771 fcinfo.arg[0] = arg1;
01772 fcinfo.arg[1] = arg2;
01773 fcinfo.arg[2] = arg3;
01774 fcinfo.arg[3] = arg4;
01775 fcinfo.arg[4] = arg5;
01776 fcinfo.arg[5] = arg6;
01777 fcinfo.arg[6] = arg7;
01778 fcinfo.argnull[0] = false;
01779 fcinfo.argnull[1] = false;
01780 fcinfo.argnull[2] = false;
01781 fcinfo.argnull[3] = false;
01782 fcinfo.argnull[4] = false;
01783 fcinfo.argnull[5] = false;
01784 fcinfo.argnull[6] = false;
01785
01786 result = FunctionCallInvoke(&fcinfo);
01787
01788
01789 if (fcinfo.isnull)
01790 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01791
01792 return result;
01793 }
01794
01795 Datum
01796 OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
01797 Datum arg3, Datum arg4, Datum arg5,
01798 Datum arg6, Datum arg7, Datum arg8)
01799 {
01800 FmgrInfo flinfo;
01801 FunctionCallInfoData fcinfo;
01802 Datum result;
01803
01804 fmgr_info(functionId, &flinfo);
01805
01806 InitFunctionCallInfoData(fcinfo, &flinfo, 8, collation, NULL, NULL);
01807
01808 fcinfo.arg[0] = arg1;
01809 fcinfo.arg[1] = arg2;
01810 fcinfo.arg[2] = arg3;
01811 fcinfo.arg[3] = arg4;
01812 fcinfo.arg[4] = arg5;
01813 fcinfo.arg[5] = arg6;
01814 fcinfo.arg[6] = arg7;
01815 fcinfo.arg[7] = arg8;
01816 fcinfo.argnull[0] = false;
01817 fcinfo.argnull[1] = false;
01818 fcinfo.argnull[2] = false;
01819 fcinfo.argnull[3] = false;
01820 fcinfo.argnull[4] = false;
01821 fcinfo.argnull[5] = false;
01822 fcinfo.argnull[6] = false;
01823 fcinfo.argnull[7] = false;
01824
01825 result = FunctionCallInvoke(&fcinfo);
01826
01827
01828 if (fcinfo.isnull)
01829 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01830
01831 return result;
01832 }
01833
01834 Datum
01835 OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
01836 Datum arg3, Datum arg4, Datum arg5,
01837 Datum arg6, Datum arg7, Datum arg8,
01838 Datum arg9)
01839 {
01840 FmgrInfo flinfo;
01841 FunctionCallInfoData fcinfo;
01842 Datum result;
01843
01844 fmgr_info(functionId, &flinfo);
01845
01846 InitFunctionCallInfoData(fcinfo, &flinfo, 9, collation, NULL, NULL);
01847
01848 fcinfo.arg[0] = arg1;
01849 fcinfo.arg[1] = arg2;
01850 fcinfo.arg[2] = arg3;
01851 fcinfo.arg[3] = arg4;
01852 fcinfo.arg[4] = arg5;
01853 fcinfo.arg[5] = arg6;
01854 fcinfo.arg[6] = arg7;
01855 fcinfo.arg[7] = arg8;
01856 fcinfo.arg[8] = arg9;
01857 fcinfo.argnull[0] = false;
01858 fcinfo.argnull[1] = false;
01859 fcinfo.argnull[2] = false;
01860 fcinfo.argnull[3] = false;
01861 fcinfo.argnull[4] = false;
01862 fcinfo.argnull[5] = false;
01863 fcinfo.argnull[6] = false;
01864 fcinfo.argnull[7] = false;
01865 fcinfo.argnull[8] = false;
01866
01867 result = FunctionCallInvoke(&fcinfo);
01868
01869
01870 if (fcinfo.isnull)
01871 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
01872
01873 return result;
01874 }
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895 Datum
01896 InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
01897 {
01898 FunctionCallInfoData fcinfo;
01899 Datum result;
01900 bool pushed;
01901
01902 if (str == NULL && flinfo->fn_strict)
01903 return (Datum) 0;
01904
01905 pushed = SPI_push_conditional();
01906
01907 InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
01908
01909 fcinfo.arg[0] = CStringGetDatum(str);
01910 fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
01911 fcinfo.arg[2] = Int32GetDatum(typmod);
01912 fcinfo.argnull[0] = (str == NULL);
01913 fcinfo.argnull[1] = false;
01914 fcinfo.argnull[2] = false;
01915
01916 result = FunctionCallInvoke(&fcinfo);
01917
01918
01919 if (str == NULL)
01920 {
01921 if (!fcinfo.isnull)
01922 elog(ERROR, "input function %u returned non-NULL",
01923 fcinfo.flinfo->fn_oid);
01924 }
01925 else
01926 {
01927 if (fcinfo.isnull)
01928 elog(ERROR, "input function %u returned NULL",
01929 fcinfo.flinfo->fn_oid);
01930 }
01931
01932 SPI_pop_conditional(pushed);
01933
01934 return result;
01935 }
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945 char *
01946 OutputFunctionCall(FmgrInfo *flinfo, Datum val)
01947 {
01948 char *result;
01949 bool pushed;
01950
01951 pushed = SPI_push_conditional();
01952
01953 result = DatumGetCString(FunctionCall1(flinfo, val));
01954
01955 SPI_pop_conditional(pushed);
01956
01957 return result;
01958 }
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969 Datum
01970 ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
01971 Oid typioparam, int32 typmod)
01972 {
01973 FunctionCallInfoData fcinfo;
01974 Datum result;
01975 bool pushed;
01976
01977 if (buf == NULL && flinfo->fn_strict)
01978 return (Datum) 0;
01979
01980 pushed = SPI_push_conditional();
01981
01982 InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
01983
01984 fcinfo.arg[0] = PointerGetDatum(buf);
01985 fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
01986 fcinfo.arg[2] = Int32GetDatum(typmod);
01987 fcinfo.argnull[0] = (buf == NULL);
01988 fcinfo.argnull[1] = false;
01989 fcinfo.argnull[2] = false;
01990
01991 result = FunctionCallInvoke(&fcinfo);
01992
01993
01994 if (buf == NULL)
01995 {
01996 if (!fcinfo.isnull)
01997 elog(ERROR, "receive function %u returned non-NULL",
01998 fcinfo.flinfo->fn_oid);
01999 }
02000 else
02001 {
02002 if (fcinfo.isnull)
02003 elog(ERROR, "receive function %u returned NULL",
02004 fcinfo.flinfo->fn_oid);
02005 }
02006
02007 SPI_pop_conditional(pushed);
02008
02009 return result;
02010 }
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022 bytea *
02023 SendFunctionCall(FmgrInfo *flinfo, Datum val)
02024 {
02025 bytea *result;
02026 bool pushed;
02027
02028 pushed = SPI_push_conditional();
02029
02030 result = DatumGetByteaP(FunctionCall1(flinfo, val));
02031
02032 SPI_pop_conditional(pushed);
02033
02034 return result;
02035 }
02036
02037
02038
02039
02040
02041 Datum
02042 OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
02043 {
02044 FmgrInfo flinfo;
02045
02046 fmgr_info(functionId, &flinfo);
02047 return InputFunctionCall(&flinfo, str, typioparam, typmod);
02048 }
02049
02050 char *
02051 OidOutputFunctionCall(Oid functionId, Datum val)
02052 {
02053 FmgrInfo flinfo;
02054
02055 fmgr_info(functionId, &flinfo);
02056 return OutputFunctionCall(&flinfo, val);
02057 }
02058
02059 Datum
02060 OidReceiveFunctionCall(Oid functionId, StringInfo buf,
02061 Oid typioparam, int32 typmod)
02062 {
02063 FmgrInfo flinfo;
02064
02065 fmgr_info(functionId, &flinfo);
02066 return ReceiveFunctionCall(&flinfo, buf, typioparam, typmod);
02067 }
02068
02069 bytea *
02070 OidSendFunctionCall(Oid functionId, Datum val)
02071 {
02072 FmgrInfo flinfo;
02073
02074 fmgr_info(functionId, &flinfo);
02075 return SendFunctionCall(&flinfo, val);
02076 }
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090 char *
02091 fmgr(Oid procedureId,...)
02092 {
02093 FmgrInfo flinfo;
02094 FunctionCallInfoData fcinfo;
02095 int n_arguments;
02096 Datum result;
02097
02098 fmgr_info(procedureId, &flinfo);
02099
02100 MemSet(&fcinfo, 0, sizeof(fcinfo));
02101 fcinfo.flinfo = &flinfo;
02102 fcinfo.nargs = flinfo.fn_nargs;
02103 n_arguments = fcinfo.nargs;
02104
02105 if (n_arguments > 0)
02106 {
02107 va_list pvar;
02108 int i;
02109
02110 if (n_arguments > FUNC_MAX_ARGS)
02111 ereport(ERROR,
02112 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
02113 errmsg("function %u has too many arguments (%d, maximum is %d)",
02114 flinfo.fn_oid, n_arguments, FUNC_MAX_ARGS)));
02115 va_start(pvar, procedureId);
02116 for (i = 0; i < n_arguments; i++)
02117 fcinfo.arg[i] = PointerGetDatum(va_arg(pvar, char *));
02118 va_end(pvar);
02119 }
02120
02121 result = FunctionCallInvoke(&fcinfo);
02122
02123
02124 if (fcinfo.isnull)
02125 elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
02126
02127 return DatumGetPointer(result);
02128 }
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147 #ifndef USE_FLOAT8_BYVAL
02148
02149 Datum
02150 Int64GetDatum(int64 X)
02151 {
02152 int64 *retval = (int64 *) palloc(sizeof(int64));
02153
02154 *retval = X;
02155 return PointerGetDatum(retval);
02156 }
02157 #endif
02158
02159 Datum
02160 Float4GetDatum(float4 X)
02161 {
02162 #ifdef USE_FLOAT4_BYVAL
02163 union
02164 {
02165 float4 value;
02166 int32 retval;
02167 } myunion;
02168
02169 myunion.value = X;
02170 return SET_4_BYTES(myunion.retval);
02171 #else
02172 float4 *retval = (float4 *) palloc(sizeof(float4));
02173
02174 *retval = X;
02175 return PointerGetDatum(retval);
02176 #endif
02177 }
02178
02179 #ifdef USE_FLOAT4_BYVAL
02180
02181 float4
02182 DatumGetFloat4(Datum X)
02183 {
02184 union
02185 {
02186 int32 value;
02187 float4 retval;
02188 } myunion;
02189
02190 myunion.value = GET_4_BYTES(X);
02191 return myunion.retval;
02192 }
02193 #endif
02194
02195 Datum
02196 Float8GetDatum(float8 X)
02197 {
02198 #ifdef USE_FLOAT8_BYVAL
02199 union
02200 {
02201 float8 value;
02202 int64 retval;
02203 } myunion;
02204
02205 myunion.value = X;
02206 return SET_8_BYTES(myunion.retval);
02207 #else
02208 float8 *retval = (float8 *) palloc(sizeof(float8));
02209
02210 *retval = X;
02211 return PointerGetDatum(retval);
02212 #endif
02213 }
02214
02215 #ifdef USE_FLOAT8_BYVAL
02216
02217 float8
02218 DatumGetFloat8(Datum X)
02219 {
02220 union
02221 {
02222 int64 value;
02223 float8 retval;
02224 } myunion;
02225
02226 myunion.value = GET_8_BYTES(X);
02227 return myunion.retval;
02228 }
02229 #endif
02230
02231
02232
02233
02234
02235
02236
02237 struct varlena *
02238 pg_detoast_datum(struct varlena * datum)
02239 {
02240 if (VARATT_IS_EXTENDED(datum))
02241 return heap_tuple_untoast_attr(datum);
02242 else
02243 return datum;
02244 }
02245
02246 struct varlena *
02247 pg_detoast_datum_copy(struct varlena * datum)
02248 {
02249 if (VARATT_IS_EXTENDED(datum))
02250 return heap_tuple_untoast_attr(datum);
02251 else
02252 {
02253
02254 Size len = VARSIZE(datum);
02255 struct varlena *result = (struct varlena *) palloc(len);
02256
02257 memcpy(result, datum, len);
02258 return result;
02259 }
02260 }
02261
02262 struct varlena *
02263 pg_detoast_datum_slice(struct varlena * datum, int32 first, int32 count)
02264 {
02265
02266 return heap_tuple_untoast_attr_slice(datum, first, count);
02267 }
02268
02269 struct varlena *
02270 pg_detoast_datum_packed(struct varlena * datum)
02271 {
02272 if (VARATT_IS_COMPRESSED(datum) || VARATT_IS_EXTERNAL(datum))
02273 return heap_tuple_untoast_attr(datum);
02274 else
02275 return datum;
02276 }
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293 Oid
02294 get_fn_expr_rettype(FmgrInfo *flinfo)
02295 {
02296 Node *expr;
02297
02298
02299
02300
02301
02302 if (!flinfo || !flinfo->fn_expr)
02303 return InvalidOid;
02304
02305 expr = flinfo->fn_expr;
02306
02307 return exprType(expr);
02308 }
02309
02310
02311
02312
02313
02314
02315 Oid
02316 get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
02317 {
02318
02319
02320
02321
02322 if (!flinfo || !flinfo->fn_expr)
02323 return InvalidOid;
02324
02325 return get_call_expr_argtype(flinfo->fn_expr, argnum);
02326 }
02327
02328
02329
02330
02331
02332
02333
02334 Oid
02335 get_call_expr_argtype(Node *expr, int argnum)
02336 {
02337 List *args;
02338 Oid argtype;
02339
02340 if (expr == NULL)
02341 return InvalidOid;
02342
02343 if (IsA(expr, FuncExpr))
02344 args = ((FuncExpr *) expr)->args;
02345 else if (IsA(expr, OpExpr))
02346 args = ((OpExpr *) expr)->args;
02347 else if (IsA(expr, DistinctExpr))
02348 args = ((DistinctExpr *) expr)->args;
02349 else if (IsA(expr, ScalarArrayOpExpr))
02350 args = ((ScalarArrayOpExpr *) expr)->args;
02351 else if (IsA(expr, ArrayCoerceExpr))
02352 args = list_make1(((ArrayCoerceExpr *) expr)->arg);
02353 else if (IsA(expr, NullIfExpr))
02354 args = ((NullIfExpr *) expr)->args;
02355 else if (IsA(expr, WindowFunc))
02356 args = ((WindowFunc *) expr)->args;
02357 else
02358 return InvalidOid;
02359
02360 if (argnum < 0 || argnum >= list_length(args))
02361 return InvalidOid;
02362
02363 argtype = exprType((Node *) list_nth(args, argnum));
02364
02365
02366
02367
02368
02369
02370 if (IsA(expr, ScalarArrayOpExpr) &&
02371 argnum == 1)
02372 argtype = get_base_element_type(argtype);
02373 else if (IsA(expr, ArrayCoerceExpr) &&
02374 argnum == 0)
02375 argtype = get_base_element_type(argtype);
02376
02377 return argtype;
02378 }
02379
02380
02381
02382
02383
02384
02385
02386 bool
02387 get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
02388 {
02389
02390
02391
02392
02393 if (!flinfo || !flinfo->fn_expr)
02394 return false;
02395
02396 return get_call_expr_arg_stable(flinfo->fn_expr, argnum);
02397 }
02398
02399
02400
02401
02402
02403
02404
02405 bool
02406 get_call_expr_arg_stable(Node *expr, int argnum)
02407 {
02408 List *args;
02409 Node *arg;
02410
02411 if (expr == NULL)
02412 return false;
02413
02414 if (IsA(expr, FuncExpr))
02415 args = ((FuncExpr *) expr)->args;
02416 else if (IsA(expr, OpExpr))
02417 args = ((OpExpr *) expr)->args;
02418 else if (IsA(expr, DistinctExpr))
02419 args = ((DistinctExpr *) expr)->args;
02420 else if (IsA(expr, ScalarArrayOpExpr))
02421 args = ((ScalarArrayOpExpr *) expr)->args;
02422 else if (IsA(expr, ArrayCoerceExpr))
02423 args = list_make1(((ArrayCoerceExpr *) expr)->arg);
02424 else if (IsA(expr, NullIfExpr))
02425 args = ((NullIfExpr *) expr)->args;
02426 else if (IsA(expr, WindowFunc))
02427 args = ((WindowFunc *) expr)->args;
02428 else
02429 return false;
02430
02431 if (argnum < 0 || argnum >= list_length(args))
02432 return false;
02433
02434 arg = (Node *) list_nth(args, argnum);
02435
02436
02437
02438
02439
02440
02441 if (IsA(arg, Const))
02442 return true;
02443 if (IsA(arg, Param) &&
02444 ((Param *) arg)->paramkind == PARAM_EXTERN)
02445 return true;
02446
02447 return false;
02448 }
02449
02450
02451
02452
02453
02454
02455 bool
02456 get_fn_expr_variadic(FmgrInfo *flinfo)
02457 {
02458 Node *expr;
02459
02460
02461
02462
02463
02464 if (!flinfo || !flinfo->fn_expr)
02465 return false;
02466
02467 expr = flinfo->fn_expr;
02468
02469 if (IsA(expr, FuncExpr))
02470 return ((FuncExpr *) expr)->funcvariadic;
02471 else
02472 return false;
02473 }