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