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