1 /*-------------------------------------------------------------------------
2 *
3 * fmgr.c
4 * The Postgres function manager.
5 *
6 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/fmgr/fmgr.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16 #include "postgres.h"
17
18 #include "access/detoast.h"
19 #include "catalog/pg_language.h"
20 #include "catalog/pg_proc.h"
21 #include "catalog/pg_type.h"
22 #include "executor/functions.h"
23 #include "lib/stringinfo.h"
24 #include "miscadmin.h"
25 #include "nodes/makefuncs.h"
26 #include "nodes/nodeFuncs.h"
27 #include "pgstat.h"
28 #include "utils/acl.h"
29 #include "utils/builtins.h"
30 #include "utils/fmgrtab.h"
31 #include "utils/guc.h"
32 #include "utils/lsyscache.h"
33 #include "utils/syscache.h"
34
35 /*
36 * Hooks for function calls
37 */
38 PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook = NULL;
39 PGDLLIMPORT fmgr_hook_type fmgr_hook = NULL;
40
41 /*
42 * Hashtable for fast lookup of external C functions
43 */
44 typedef struct
45 {
46 /* fn_oid is the hash key and so must be first! */
47 Oid fn_oid; /* OID of an external C function */
48 TransactionId fn_xmin; /* for checking up-to-dateness */
49 ItemPointerData fn_tid;
50 PGFunction user_fn; /* the function's address */
51 const Pg_finfo_record *inforec; /* address of its info record */
52 } CFuncHashTabEntry;
53
54 static HTAB *CFuncHash = NULL;
55
56
57 static void fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
58 bool ignore_security);
59 static void fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
60 static void fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple);
61 static CFuncHashTabEntry *lookup_C_func(HeapTuple procedureTuple);
62 static void record_C_func(HeapTuple procedureTuple,
63 PGFunction user_fn, const Pg_finfo_record *inforec);
64
65 /* extern so it's callable via JIT */
66 extern Datum fmgr_security_definer(PG_FUNCTION_ARGS);
67
68
69 /*
70 * Lookup routines for builtin-function table. We can search by either Oid
71 * or name, but search by Oid is much faster.
72 */
73
74 static const FmgrBuiltin *
fmgr_isbuiltin(Oid id)75 fmgr_isbuiltin(Oid id)
76 {
77 uint16 index;
78
79 /* fast lookup only possible if original oid still assigned */
80 if (id > fmgr_last_builtin_oid)
81 return NULL;
82
83 /*
84 * Lookup function data. If there's a miss in that range it's likely a
85 * nonexistent function, returning NULL here will trigger an ERROR later.
86 */
87 index = fmgr_builtin_oid_index[id];
88 if (index == InvalidOidBuiltinMapping)
89 return NULL;
90
91 return &fmgr_builtins[index];
92 }
93
94 /*
95 * Lookup a builtin by name. Note there can be more than one entry in
96 * the array with the same name, but they should all point to the same
97 * routine.
98 */
99 static const FmgrBuiltin *
fmgr_lookupByName(const char * name)100 fmgr_lookupByName(const char *name)
101 {
102 int i;
103
104 for (i = 0; i < fmgr_nbuiltins; i++)
105 {
106 if (strcmp(name, fmgr_builtins[i].funcName) == 0)
107 return fmgr_builtins + i;
108 }
109 return NULL;
110 }
111
112 /*
113 * This routine fills a FmgrInfo struct, given the OID
114 * of the function to be called.
115 *
116 * The caller's CurrentMemoryContext is used as the fn_mcxt of the info
117 * struct; this means that any subsidiary data attached to the info struct
118 * (either by fmgr_info itself, or later on by a function call handler)
119 * will be allocated in that context. The caller must ensure that this
120 * context is at least as long-lived as the info struct itself. This is
121 * not a problem in typical cases where the info struct is on the stack or
122 * in freshly-palloc'd space. However, if one intends to store an info
123 * struct in a long-lived table, it's better to use fmgr_info_cxt.
124 */
125 void
fmgr_info(Oid functionId,FmgrInfo * finfo)126 fmgr_info(Oid functionId, FmgrInfo *finfo)
127 {
128 fmgr_info_cxt_security(functionId, finfo, CurrentMemoryContext, false);
129 }
130
131 /*
132 * Fill a FmgrInfo struct, specifying a memory context in which its
133 * subsidiary data should go.
134 */
135 void
fmgr_info_cxt(Oid functionId,FmgrInfo * finfo,MemoryContext mcxt)136 fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
137 {
138 fmgr_info_cxt_security(functionId, finfo, mcxt, false);
139 }
140
141 /*
142 * This one does the actual work. ignore_security is ordinarily false
143 * but is set to true when we need to avoid recursion.
144 */
145 static void
fmgr_info_cxt_security(Oid functionId,FmgrInfo * finfo,MemoryContext mcxt,bool ignore_security)146 fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
147 bool ignore_security)
148 {
149 const FmgrBuiltin *fbp;
150 HeapTuple procedureTuple;
151 Form_pg_proc procedureStruct;
152 Datum prosrcdatum;
153 bool isnull;
154 char *prosrc;
155
156 /*
157 * fn_oid *must* be filled in last. Some code assumes that if fn_oid is
158 * valid, the whole struct is valid. Some FmgrInfo struct's do survive
159 * elogs.
160 */
161 finfo->fn_oid = InvalidOid;
162 finfo->fn_extra = NULL;
163 finfo->fn_mcxt = mcxt;
164 finfo->fn_expr = NULL; /* caller may set this later */
165
166 if ((fbp = fmgr_isbuiltin(functionId)) != NULL)
167 {
168 /*
169 * Fast path for builtin functions: don't bother consulting pg_proc
170 */
171 finfo->fn_nargs = fbp->nargs;
172 finfo->fn_strict = fbp->strict;
173 finfo->fn_retset = fbp->retset;
174 finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
175 finfo->fn_addr = fbp->func;
176 finfo->fn_oid = functionId;
177 return;
178 }
179
180 /* Otherwise we need the pg_proc entry */
181 procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
182 if (!HeapTupleIsValid(procedureTuple))
183 elog(ERROR, "cache lookup failed for function %u", functionId);
184 procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
185
186 finfo->fn_nargs = procedureStruct->pronargs;
187 finfo->fn_strict = procedureStruct->proisstrict;
188 finfo->fn_retset = procedureStruct->proretset;
189
190 /*
191 * If it has prosecdef set, non-null proconfig, or if a plugin wants to
192 * hook function entry/exit, use fmgr_security_definer call handler ---
193 * unless we are being called again by fmgr_security_definer or
194 * fmgr_info_other_lang.
195 *
196 * When using fmgr_security_definer, function stats tracking is always
197 * disabled at the outer level, and instead we set the flag properly in
198 * fmgr_security_definer's private flinfo and implement the tracking
199 * inside fmgr_security_definer. This loses the ability to charge the
200 * overhead of fmgr_security_definer to the function, but gains the
201 * ability to set the track_functions GUC as a local GUC parameter of an
202 * interesting function and have the right things happen.
203 */
204 if (!ignore_security &&
205 (procedureStruct->prosecdef ||
206 !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig, NULL) ||
207 FmgrHookIsNeeded(functionId)))
208 {
209 finfo->fn_addr = fmgr_security_definer;
210 finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
211 finfo->fn_oid = functionId;
212 ReleaseSysCache(procedureTuple);
213 return;
214 }
215
216 switch (procedureStruct->prolang)
217 {
218 case INTERNALlanguageId:
219
220 /*
221 * For an ordinary builtin function, we should never get here
222 * because the fmgr_isbuiltin() search above will have succeeded.
223 * However, if the user has done a CREATE FUNCTION to create an
224 * alias for a builtin function, we can end up here. In that case
225 * we have to look up the function by name. The name of the
226 * internal function is stored in prosrc (it doesn't have to be
227 * the same as the name of the alias!)
228 */
229 prosrcdatum = SysCacheGetAttr(PROCOID, procedureTuple,
230 Anum_pg_proc_prosrc, &isnull);
231 if (isnull)
232 elog(ERROR, "null prosrc");
233 prosrc = TextDatumGetCString(prosrcdatum);
234 fbp = fmgr_lookupByName(prosrc);
235 if (fbp == NULL)
236 ereport(ERROR,
237 (errcode(ERRCODE_UNDEFINED_FUNCTION),
238 errmsg("internal function \"%s\" is not in internal lookup table",
239 prosrc)));
240 pfree(prosrc);
241 /* Should we check that nargs, strict, retset match the table? */
242 finfo->fn_addr = fbp->func;
243 /* note this policy is also assumed in fast path above */
244 finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
245 break;
246
247 case ClanguageId:
248 fmgr_info_C_lang(functionId, finfo, procedureTuple);
249 finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
250 break;
251
252 case SQLlanguageId:
253 finfo->fn_addr = fmgr_sql;
254 finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
255 break;
256
257 default:
258 fmgr_info_other_lang(functionId, finfo, procedureTuple);
259 finfo->fn_stats = TRACK_FUNC_OFF; /* ie, track if not OFF */
260 break;
261 }
262
263 finfo->fn_oid = functionId;
264 ReleaseSysCache(procedureTuple);
265 }
266
267 /*
268 * Return module and C function name providing implementation of functionId.
269 *
270 * If *mod == NULL and *fn == NULL, no C symbol is known to implement
271 * function.
272 *
273 * If *mod == NULL and *fn != NULL, the function is implemented by a symbol in
274 * the main binary.
275 *
276 * If *mod != NULL and *fn != NULL the function is implemented in an extension
277 * shared object.
278 *
279 * The returned module and function names are pstrdup'ed into the current
280 * memory context.
281 */
282 void
fmgr_symbol(Oid functionId,char ** mod,char ** fn)283 fmgr_symbol(Oid functionId, char **mod, char **fn)
284 {
285 HeapTuple procedureTuple;
286 Form_pg_proc procedureStruct;
287 bool isnull;
288 Datum prosrcattr;
289 Datum probinattr;
290
291 procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
292 if (!HeapTupleIsValid(procedureTuple))
293 elog(ERROR, "cache lookup failed for function %u", functionId);
294 procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
295
296 if (procedureStruct->prosecdef ||
297 !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig, NULL) ||
298 FmgrHookIsNeeded(functionId))
299 {
300 *mod = NULL; /* core binary */
301 *fn = pstrdup("fmgr_security_definer");
302 ReleaseSysCache(procedureTuple);
303 return;
304 }
305
306 /* see fmgr_info_cxt_security for the individual cases */
307 switch (procedureStruct->prolang)
308 {
309 case INTERNALlanguageId:
310 prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
311 Anum_pg_proc_prosrc, &isnull);
312 if (isnull)
313 elog(ERROR, "null prosrc");
314
315 *mod = NULL; /* core binary */
316 *fn = TextDatumGetCString(prosrcattr);
317 break;
318
319 case ClanguageId:
320 prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
321 Anum_pg_proc_prosrc, &isnull);
322 if (isnull)
323 elog(ERROR, "null prosrc for C function %u", functionId);
324
325 probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
326 Anum_pg_proc_probin, &isnull);
327 if (isnull)
328 elog(ERROR, "null probin for C function %u", functionId);
329
330 /*
331 * No need to check symbol presence / API version here, already
332 * checked in fmgr_info_cxt_security.
333 */
334 *mod = TextDatumGetCString(probinattr);
335 *fn = TextDatumGetCString(prosrcattr);
336 break;
337
338 case SQLlanguageId:
339 *mod = NULL; /* core binary */
340 *fn = pstrdup("fmgr_sql");
341 break;
342
343 default:
344 *mod = NULL;
345 *fn = NULL; /* unknown, pass pointer */
346 break;
347 }
348
349 ReleaseSysCache(procedureTuple);
350 }
351
352
353 /*
354 * Special fmgr_info processing for C-language functions. Note that
355 * finfo->fn_oid is not valid yet.
356 */
357 static void
fmgr_info_C_lang(Oid functionId,FmgrInfo * finfo,HeapTuple procedureTuple)358 fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
359 {
360 CFuncHashTabEntry *hashentry;
361 PGFunction user_fn;
362 const Pg_finfo_record *inforec;
363 bool isnull;
364
365 /*
366 * See if we have the function address cached already
367 */
368 hashentry = lookup_C_func(procedureTuple);
369 if (hashentry)
370 {
371 user_fn = hashentry->user_fn;
372 inforec = hashentry->inforec;
373 }
374 else
375 {
376 Datum prosrcattr,
377 probinattr;
378 char *prosrcstring,
379 *probinstring;
380 void *libraryhandle;
381
382 /*
383 * Get prosrc and probin strings (link symbol and library filename).
384 * While in general these columns might be null, that's not allowed
385 * for C-language functions.
386 */
387 prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
388 Anum_pg_proc_prosrc, &isnull);
389 if (isnull)
390 elog(ERROR, "null prosrc for C function %u", functionId);
391 prosrcstring = TextDatumGetCString(prosrcattr);
392
393 probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
394 Anum_pg_proc_probin, &isnull);
395 if (isnull)
396 elog(ERROR, "null probin for C function %u", functionId);
397 probinstring = TextDatumGetCString(probinattr);
398
399 /* Look up the function itself */
400 user_fn = load_external_function(probinstring, prosrcstring, true,
401 &libraryhandle);
402
403 /* Get the function information record (real or default) */
404 inforec = fetch_finfo_record(libraryhandle, prosrcstring);
405
406 /* Cache the addresses for later calls */
407 record_C_func(procedureTuple, user_fn, inforec);
408
409 pfree(prosrcstring);
410 pfree(probinstring);
411 }
412
413 switch (inforec->api_version)
414 {
415 case 1:
416 /* New style: call directly */
417 finfo->fn_addr = user_fn;
418 break;
419 default:
420 /* Shouldn't get here if fetch_finfo_record did its job */
421 elog(ERROR, "unrecognized function API version: %d",
422 inforec->api_version);
423 break;
424 }
425 }
426
427 /*
428 * Special fmgr_info processing for other-language functions. Note
429 * that finfo->fn_oid is not valid yet.
430 */
431 static void
fmgr_info_other_lang(Oid functionId,FmgrInfo * finfo,HeapTuple procedureTuple)432 fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
433 {
434 Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
435 Oid language = procedureStruct->prolang;
436 HeapTuple languageTuple;
437 Form_pg_language languageStruct;
438 FmgrInfo plfinfo;
439
440 languageTuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(language));
441 if (!HeapTupleIsValid(languageTuple))
442 elog(ERROR, "cache lookup failed for language %u", language);
443 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
444
445 /*
446 * Look up the language's call handler function, ignoring any attributes
447 * that would normally cause insertion of fmgr_security_definer. We need
448 * to get back a bare pointer to the actual C-language function.
449 */
450 fmgr_info_cxt_security(languageStruct->lanplcallfoid, &plfinfo,
451 CurrentMemoryContext, true);
452 finfo->fn_addr = plfinfo.fn_addr;
453
454 ReleaseSysCache(languageTuple);
455 }
456
457 /*
458 * Fetch and validate the information record for the given external function.
459 * The function is specified by a handle for the containing library
460 * (obtained from load_external_function) as well as the function name.
461 *
462 * If no info function exists for the given name an error is raised.
463 *
464 * This function is broken out of fmgr_info_C_lang so that fmgr_c_validator
465 * can validate the information record for a function not yet entered into
466 * pg_proc.
467 */
468 const Pg_finfo_record *
fetch_finfo_record(void * filehandle,const char * funcname)469 fetch_finfo_record(void *filehandle, const char *funcname)
470 {
471 char *infofuncname;
472 PGFInfoFunction infofunc;
473 const Pg_finfo_record *inforec;
474
475 infofuncname = psprintf("pg_finfo_%s", funcname);
476
477 /* Try to look up the info function */
478 infofunc = (PGFInfoFunction) lookup_external_function(filehandle,
479 infofuncname);
480 if (infofunc == NULL)
481 {
482 ereport(ERROR,
483 (errcode(ERRCODE_UNDEFINED_FUNCTION),
484 errmsg("could not find function information for function \"%s\"",
485 funcname),
486 errhint("SQL-callable functions need an accompanying PG_FUNCTION_INFO_V1(funcname).")));
487 return NULL; /* silence compiler */
488 }
489
490 /* Found, so call it */
491 inforec = (*infofunc) ();
492
493 /* Validate result as best we can */
494 if (inforec == NULL)
495 elog(ERROR, "null result from info function \"%s\"", infofuncname);
496 switch (inforec->api_version)
497 {
498 case 1:
499 /* OK, no additional fields to validate */
500 break;
501 default:
502 ereport(ERROR,
503 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
504 errmsg("unrecognized API version %d reported by info function \"%s\"",
505 inforec->api_version, infofuncname)));
506 break;
507 }
508
509 pfree(infofuncname);
510 return inforec;
511 }
512
513
514 /*-------------------------------------------------------------------------
515 * Routines for caching lookup information for external C functions.
516 *
517 * The routines in dfmgr.c are relatively slow, so we try to avoid running
518 * them more than once per external function per session. We use a hash table
519 * with the function OID as the lookup key.
520 *-------------------------------------------------------------------------
521 */
522
523 /*
524 * lookup_C_func: try to find a C function in the hash table
525 *
526 * If an entry exists and is up to date, return it; else return NULL
527 */
528 static CFuncHashTabEntry *
lookup_C_func(HeapTuple procedureTuple)529 lookup_C_func(HeapTuple procedureTuple)
530 {
531 Oid fn_oid = ((Form_pg_proc) GETSTRUCT(procedureTuple))->oid;
532 CFuncHashTabEntry *entry;
533
534 if (CFuncHash == NULL)
535 return NULL; /* no table yet */
536 entry = (CFuncHashTabEntry *)
537 hash_search(CFuncHash,
538 &fn_oid,
539 HASH_FIND,
540 NULL);
541 if (entry == NULL)
542 return NULL; /* no such entry */
543 if (entry->fn_xmin == HeapTupleHeaderGetRawXmin(procedureTuple->t_data) &&
544 ItemPointerEquals(&entry->fn_tid, &procedureTuple->t_self))
545 return entry; /* OK */
546 return NULL; /* entry is out of date */
547 }
548
549 /*
550 * record_C_func: enter (or update) info about a C function in the hash table
551 */
552 static void
record_C_func(HeapTuple procedureTuple,PGFunction user_fn,const Pg_finfo_record * inforec)553 record_C_func(HeapTuple procedureTuple,
554 PGFunction user_fn, const Pg_finfo_record *inforec)
555 {
556 Oid fn_oid = ((Form_pg_proc) GETSTRUCT(procedureTuple))->oid;
557 CFuncHashTabEntry *entry;
558 bool found;
559
560 /* Create the hash table if it doesn't exist yet */
561 if (CFuncHash == NULL)
562 {
563 HASHCTL hash_ctl;
564
565 hash_ctl.keysize = sizeof(Oid);
566 hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
567 CFuncHash = hash_create("CFuncHash",
568 100,
569 &hash_ctl,
570 HASH_ELEM | HASH_BLOBS);
571 }
572
573 entry = (CFuncHashTabEntry *)
574 hash_search(CFuncHash,
575 &fn_oid,
576 HASH_ENTER,
577 &found);
578 /* OID is already filled in */
579 entry->fn_xmin = HeapTupleHeaderGetRawXmin(procedureTuple->t_data);
580 entry->fn_tid = procedureTuple->t_self;
581 entry->user_fn = user_fn;
582 entry->inforec = inforec;
583 }
584
585 /*
586 * clear_external_function_hash: remove entries for a library being closed
587 *
588 * Presently we just zap the entire hash table, but later it might be worth
589 * the effort to remove only the entries associated with the given handle.
590 */
591 void
clear_external_function_hash(void * filehandle)592 clear_external_function_hash(void *filehandle)
593 {
594 if (CFuncHash)
595 hash_destroy(CFuncHash);
596 CFuncHash = NULL;
597 }
598
599
600 /*
601 * Copy an FmgrInfo struct
602 *
603 * This is inherently somewhat bogus since we can't reliably duplicate
604 * language-dependent subsidiary info. We cheat by zeroing fn_extra,
605 * instead, meaning that subsidiary info will have to be recomputed.
606 */
607 void
fmgr_info_copy(FmgrInfo * dstinfo,FmgrInfo * srcinfo,MemoryContext destcxt)608 fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
609 MemoryContext destcxt)
610 {
611 memcpy(dstinfo, srcinfo, sizeof(FmgrInfo));
612 dstinfo->fn_mcxt = destcxt;
613 dstinfo->fn_extra = NULL;
614 }
615
616
617 /*
618 * Specialized lookup routine for fmgr_internal_validator: given the alleged
619 * name of an internal function, return the OID of the function.
620 * If the name is not recognized, return InvalidOid.
621 */
622 Oid
fmgr_internal_function(const char * proname)623 fmgr_internal_function(const char *proname)
624 {
625 const FmgrBuiltin *fbp = fmgr_lookupByName(proname);
626
627 if (fbp == NULL)
628 return InvalidOid;
629 return fbp->foid;
630 }
631
632
633 /*
634 * Support for security-definer and proconfig-using functions. We support
635 * both of these features using the same call handler, because they are
636 * often used together and it would be inefficient (as well as notationally
637 * messy) to have two levels of call handler involved.
638 */
639 struct fmgr_security_definer_cache
640 {
641 FmgrInfo flinfo; /* lookup info for target function */
642 Oid userid; /* userid to set, or InvalidOid */
643 ArrayType *proconfig; /* GUC values to set, or NULL */
644 Datum arg; /* passthrough argument for plugin modules */
645 };
646
647 /*
648 * Function handler for security-definer/proconfig/plugin-hooked functions.
649 * We extract the OID of the actual function and do a fmgr lookup again.
650 * Then we fetch the pg_proc row and copy the owner ID and proconfig fields.
651 * (All this info is cached for the duration of the current query.)
652 * To execute a call, we temporarily replace the flinfo with the cached
653 * and looked-up one, while keeping the outer fcinfo (which contains all
654 * the actual arguments, etc.) intact. This is not re-entrant, but then
655 * the fcinfo itself can't be used reentrantly anyway.
656 */
657 extern Datum
fmgr_security_definer(PG_FUNCTION_ARGS)658 fmgr_security_definer(PG_FUNCTION_ARGS)
659 {
660 Datum result;
661 struct fmgr_security_definer_cache *volatile fcache;
662 FmgrInfo *save_flinfo;
663 Oid save_userid;
664 int save_sec_context;
665 volatile int save_nestlevel;
666 PgStat_FunctionCallUsage fcusage;
667
668 if (!fcinfo->flinfo->fn_extra)
669 {
670 HeapTuple tuple;
671 Form_pg_proc procedureStruct;
672 Datum datum;
673 bool isnull;
674 MemoryContext oldcxt;
675
676 fcache = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
677 sizeof(*fcache));
678
679 fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo,
680 fcinfo->flinfo->fn_mcxt, true);
681 fcache->flinfo.fn_expr = fcinfo->flinfo->fn_expr;
682
683 tuple = SearchSysCache1(PROCOID,
684 ObjectIdGetDatum(fcinfo->flinfo->fn_oid));
685 if (!HeapTupleIsValid(tuple))
686 elog(ERROR, "cache lookup failed for function %u",
687 fcinfo->flinfo->fn_oid);
688 procedureStruct = (Form_pg_proc) GETSTRUCT(tuple);
689
690 if (procedureStruct->prosecdef)
691 fcache->userid = procedureStruct->proowner;
692
693 datum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proconfig,
694 &isnull);
695 if (!isnull)
696 {
697 oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
698 fcache->proconfig = DatumGetArrayTypePCopy(datum);
699 MemoryContextSwitchTo(oldcxt);
700 }
701
702 ReleaseSysCache(tuple);
703
704 fcinfo->flinfo->fn_extra = fcache;
705 }
706 else
707 fcache = fcinfo->flinfo->fn_extra;
708
709 /* GetUserIdAndSecContext is cheap enough that no harm in a wasted call */
710 GetUserIdAndSecContext(&save_userid, &save_sec_context);
711 if (fcache->proconfig) /* Need a new GUC nesting level */
712 save_nestlevel = NewGUCNestLevel();
713 else
714 save_nestlevel = 0; /* keep compiler quiet */
715
716 if (OidIsValid(fcache->userid))
717 SetUserIdAndSecContext(fcache->userid,
718 save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
719
720 if (fcache->proconfig)
721 {
722 ProcessGUCArray(fcache->proconfig,
723 (superuser() ? PGC_SUSET : PGC_USERSET),
724 PGC_S_SESSION,
725 GUC_ACTION_SAVE);
726 }
727
728 /* function manager hook */
729 if (fmgr_hook)
730 (*fmgr_hook) (FHET_START, &fcache->flinfo, &fcache->arg);
731
732 /*
733 * We don't need to restore GUC or userid settings on error, because the
734 * ensuing xact or subxact abort will do that. The PG_TRY block is only
735 * needed to clean up the flinfo link.
736 */
737 save_flinfo = fcinfo->flinfo;
738
739 PG_TRY();
740 {
741 fcinfo->flinfo = &fcache->flinfo;
742
743 /* See notes in fmgr_info_cxt_security */
744 pgstat_init_function_usage(fcinfo, &fcusage);
745
746 result = FunctionCallInvoke(fcinfo);
747
748 /*
749 * We could be calling either a regular or a set-returning function,
750 * so we have to test to see what finalize flag to use.
751 */
752 pgstat_end_function_usage(&fcusage,
753 (fcinfo->resultinfo == NULL ||
754 !IsA(fcinfo->resultinfo, ReturnSetInfo) ||
755 ((ReturnSetInfo *) fcinfo->resultinfo)->isDone != ExprMultipleResult));
756 }
757 PG_CATCH();
758 {
759 fcinfo->flinfo = save_flinfo;
760 if (fmgr_hook)
761 (*fmgr_hook) (FHET_ABORT, &fcache->flinfo, &fcache->arg);
762 PG_RE_THROW();
763 }
764 PG_END_TRY();
765
766 fcinfo->flinfo = save_flinfo;
767
768 if (fcache->proconfig)
769 AtEOXact_GUC(true, save_nestlevel);
770 if (OidIsValid(fcache->userid))
771 SetUserIdAndSecContext(save_userid, save_sec_context);
772 if (fmgr_hook)
773 (*fmgr_hook) (FHET_END, &fcache->flinfo, &fcache->arg);
774
775 return result;
776 }
777
778
779 /*-------------------------------------------------------------------------
780 * Support routines for callers of fmgr-compatible functions
781 *-------------------------------------------------------------------------
782 */
783
784 /*
785 * These are for invocation of a specifically named function with a
786 * directly-computed parameter list. Note that neither arguments nor result
787 * are allowed to be NULL. Also, the function cannot be one that needs to
788 * look at FmgrInfo, since there won't be any.
789 */
790 Datum
DirectFunctionCall1Coll(PGFunction func,Oid collation,Datum arg1)791 DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
792 {
793 LOCAL_FCINFO(fcinfo, 1);
794 Datum result;
795
796 InitFunctionCallInfoData(*fcinfo, NULL, 1, collation, NULL, NULL);
797
798 fcinfo->args[0].value = arg1;
799 fcinfo->args[0].isnull = false;
800
801 result = (*func) (fcinfo);
802
803 /* Check for null result, since caller is clearly not expecting one */
804 if (fcinfo->isnull)
805 elog(ERROR, "function %p returned NULL", (void *) func);
806
807 return result;
808 }
809
810 Datum
DirectFunctionCall2Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2)811 DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
812 {
813 LOCAL_FCINFO(fcinfo, 2);
814 Datum result;
815
816 InitFunctionCallInfoData(*fcinfo, NULL, 2, collation, NULL, NULL);
817
818 fcinfo->args[0].value = arg1;
819 fcinfo->args[0].isnull = false;
820 fcinfo->args[1].value = arg2;
821 fcinfo->args[1].isnull = false;
822
823 result = (*func) (fcinfo);
824
825 /* Check for null result, since caller is clearly not expecting one */
826 if (fcinfo->isnull)
827 elog(ERROR, "function %p returned NULL", (void *) func);
828
829 return result;
830 }
831
832 Datum
DirectFunctionCall3Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2,Datum arg3)833 DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
834 Datum arg3)
835 {
836 LOCAL_FCINFO(fcinfo, 3);
837 Datum result;
838
839 InitFunctionCallInfoData(*fcinfo, NULL, 3, collation, NULL, NULL);
840
841 fcinfo->args[0].value = arg1;
842 fcinfo->args[0].isnull = false;
843 fcinfo->args[1].value = arg2;
844 fcinfo->args[1].isnull = false;
845 fcinfo->args[2].value = arg3;
846 fcinfo->args[2].isnull = false;
847
848 result = (*func) (fcinfo);
849
850 /* Check for null result, since caller is clearly not expecting one */
851 if (fcinfo->isnull)
852 elog(ERROR, "function %p returned NULL", (void *) func);
853
854 return result;
855 }
856
857 Datum
DirectFunctionCall4Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4)858 DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
859 Datum arg3, Datum arg4)
860 {
861 LOCAL_FCINFO(fcinfo, 4);
862 Datum result;
863
864 InitFunctionCallInfoData(*fcinfo, NULL, 4, collation, NULL, NULL);
865
866 fcinfo->args[0].value = arg1;
867 fcinfo->args[0].isnull = false;
868 fcinfo->args[1].value = arg2;
869 fcinfo->args[1].isnull = false;
870 fcinfo->args[2].value = arg3;
871 fcinfo->args[2].isnull = false;
872 fcinfo->args[3].value = arg4;
873 fcinfo->args[3].isnull = false;
874
875 result = (*func) (fcinfo);
876
877 /* Check for null result, since caller is clearly not expecting one */
878 if (fcinfo->isnull)
879 elog(ERROR, "function %p returned NULL", (void *) func);
880
881 return result;
882 }
883
884 Datum
DirectFunctionCall5Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5)885 DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
886 Datum arg3, Datum arg4, Datum arg5)
887 {
888 LOCAL_FCINFO(fcinfo, 5);
889 Datum result;
890
891 InitFunctionCallInfoData(*fcinfo, NULL, 5, collation, NULL, NULL);
892
893 fcinfo->args[0].value = arg1;
894 fcinfo->args[0].isnull = false;
895 fcinfo->args[1].value = arg2;
896 fcinfo->args[1].isnull = false;
897 fcinfo->args[2].value = arg3;
898 fcinfo->args[2].isnull = false;
899 fcinfo->args[3].value = arg4;
900 fcinfo->args[3].isnull = false;
901 fcinfo->args[4].value = arg5;
902 fcinfo->args[4].isnull = false;
903
904 result = (*func) (fcinfo);
905
906 /* Check for null result, since caller is clearly not expecting one */
907 if (fcinfo->isnull)
908 elog(ERROR, "function %p returned NULL", (void *) func);
909
910 return result;
911 }
912
913 Datum
DirectFunctionCall6Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6)914 DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
915 Datum arg3, Datum arg4, Datum arg5,
916 Datum arg6)
917 {
918 LOCAL_FCINFO(fcinfo, 6);
919 Datum result;
920
921 InitFunctionCallInfoData(*fcinfo, NULL, 6, collation, NULL, NULL);
922
923 fcinfo->args[0].value = arg1;
924 fcinfo->args[0].isnull = false;
925 fcinfo->args[1].value = arg2;
926 fcinfo->args[1].isnull = false;
927 fcinfo->args[2].value = arg3;
928 fcinfo->args[2].isnull = false;
929 fcinfo->args[3].value = arg4;
930 fcinfo->args[3].isnull = false;
931 fcinfo->args[4].value = arg5;
932 fcinfo->args[4].isnull = false;
933 fcinfo->args[5].value = arg6;
934 fcinfo->args[5].isnull = false;
935
936 result = (*func) (fcinfo);
937
938 /* Check for null result, since caller is clearly not expecting one */
939 if (fcinfo->isnull)
940 elog(ERROR, "function %p returned NULL", (void *) func);
941
942 return result;
943 }
944
945 Datum
DirectFunctionCall7Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7)946 DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
947 Datum arg3, Datum arg4, Datum arg5,
948 Datum arg6, Datum arg7)
949 {
950 LOCAL_FCINFO(fcinfo, 7);
951 Datum result;
952
953 InitFunctionCallInfoData(*fcinfo, NULL, 7, collation, NULL, NULL);
954
955 fcinfo->args[0].value = arg1;
956 fcinfo->args[0].isnull = false;
957 fcinfo->args[1].value = arg2;
958 fcinfo->args[1].isnull = false;
959 fcinfo->args[2].value = arg3;
960 fcinfo->args[2].isnull = false;
961 fcinfo->args[3].value = arg4;
962 fcinfo->args[3].isnull = false;
963 fcinfo->args[4].value = arg5;
964 fcinfo->args[4].isnull = false;
965 fcinfo->args[5].value = arg6;
966 fcinfo->args[5].isnull = false;
967 fcinfo->args[6].value = arg7;
968 fcinfo->args[6].isnull = false;
969
970 result = (*func) (fcinfo);
971
972 /* Check for null result, since caller is clearly not expecting one */
973 if (fcinfo->isnull)
974 elog(ERROR, "function %p returned NULL", (void *) func);
975
976 return result;
977 }
978
979 Datum
DirectFunctionCall8Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7,Datum arg8)980 DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
981 Datum arg3, Datum arg4, Datum arg5,
982 Datum arg6, Datum arg7, Datum arg8)
983 {
984 LOCAL_FCINFO(fcinfo, 8);
985 Datum result;
986
987 InitFunctionCallInfoData(*fcinfo, NULL, 8, collation, NULL, NULL);
988
989 fcinfo->args[0].value = arg1;
990 fcinfo->args[0].isnull = false;
991 fcinfo->args[1].value = arg2;
992 fcinfo->args[1].isnull = false;
993 fcinfo->args[2].value = arg3;
994 fcinfo->args[2].isnull = false;
995 fcinfo->args[3].value = arg4;
996 fcinfo->args[3].isnull = false;
997 fcinfo->args[4].value = arg5;
998 fcinfo->args[4].isnull = false;
999 fcinfo->args[5].value = arg6;
1000 fcinfo->args[5].isnull = false;
1001 fcinfo->args[6].value = arg7;
1002 fcinfo->args[6].isnull = false;
1003 fcinfo->args[7].value = arg8;
1004 fcinfo->args[7].isnull = false;
1005
1006 result = (*func) (fcinfo);
1007
1008 /* Check for null result, since caller is clearly not expecting one */
1009 if (fcinfo->isnull)
1010 elog(ERROR, "function %p returned NULL", (void *) func);
1011
1012 return result;
1013 }
1014
1015 Datum
DirectFunctionCall9Coll(PGFunction func,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7,Datum arg8,Datum arg9)1016 DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
1017 Datum arg3, Datum arg4, Datum arg5,
1018 Datum arg6, Datum arg7, Datum arg8,
1019 Datum arg9)
1020 {
1021 LOCAL_FCINFO(fcinfo, 9);
1022 Datum result;
1023
1024 InitFunctionCallInfoData(*fcinfo, NULL, 9, collation, NULL, NULL);
1025
1026 fcinfo->args[0].value = arg1;
1027 fcinfo->args[0].isnull = false;
1028 fcinfo->args[1].value = arg2;
1029 fcinfo->args[1].isnull = false;
1030 fcinfo->args[2].value = arg3;
1031 fcinfo->args[2].isnull = false;
1032 fcinfo->args[3].value = arg4;
1033 fcinfo->args[3].isnull = false;
1034 fcinfo->args[4].value = arg5;
1035 fcinfo->args[4].isnull = false;
1036 fcinfo->args[5].value = arg6;
1037 fcinfo->args[5].isnull = false;
1038 fcinfo->args[6].value = arg7;
1039 fcinfo->args[6].isnull = false;
1040 fcinfo->args[7].value = arg8;
1041 fcinfo->args[7].isnull = false;
1042 fcinfo->args[8].value = arg9;
1043 fcinfo->args[8].isnull = false;
1044
1045 result = (*func) (fcinfo);
1046
1047 /* Check for null result, since caller is clearly not expecting one */
1048 if (fcinfo->isnull)
1049 elog(ERROR, "function %p returned NULL", (void *) func);
1050
1051 return result;
1052 }
1053
1054 /*
1055 * These functions work like the DirectFunctionCall functions except that
1056 * they use the flinfo parameter to initialise the fcinfo for the call.
1057 * It's recommended that the callee only use the fn_extra and fn_mcxt
1058 * fields, as other fields will typically describe the calling function
1059 * not the callee. Conversely, the calling function should not have
1060 * used fn_extra, unless its use is known to be compatible with the callee's.
1061 */
1062
1063 Datum
CallerFInfoFunctionCall1(PGFunction func,FmgrInfo * flinfo,Oid collation,Datum arg1)1064 CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1)
1065 {
1066 LOCAL_FCINFO(fcinfo, 1);
1067 Datum result;
1068
1069 InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL);
1070
1071 fcinfo->args[0].value = arg1;
1072 fcinfo->args[0].isnull = false;
1073
1074 result = (*func) (fcinfo);
1075
1076 /* Check for null result, since caller is clearly not expecting one */
1077 if (fcinfo->isnull)
1078 elog(ERROR, "function %p returned NULL", (void *) func);
1079
1080 return result;
1081 }
1082
1083 Datum
CallerFInfoFunctionCall2(PGFunction func,FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2)1084 CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
1085 {
1086 LOCAL_FCINFO(fcinfo, 2);
1087 Datum result;
1088
1089 InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
1090
1091 fcinfo->args[0].value = arg1;
1092 fcinfo->args[0].isnull = false;
1093 fcinfo->args[1].value = arg2;
1094 fcinfo->args[1].isnull = false;
1095
1096 result = (*func) (fcinfo);
1097
1098 /* Check for null result, since caller is clearly not expecting one */
1099 if (fcinfo->isnull)
1100 elog(ERROR, "function %p returned NULL", (void *) func);
1101
1102 return result;
1103 }
1104
1105 /*
1106 * These are for invocation of a previously-looked-up function with a
1107 * directly-computed parameter list. Note that neither arguments nor result
1108 * are allowed to be NULL.
1109 */
1110 Datum
FunctionCall0Coll(FmgrInfo * flinfo,Oid collation)1111 FunctionCall0Coll(FmgrInfo *flinfo, Oid collation)
1112 {
1113 LOCAL_FCINFO(fcinfo, 0);
1114 Datum result;
1115
1116 InitFunctionCallInfoData(*fcinfo, flinfo, 0, collation, NULL, NULL);
1117
1118 result = FunctionCallInvoke(fcinfo);
1119
1120 /* Check for null result, since caller is clearly not expecting one */
1121 if (fcinfo->isnull)
1122 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1123
1124 return result;
1125 }
1126
1127 Datum
FunctionCall1Coll(FmgrInfo * flinfo,Oid collation,Datum arg1)1128 FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
1129 {
1130 LOCAL_FCINFO(fcinfo, 1);
1131 Datum result;
1132
1133 InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL);
1134
1135 fcinfo->args[0].value = arg1;
1136 fcinfo->args[0].isnull = false;
1137
1138 result = FunctionCallInvoke(fcinfo);
1139
1140 /* Check for null result, since caller is clearly not expecting one */
1141 if (fcinfo->isnull)
1142 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1143
1144 return result;
1145 }
1146
1147 Datum
FunctionCall2Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2)1148 FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
1149 {
1150 LOCAL_FCINFO(fcinfo, 2);
1151 Datum result;
1152
1153 InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
1154
1155 fcinfo->args[0].value = arg1;
1156 fcinfo->args[0].isnull = false;
1157 fcinfo->args[1].value = arg2;
1158 fcinfo->args[1].isnull = false;
1159
1160 result = FunctionCallInvoke(fcinfo);
1161
1162 /* Check for null result, since caller is clearly not expecting one */
1163 if (fcinfo->isnull)
1164 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1165
1166 return result;
1167 }
1168
1169 Datum
FunctionCall3Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2,Datum arg3)1170 FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1171 Datum arg3)
1172 {
1173 LOCAL_FCINFO(fcinfo, 3);
1174 Datum result;
1175
1176 InitFunctionCallInfoData(*fcinfo, flinfo, 3, collation, NULL, NULL);
1177
1178 fcinfo->args[0].value = arg1;
1179 fcinfo->args[0].isnull = false;
1180 fcinfo->args[1].value = arg2;
1181 fcinfo->args[1].isnull = false;
1182 fcinfo->args[2].value = arg3;
1183 fcinfo->args[2].isnull = false;
1184
1185 result = FunctionCallInvoke(fcinfo);
1186
1187 /* Check for null result, since caller is clearly not expecting one */
1188 if (fcinfo->isnull)
1189 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1190
1191 return result;
1192 }
1193
1194 Datum
FunctionCall4Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4)1195 FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1196 Datum arg3, Datum arg4)
1197 {
1198 LOCAL_FCINFO(fcinfo, 4);
1199 Datum result;
1200
1201 InitFunctionCallInfoData(*fcinfo, flinfo, 4, collation, NULL, NULL);
1202
1203 fcinfo->args[0].value = arg1;
1204 fcinfo->args[0].isnull = false;
1205 fcinfo->args[1].value = arg2;
1206 fcinfo->args[1].isnull = false;
1207 fcinfo->args[2].value = arg3;
1208 fcinfo->args[2].isnull = false;
1209 fcinfo->args[3].value = arg4;
1210 fcinfo->args[3].isnull = false;
1211
1212 result = FunctionCallInvoke(fcinfo);
1213
1214 /* Check for null result, since caller is clearly not expecting one */
1215 if (fcinfo->isnull)
1216 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1217
1218 return result;
1219 }
1220
1221 Datum
FunctionCall5Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5)1222 FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1223 Datum arg3, Datum arg4, Datum arg5)
1224 {
1225 LOCAL_FCINFO(fcinfo, 5);
1226 Datum result;
1227
1228 InitFunctionCallInfoData(*fcinfo, flinfo, 5, collation, NULL, NULL);
1229
1230 fcinfo->args[0].value = arg1;
1231 fcinfo->args[0].isnull = false;
1232 fcinfo->args[1].value = arg2;
1233 fcinfo->args[1].isnull = false;
1234 fcinfo->args[2].value = arg3;
1235 fcinfo->args[2].isnull = false;
1236 fcinfo->args[3].value = arg4;
1237 fcinfo->args[3].isnull = false;
1238 fcinfo->args[4].value = arg5;
1239 fcinfo->args[4].isnull = false;
1240
1241 result = FunctionCallInvoke(fcinfo);
1242
1243 /* Check for null result, since caller is clearly not expecting one */
1244 if (fcinfo->isnull)
1245 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1246
1247 return result;
1248 }
1249
1250 Datum
FunctionCall6Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6)1251 FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1252 Datum arg3, Datum arg4, Datum arg5,
1253 Datum arg6)
1254 {
1255 LOCAL_FCINFO(fcinfo, 6);
1256 Datum result;
1257
1258 InitFunctionCallInfoData(*fcinfo, flinfo, 6, collation, NULL, NULL);
1259
1260 fcinfo->args[0].value = arg1;
1261 fcinfo->args[0].isnull = false;
1262 fcinfo->args[1].value = arg2;
1263 fcinfo->args[1].isnull = false;
1264 fcinfo->args[2].value = arg3;
1265 fcinfo->args[2].isnull = false;
1266 fcinfo->args[3].value = arg4;
1267 fcinfo->args[3].isnull = false;
1268 fcinfo->args[4].value = arg5;
1269 fcinfo->args[4].isnull = false;
1270 fcinfo->args[5].value = arg6;
1271 fcinfo->args[5].isnull = false;
1272
1273 result = FunctionCallInvoke(fcinfo);
1274
1275 /* Check for null result, since caller is clearly not expecting one */
1276 if (fcinfo->isnull)
1277 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1278
1279 return result;
1280 }
1281
1282 Datum
FunctionCall7Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7)1283 FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1284 Datum arg3, Datum arg4, Datum arg5,
1285 Datum arg6, Datum arg7)
1286 {
1287 LOCAL_FCINFO(fcinfo, 7);
1288 Datum result;
1289
1290 InitFunctionCallInfoData(*fcinfo, flinfo, 7, collation, NULL, NULL);
1291
1292 fcinfo->args[0].value = arg1;
1293 fcinfo->args[0].isnull = false;
1294 fcinfo->args[1].value = arg2;
1295 fcinfo->args[1].isnull = false;
1296 fcinfo->args[2].value = arg3;
1297 fcinfo->args[2].isnull = false;
1298 fcinfo->args[3].value = arg4;
1299 fcinfo->args[3].isnull = false;
1300 fcinfo->args[4].value = arg5;
1301 fcinfo->args[4].isnull = false;
1302 fcinfo->args[5].value = arg6;
1303 fcinfo->args[5].isnull = false;
1304 fcinfo->args[6].value = arg7;
1305 fcinfo->args[6].isnull = false;
1306
1307 result = FunctionCallInvoke(fcinfo);
1308
1309 /* Check for null result, since caller is clearly not expecting one */
1310 if (fcinfo->isnull)
1311 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1312
1313 return result;
1314 }
1315
1316 Datum
FunctionCall8Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7,Datum arg8)1317 FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1318 Datum arg3, Datum arg4, Datum arg5,
1319 Datum arg6, Datum arg7, Datum arg8)
1320 {
1321 LOCAL_FCINFO(fcinfo, 8);
1322 Datum result;
1323
1324 InitFunctionCallInfoData(*fcinfo, flinfo, 8, collation, NULL, NULL);
1325
1326 fcinfo->args[0].value = arg1;
1327 fcinfo->args[0].isnull = false;
1328 fcinfo->args[1].value = arg2;
1329 fcinfo->args[1].isnull = false;
1330 fcinfo->args[2].value = arg3;
1331 fcinfo->args[2].isnull = false;
1332 fcinfo->args[3].value = arg4;
1333 fcinfo->args[3].isnull = false;
1334 fcinfo->args[4].value = arg5;
1335 fcinfo->args[4].isnull = false;
1336 fcinfo->args[5].value = arg6;
1337 fcinfo->args[5].isnull = false;
1338 fcinfo->args[6].value = arg7;
1339 fcinfo->args[6].isnull = false;
1340 fcinfo->args[7].value = arg8;
1341 fcinfo->args[7].isnull = false;
1342
1343 result = FunctionCallInvoke(fcinfo);
1344
1345 /* Check for null result, since caller is clearly not expecting one */
1346 if (fcinfo->isnull)
1347 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1348
1349 return result;
1350 }
1351
1352 Datum
FunctionCall9Coll(FmgrInfo * flinfo,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7,Datum arg8,Datum arg9)1353 FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1354 Datum arg3, Datum arg4, Datum arg5,
1355 Datum arg6, Datum arg7, Datum arg8,
1356 Datum arg9)
1357 {
1358 LOCAL_FCINFO(fcinfo, 9);
1359 Datum result;
1360
1361 InitFunctionCallInfoData(*fcinfo, flinfo, 9, collation, NULL, NULL);
1362
1363 fcinfo->args[0].value = arg1;
1364 fcinfo->args[0].isnull = false;
1365 fcinfo->args[1].value = arg2;
1366 fcinfo->args[1].isnull = false;
1367 fcinfo->args[2].value = arg3;
1368 fcinfo->args[2].isnull = false;
1369 fcinfo->args[3].value = arg4;
1370 fcinfo->args[3].isnull = false;
1371 fcinfo->args[4].value = arg5;
1372 fcinfo->args[4].isnull = false;
1373 fcinfo->args[5].value = arg6;
1374 fcinfo->args[5].isnull = false;
1375 fcinfo->args[6].value = arg7;
1376 fcinfo->args[6].isnull = false;
1377 fcinfo->args[7].value = arg8;
1378 fcinfo->args[7].isnull = false;
1379 fcinfo->args[8].value = arg9;
1380 fcinfo->args[8].isnull = false;
1381
1382 result = FunctionCallInvoke(fcinfo);
1383
1384 /* Check for null result, since caller is clearly not expecting one */
1385 if (fcinfo->isnull)
1386 elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1387
1388 return result;
1389 }
1390
1391
1392 /*
1393 * These are for invocation of a function identified by OID with a
1394 * directly-computed parameter list. Note that neither arguments nor result
1395 * are allowed to be NULL. These are essentially fmgr_info() followed
1396 * by FunctionCallN(). If the same function is to be invoked repeatedly,
1397 * do the fmgr_info() once and then use FunctionCallN().
1398 */
1399 Datum
OidFunctionCall0Coll(Oid functionId,Oid collation)1400 OidFunctionCall0Coll(Oid functionId, Oid collation)
1401 {
1402 FmgrInfo flinfo;
1403
1404 fmgr_info(functionId, &flinfo);
1405
1406 return FunctionCall0Coll(&flinfo, collation);
1407 }
1408
1409 Datum
OidFunctionCall1Coll(Oid functionId,Oid collation,Datum arg1)1410 OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
1411 {
1412 FmgrInfo flinfo;
1413
1414 fmgr_info(functionId, &flinfo);
1415
1416 return FunctionCall1Coll(&flinfo, collation, arg1);
1417 }
1418
1419 Datum
OidFunctionCall2Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2)1420 OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
1421 {
1422 FmgrInfo flinfo;
1423
1424 fmgr_info(functionId, &flinfo);
1425
1426 return FunctionCall2Coll(&flinfo, collation, arg1, arg2);
1427 }
1428
1429 Datum
OidFunctionCall3Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2,Datum arg3)1430 OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1431 Datum arg3)
1432 {
1433 FmgrInfo flinfo;
1434
1435 fmgr_info(functionId, &flinfo);
1436
1437 return FunctionCall3Coll(&flinfo, collation, arg1, arg2, arg3);
1438 }
1439
1440 Datum
OidFunctionCall4Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4)1441 OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1442 Datum arg3, Datum arg4)
1443 {
1444 FmgrInfo flinfo;
1445
1446 fmgr_info(functionId, &flinfo);
1447
1448 return FunctionCall4Coll(&flinfo, collation, arg1, arg2, arg3, arg4);
1449 }
1450
1451 Datum
OidFunctionCall5Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5)1452 OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1453 Datum arg3, Datum arg4, Datum arg5)
1454 {
1455 FmgrInfo flinfo;
1456
1457 fmgr_info(functionId, &flinfo);
1458
1459 return FunctionCall5Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5);
1460 }
1461
1462 Datum
OidFunctionCall6Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6)1463 OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1464 Datum arg3, Datum arg4, Datum arg5,
1465 Datum arg6)
1466 {
1467 FmgrInfo flinfo;
1468
1469 fmgr_info(functionId, &flinfo);
1470
1471 return FunctionCall6Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1472 arg6);
1473 }
1474
1475 Datum
OidFunctionCall7Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7)1476 OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1477 Datum arg3, Datum arg4, Datum arg5,
1478 Datum arg6, Datum arg7)
1479 {
1480 FmgrInfo flinfo;
1481
1482 fmgr_info(functionId, &flinfo);
1483
1484 return FunctionCall7Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1485 arg6, arg7);
1486 }
1487
1488 Datum
OidFunctionCall8Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7,Datum arg8)1489 OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1490 Datum arg3, Datum arg4, Datum arg5,
1491 Datum arg6, Datum arg7, Datum arg8)
1492 {
1493 FmgrInfo flinfo;
1494
1495 fmgr_info(functionId, &flinfo);
1496
1497 return FunctionCall8Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1498 arg6, arg7, arg8);
1499 }
1500
1501 Datum
OidFunctionCall9Coll(Oid functionId,Oid collation,Datum arg1,Datum arg2,Datum arg3,Datum arg4,Datum arg5,Datum arg6,Datum arg7,Datum arg8,Datum arg9)1502 OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1503 Datum arg3, Datum arg4, Datum arg5,
1504 Datum arg6, Datum arg7, Datum arg8,
1505 Datum arg9)
1506 {
1507 FmgrInfo flinfo;
1508
1509 fmgr_info(functionId, &flinfo);
1510
1511 return FunctionCall9Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1512 arg6, arg7, arg8, arg9);
1513 }
1514
1515
1516 /*
1517 * Special cases for convenient invocation of datatype I/O functions.
1518 */
1519
1520 /*
1521 * Call a previously-looked-up datatype input function.
1522 *
1523 * "str" may be NULL to indicate we are reading a NULL. In this case
1524 * the caller should assume the result is NULL, but we'll call the input
1525 * function anyway if it's not strict. So this is almost but not quite
1526 * the same as FunctionCall3.
1527 */
1528 Datum
InputFunctionCall(FmgrInfo * flinfo,char * str,Oid typioparam,int32 typmod)1529 InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
1530 {
1531 LOCAL_FCINFO(fcinfo, 3);
1532 Datum result;
1533
1534 if (str == NULL && flinfo->fn_strict)
1535 return (Datum) 0; /* just return null result */
1536
1537 InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
1538
1539 fcinfo->args[0].value = CStringGetDatum(str);
1540 fcinfo->args[0].isnull = false;
1541 fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1542 fcinfo->args[1].isnull = false;
1543 fcinfo->args[2].value = Int32GetDatum(typmod);
1544 fcinfo->args[2].isnull = false;
1545
1546 result = FunctionCallInvoke(fcinfo);
1547
1548 /* Should get null result if and only if str is NULL */
1549 if (str == NULL)
1550 {
1551 if (!fcinfo->isnull)
1552 elog(ERROR, "input function %u returned non-NULL",
1553 flinfo->fn_oid);
1554 }
1555 else
1556 {
1557 if (fcinfo->isnull)
1558 elog(ERROR, "input function %u returned NULL",
1559 flinfo->fn_oid);
1560 }
1561
1562 return result;
1563 }
1564
1565 /*
1566 * Call a previously-looked-up datatype output function.
1567 *
1568 * Do not call this on NULL datums.
1569 *
1570 * This is currently little more than window dressing for FunctionCall1.
1571 */
1572 char *
OutputFunctionCall(FmgrInfo * flinfo,Datum val)1573 OutputFunctionCall(FmgrInfo *flinfo, Datum val)
1574 {
1575 return DatumGetCString(FunctionCall1(flinfo, val));
1576 }
1577
1578 /*
1579 * Call a previously-looked-up datatype binary-input function.
1580 *
1581 * "buf" may be NULL to indicate we are reading a NULL. In this case
1582 * the caller should assume the result is NULL, but we'll call the receive
1583 * function anyway if it's not strict. So this is almost but not quite
1584 * the same as FunctionCall3.
1585 */
1586 Datum
ReceiveFunctionCall(FmgrInfo * flinfo,StringInfo buf,Oid typioparam,int32 typmod)1587 ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
1588 Oid typioparam, int32 typmod)
1589 {
1590 LOCAL_FCINFO(fcinfo, 3);
1591 Datum result;
1592
1593 if (buf == NULL && flinfo->fn_strict)
1594 return (Datum) 0; /* just return null result */
1595
1596 InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
1597
1598 fcinfo->args[0].value = PointerGetDatum(buf);
1599 fcinfo->args[0].isnull = false;
1600 fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1601 fcinfo->args[1].isnull = false;
1602 fcinfo->args[2].value = Int32GetDatum(typmod);
1603 fcinfo->args[2].isnull = false;
1604
1605 result = FunctionCallInvoke(fcinfo);
1606
1607 /* Should get null result if and only if buf is NULL */
1608 if (buf == NULL)
1609 {
1610 if (!fcinfo->isnull)
1611 elog(ERROR, "receive function %u returned non-NULL",
1612 flinfo->fn_oid);
1613 }
1614 else
1615 {
1616 if (fcinfo->isnull)
1617 elog(ERROR, "receive function %u returned NULL",
1618 flinfo->fn_oid);
1619 }
1620
1621 return result;
1622 }
1623
1624 /*
1625 * Call a previously-looked-up datatype binary-output function.
1626 *
1627 * Do not call this on NULL datums.
1628 *
1629 * This is little more than window dressing for FunctionCall1, but it does
1630 * guarantee a non-toasted result, which strictly speaking the underlying
1631 * function doesn't.
1632 */
1633 bytea *
SendFunctionCall(FmgrInfo * flinfo,Datum val)1634 SendFunctionCall(FmgrInfo *flinfo, Datum val)
1635 {
1636 return DatumGetByteaP(FunctionCall1(flinfo, val));
1637 }
1638
1639 /*
1640 * As above, for I/O functions identified by OID. These are only to be used
1641 * in seldom-executed code paths. They are not only slow but leak memory.
1642 */
1643 Datum
OidInputFunctionCall(Oid functionId,char * str,Oid typioparam,int32 typmod)1644 OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
1645 {
1646 FmgrInfo flinfo;
1647
1648 fmgr_info(functionId, &flinfo);
1649 return InputFunctionCall(&flinfo, str, typioparam, typmod);
1650 }
1651
1652 char *
OidOutputFunctionCall(Oid functionId,Datum val)1653 OidOutputFunctionCall(Oid functionId, Datum val)
1654 {
1655 FmgrInfo flinfo;
1656
1657 fmgr_info(functionId, &flinfo);
1658 return OutputFunctionCall(&flinfo, val);
1659 }
1660
1661 Datum
OidReceiveFunctionCall(Oid functionId,StringInfo buf,Oid typioparam,int32 typmod)1662 OidReceiveFunctionCall(Oid functionId, StringInfo buf,
1663 Oid typioparam, int32 typmod)
1664 {
1665 FmgrInfo flinfo;
1666
1667 fmgr_info(functionId, &flinfo);
1668 return ReceiveFunctionCall(&flinfo, buf, typioparam, typmod);
1669 }
1670
1671 bytea *
OidSendFunctionCall(Oid functionId,Datum val)1672 OidSendFunctionCall(Oid functionId, Datum val)
1673 {
1674 FmgrInfo flinfo;
1675
1676 fmgr_info(functionId, &flinfo);
1677 return SendFunctionCall(&flinfo, val);
1678 }
1679
1680
1681 /*-------------------------------------------------------------------------
1682 * Support routines for standard maybe-pass-by-reference datatypes
1683 *
1684 * int8 and float8 can be passed by value if Datum is wide enough.
1685 * (For backwards-compatibility reasons, we allow pass-by-ref to be chosen
1686 * at compile time even if pass-by-val is possible.)
1687 *
1688 * Note: there is only one switch controlling the pass-by-value option for
1689 * both int8 and float8; this is to avoid making things unduly complicated
1690 * for the timestamp types, which might have either representation.
1691 *-------------------------------------------------------------------------
1692 */
1693
1694 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
1695
1696 Datum
Int64GetDatum(int64 X)1697 Int64GetDatum(int64 X)
1698 {
1699 int64 *retval = (int64 *) palloc(sizeof(int64));
1700
1701 *retval = X;
1702 return PointerGetDatum(retval);
1703 }
1704
1705 Datum
Float8GetDatum(float8 X)1706 Float8GetDatum(float8 X)
1707 {
1708 float8 *retval = (float8 *) palloc(sizeof(float8));
1709
1710 *retval = X;
1711 return PointerGetDatum(retval);
1712 }
1713 #endif /* USE_FLOAT8_BYVAL */
1714
1715
1716 /*-------------------------------------------------------------------------
1717 * Support routines for toastable datatypes
1718 *-------------------------------------------------------------------------
1719 */
1720
1721 struct varlena *
pg_detoast_datum(struct varlena * datum)1722 pg_detoast_datum(struct varlena *datum)
1723 {
1724 if (VARATT_IS_EXTENDED(datum))
1725 return detoast_attr(datum);
1726 else
1727 return datum;
1728 }
1729
1730 struct varlena *
pg_detoast_datum_copy(struct varlena * datum)1731 pg_detoast_datum_copy(struct varlena *datum)
1732 {
1733 if (VARATT_IS_EXTENDED(datum))
1734 return detoast_attr(datum);
1735 else
1736 {
1737 /* Make a modifiable copy of the varlena object */
1738 Size len = VARSIZE(datum);
1739 struct varlena *result = (struct varlena *) palloc(len);
1740
1741 memcpy(result, datum, len);
1742 return result;
1743 }
1744 }
1745
1746 struct varlena *
pg_detoast_datum_slice(struct varlena * datum,int32 first,int32 count)1747 pg_detoast_datum_slice(struct varlena *datum, int32 first, int32 count)
1748 {
1749 /* Only get the specified portion from the toast rel */
1750 return detoast_attr_slice(datum, first, count);
1751 }
1752
1753 struct varlena *
pg_detoast_datum_packed(struct varlena * datum)1754 pg_detoast_datum_packed(struct varlena *datum)
1755 {
1756 if (VARATT_IS_COMPRESSED(datum) || VARATT_IS_EXTERNAL(datum))
1757 return detoast_attr(datum);
1758 else
1759 return datum;
1760 }
1761
1762 /*-------------------------------------------------------------------------
1763 * Support routines for extracting info from fn_expr parse tree
1764 *
1765 * These are needed by polymorphic functions, which accept multiple possible
1766 * input types and need help from the parser to know what they've got.
1767 * Also, some functions might be interested in whether a parameter is constant.
1768 * Functions taking VARIADIC ANY also need to know about the VARIADIC keyword.
1769 *-------------------------------------------------------------------------
1770 */
1771
1772 /*
1773 * Get the actual type OID of the function return type
1774 *
1775 * Returns InvalidOid if information is not available
1776 */
1777 Oid
get_fn_expr_rettype(FmgrInfo * flinfo)1778 get_fn_expr_rettype(FmgrInfo *flinfo)
1779 {
1780 Node *expr;
1781
1782 /*
1783 * can't return anything useful if we have no FmgrInfo or if its fn_expr
1784 * node has not been initialized
1785 */
1786 if (!flinfo || !flinfo->fn_expr)
1787 return InvalidOid;
1788
1789 expr = flinfo->fn_expr;
1790
1791 return exprType(expr);
1792 }
1793
1794 /*
1795 * Get the actual type OID of a specific function argument (counting from 0)
1796 *
1797 * Returns InvalidOid if information is not available
1798 */
1799 Oid
get_fn_expr_argtype(FmgrInfo * flinfo,int argnum)1800 get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
1801 {
1802 /*
1803 * can't return anything useful if we have no FmgrInfo or if its fn_expr
1804 * node has not been initialized
1805 */
1806 if (!flinfo || !flinfo->fn_expr)
1807 return InvalidOid;
1808
1809 return get_call_expr_argtype(flinfo->fn_expr, argnum);
1810 }
1811
1812 /*
1813 * Get the actual type OID of a specific function argument (counting from 0),
1814 * but working from the calling expression tree instead of FmgrInfo
1815 *
1816 * Returns InvalidOid if information is not available
1817 */
1818 Oid
get_call_expr_argtype(Node * expr,int argnum)1819 get_call_expr_argtype(Node *expr, int argnum)
1820 {
1821 List *args;
1822 Oid argtype;
1823
1824 if (expr == NULL)
1825 return InvalidOid;
1826
1827 if (IsA(expr, FuncExpr))
1828 args = ((FuncExpr *) expr)->args;
1829 else if (IsA(expr, OpExpr))
1830 args = ((OpExpr *) expr)->args;
1831 else if (IsA(expr, DistinctExpr))
1832 args = ((DistinctExpr *) expr)->args;
1833 else if (IsA(expr, ScalarArrayOpExpr))
1834 args = ((ScalarArrayOpExpr *) expr)->args;
1835 else if (IsA(expr, NullIfExpr))
1836 args = ((NullIfExpr *) expr)->args;
1837 else if (IsA(expr, WindowFunc))
1838 args = ((WindowFunc *) expr)->args;
1839 else
1840 return InvalidOid;
1841
1842 if (argnum < 0 || argnum >= list_length(args))
1843 return InvalidOid;
1844
1845 argtype = exprType((Node *) list_nth(args, argnum));
1846
1847 /*
1848 * special hack for ScalarArrayOpExpr: what the underlying function will
1849 * actually get passed is the element type of the array.
1850 */
1851 if (IsA(expr, ScalarArrayOpExpr) &&
1852 argnum == 1)
1853 argtype = get_base_element_type(argtype);
1854
1855 return argtype;
1856 }
1857
1858 /*
1859 * Find out whether a specific function argument is constant for the
1860 * duration of a query
1861 *
1862 * Returns false if information is not available
1863 */
1864 bool
get_fn_expr_arg_stable(FmgrInfo * flinfo,int argnum)1865 get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
1866 {
1867 /*
1868 * can't return anything useful if we have no FmgrInfo or if its fn_expr
1869 * node has not been initialized
1870 */
1871 if (!flinfo || !flinfo->fn_expr)
1872 return false;
1873
1874 return get_call_expr_arg_stable(flinfo->fn_expr, argnum);
1875 }
1876
1877 /*
1878 * Find out whether a specific function argument is constant for the
1879 * duration of a query, but working from the calling expression tree
1880 *
1881 * Returns false if information is not available
1882 */
1883 bool
get_call_expr_arg_stable(Node * expr,int argnum)1884 get_call_expr_arg_stable(Node *expr, int argnum)
1885 {
1886 List *args;
1887 Node *arg;
1888
1889 if (expr == NULL)
1890 return false;
1891
1892 if (IsA(expr, FuncExpr))
1893 args = ((FuncExpr *) expr)->args;
1894 else if (IsA(expr, OpExpr))
1895 args = ((OpExpr *) expr)->args;
1896 else if (IsA(expr, DistinctExpr))
1897 args = ((DistinctExpr *) expr)->args;
1898 else if (IsA(expr, ScalarArrayOpExpr))
1899 args = ((ScalarArrayOpExpr *) expr)->args;
1900 else if (IsA(expr, NullIfExpr))
1901 args = ((NullIfExpr *) expr)->args;
1902 else if (IsA(expr, WindowFunc))
1903 args = ((WindowFunc *) expr)->args;
1904 else
1905 return false;
1906
1907 if (argnum < 0 || argnum >= list_length(args))
1908 return false;
1909
1910 arg = (Node *) list_nth(args, argnum);
1911
1912 /*
1913 * Either a true Const or an external Param will have a value that doesn't
1914 * change during the execution of the query. In future we might want to
1915 * consider other cases too, e.g. now().
1916 */
1917 if (IsA(arg, Const))
1918 return true;
1919 if (IsA(arg, Param) &&
1920 ((Param *) arg)->paramkind == PARAM_EXTERN)
1921 return true;
1922
1923 return false;
1924 }
1925
1926 /*
1927 * Get the VARIADIC flag from the function invocation
1928 *
1929 * Returns false (the default assumption) if information is not available
1930 *
1931 * Note this is generally only of interest to VARIADIC ANY functions
1932 */
1933 bool
get_fn_expr_variadic(FmgrInfo * flinfo)1934 get_fn_expr_variadic(FmgrInfo *flinfo)
1935 {
1936 Node *expr;
1937
1938 /*
1939 * can't return anything useful if we have no FmgrInfo or if its fn_expr
1940 * node has not been initialized
1941 */
1942 if (!flinfo || !flinfo->fn_expr)
1943 return false;
1944
1945 expr = flinfo->fn_expr;
1946
1947 if (IsA(expr, FuncExpr))
1948 return ((FuncExpr *) expr)->funcvariadic;
1949 else
1950 return false;
1951 }
1952
1953 /*
1954 * Set options to FmgrInfo of opclass support function.
1955 *
1956 * Opclass support functions are called outside of expressions. Thanks to that
1957 * we can use fn_expr to store opclass options as bytea constant.
1958 */
1959 void
set_fn_opclass_options(FmgrInfo * flinfo,bytea * options)1960 set_fn_opclass_options(FmgrInfo *flinfo, bytea *options)
1961 {
1962 flinfo->fn_expr = (Node *) makeConst(BYTEAOID, -1, InvalidOid, -1,
1963 PointerGetDatum(options),
1964 options == NULL, false);
1965 }
1966
1967 /*
1968 * Check if options are defined for opclass support function.
1969 */
1970 bool
has_fn_opclass_options(FmgrInfo * flinfo)1971 has_fn_opclass_options(FmgrInfo *flinfo)
1972 {
1973 if (flinfo && flinfo->fn_expr && IsA(flinfo->fn_expr, Const))
1974 {
1975 Const *expr = (Const *) flinfo->fn_expr;
1976
1977 if (expr->consttype == BYTEAOID)
1978 return !expr->constisnull;
1979 }
1980 return false;
1981 }
1982
1983 /*
1984 * Get options for opclass support function.
1985 */
1986 bytea *
get_fn_opclass_options(FmgrInfo * flinfo)1987 get_fn_opclass_options(FmgrInfo *flinfo)
1988 {
1989 if (flinfo && flinfo->fn_expr && IsA(flinfo->fn_expr, Const))
1990 {
1991 Const *expr = (Const *) flinfo->fn_expr;
1992
1993 if (expr->consttype == BYTEAOID)
1994 return expr->constisnull ? NULL : DatumGetByteaP(expr->constvalue);
1995 }
1996
1997 ereport(ERROR,
1998 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1999 errmsg("operator class options info is absent in function call context")));
2000
2001 return NULL;
2002 }
2003
2004 /*-------------------------------------------------------------------------
2005 * Support routines for procedural language implementations
2006 *-------------------------------------------------------------------------
2007 */
2008
2009 /*
2010 * Verify that a validator is actually associated with the language of a
2011 * particular function and that the user has access to both the language and
2012 * the function. All validators should call this before doing anything
2013 * substantial. Doing so ensures a user cannot achieve anything with explicit
2014 * calls to validators that he could not achieve with CREATE FUNCTION or by
2015 * simply calling an existing function.
2016 *
2017 * When this function returns false, callers should skip all validation work
2018 * and call PG_RETURN_VOID(). This never happens at present; it is reserved
2019 * for future expansion.
2020 *
2021 * In particular, checking that the validator corresponds to the function's
2022 * language allows untrusted language validators to assume they process only
2023 * superuser-chosen source code. (Untrusted language call handlers, by
2024 * definition, do assume that.) A user lacking the USAGE language privilege
2025 * would be unable to reach the validator through CREATE FUNCTION, so we check
2026 * that to block explicit calls as well. Checking the EXECUTE privilege on
2027 * the function is often superfluous, because most users can clone the
2028 * function to get an executable copy. It is meaningful against users with no
2029 * database TEMP right and no permanent schema CREATE right, thereby unable to
2030 * create any function. Also, if the function tracks persistent state by
2031 * function OID or name, validating the original function might permit more
2032 * mischief than creating and validating a clone thereof.
2033 */
2034 bool
CheckFunctionValidatorAccess(Oid validatorOid,Oid functionOid)2035 CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
2036 {
2037 HeapTuple procTup;
2038 HeapTuple langTup;
2039 Form_pg_proc procStruct;
2040 Form_pg_language langStruct;
2041 AclResult aclresult;
2042
2043 /*
2044 * Get the function's pg_proc entry. Throw a user-facing error for bad
2045 * OID, because validators can be called with user-specified OIDs.
2046 */
2047 procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionOid));
2048 if (!HeapTupleIsValid(procTup))
2049 ereport(ERROR,
2050 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2051 errmsg("function with OID %u does not exist", functionOid)));
2052 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
2053
2054 /*
2055 * Fetch pg_language entry to know if this is the correct validation
2056 * function for that pg_proc entry.
2057 */
2058 langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(procStruct->prolang));
2059 if (!HeapTupleIsValid(langTup))
2060 elog(ERROR, "cache lookup failed for language %u", procStruct->prolang);
2061 langStruct = (Form_pg_language) GETSTRUCT(langTup);
2062
2063 if (langStruct->lanvalidator != validatorOid)
2064 ereport(ERROR,
2065 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2066 errmsg("language validation function %u called for language %u instead of %u",
2067 validatorOid, procStruct->prolang,
2068 langStruct->lanvalidator)));
2069
2070 /* first validate that we have permissions to use the language */
2071 aclresult = pg_language_aclcheck(procStruct->prolang, GetUserId(),
2072 ACL_USAGE);
2073 if (aclresult != ACLCHECK_OK)
2074 aclcheck_error(aclresult, OBJECT_LANGUAGE,
2075 NameStr(langStruct->lanname));
2076
2077 /*
2078 * Check whether we are allowed to execute the function itself. If we can
2079 * execute it, there should be no possible side-effect of
2080 * compiling/validation that execution can't have.
2081 */
2082 aclresult = pg_proc_aclcheck(functionOid, GetUserId(), ACL_EXECUTE);
2083 if (aclresult != ACLCHECK_OK)
2084 aclcheck_error(aclresult, OBJECT_FUNCTION, NameStr(procStruct->proname));
2085
2086 ReleaseSysCache(procTup);
2087 ReleaseSysCache(langTup);
2088
2089 return true;
2090 }
2091