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