Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * fmgr.c
4 : * The Postgres function manager.
5 : *
6 : * Portions Copyright (c) 1996-2024, 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 37401640 : fmgr_isbuiltin(Oid id)
77 : {
78 : uint16 index;
79 :
80 : /* fast lookup only possible if original oid still assigned */
81 37401640 : if (id > fmgr_last_builtin_oid)
82 141268 : 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 37260372 : index = fmgr_builtin_oid_index[id];
89 37260372 : if (index == InvalidOidBuiltinMapping)
90 9382 : return NULL;
91 :
92 37250990 : 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 7212 : fmgr_lookupByName(const char *name)
102 : {
103 : int i;
104 :
105 10021364 : for (i = 0; i < fmgr_nbuiltins; i++)
106 : {
107 10021358 : if (strcmp(name, fmgr_builtins[i].funcName) == 0)
108 7206 : 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 34849112 : fmgr_info(Oid functionId, FmgrInfo *finfo)
128 : {
129 34849112 : fmgr_info_cxt_security(functionId, finfo, CurrentMemoryContext, false);
130 34849112 : }
131 :
132 : /*
133 : * Fill a FmgrInfo struct, specifying a memory context in which its
134 : * subsidiary data should go.
135 : */
136 : void
137 2519418 : fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
138 : {
139 2519418 : fmgr_info_cxt_security(functionId, finfo, mcxt, false);
140 2519418 : }
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 37401640 : 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 37401640 : finfo->fn_oid = InvalidOid;
162 37401640 : finfo->fn_extra = NULL;
163 37401640 : finfo->fn_mcxt = mcxt;
164 37401640 : finfo->fn_expr = NULL; /* caller may set this later */
165 :
166 37401640 : if ((fbp = fmgr_isbuiltin(functionId)) != NULL)
167 : {
168 : /*
169 : * Fast path for builtin functions: don't bother consulting pg_proc
170 : */
171 37250990 : finfo->fn_nargs = fbp->nargs;
172 37250990 : finfo->fn_strict = fbp->strict;
173 37250990 : finfo->fn_retset = fbp->retset;
174 37250990 : finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
175 37250990 : finfo->fn_addr = fbp->func;
176 37250990 : finfo->fn_oid = functionId;
177 37250990 : return;
178 : }
179 :
180 : /* Otherwise we need the pg_proc entry */
181 150650 : procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
182 150650 : if (!HeapTupleIsValid(procedureTuple))
183 0 : elog(ERROR, "cache lookup failed for function %u", functionId);
184 150650 : procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
185 :
186 150650 : finfo->fn_nargs = procedureStruct->pronargs;
187 150650 : finfo->fn_strict = procedureStruct->proisstrict;
188 150650 : 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 150650 : if (!ignore_security &&
205 117540 : (procedureStruct->prosecdef ||
206 117268 : !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig, NULL) ||
207 117146 : FmgrHookIsNeeded(functionId)))
208 : {
209 394 : finfo->fn_addr = fmgr_security_definer;
210 394 : finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
211 394 : finfo->fn_oid = functionId;
212 394 : ReleaseSysCache(procedureTuple);
213 394 : return;
214 : }
215 :
216 150256 : switch (procedureStruct->prolang)
217 : {
218 2628 : 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 2628 : prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
230 : Anum_pg_proc_prosrc);
231 2628 : prosrc = TextDatumGetCString(prosrcdatum);
232 2628 : fbp = fmgr_lookupByName(prosrc);
233 2628 : 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 2628 : pfree(prosrc);
239 : /* Should we check that nargs, strict, retset match the table? */
240 2628 : finfo->fn_addr = fbp->func;
241 : /* note this policy is also assumed in fast path above */
242 2628 : finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
243 2628 : break;
244 :
245 95696 : case ClanguageId:
246 95696 : fmgr_info_C_lang(functionId, finfo, procedureTuple);
247 95696 : finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
248 95696 : break;
249 :
250 19204 : case SQLlanguageId:
251 19204 : finfo->fn_addr = fmgr_sql;
252 19204 : finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
253 19204 : break;
254 :
255 32728 : default:
256 32728 : fmgr_info_other_lang(functionId, finfo, procedureTuple);
257 32728 : finfo->fn_stats = TRACK_FUNC_OFF; /* ie, track if not OFF */
258 32728 : break;
259 : }
260 :
261 150256 : finfo->fn_oid = functionId;
262 150256 : 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 6022 : 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 6022 : procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
289 6022 : if (!HeapTupleIsValid(procedureTuple))
290 0 : elog(ERROR, "cache lookup failed for function %u", functionId);
291 6022 : procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
292 :
293 6022 : if (procedureStruct->prosecdef ||
294 6022 : !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig, NULL) ||
295 6022 : 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 6022 : switch (procedureStruct->prolang)
305 : {
306 5998 : case INTERNALlanguageId:
307 5998 : prosrcattr = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
308 : Anum_pg_proc_prosrc);
309 :
310 5998 : *mod = NULL; /* core binary */
311 5998 : *fn = TextDatumGetCString(prosrcattr);
312 5998 : 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 6022 : 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 95696 : 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 95696 : hashentry = lookup_C_func(procedureTuple);
359 95696 : if (hashentry)
360 : {
361 88990 : user_fn = hashentry->user_fn;
362 88990 : 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 6706 : prosrcattr = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
378 : Anum_pg_proc_prosrc);
379 6706 : prosrcstring = TextDatumGetCString(prosrcattr);
380 :
381 6706 : probinattr = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
382 : Anum_pg_proc_probin);
383 6706 : probinstring = TextDatumGetCString(probinattr);
384 :
385 : /* Look up the function itself */
386 6706 : user_fn = load_external_function(probinstring, prosrcstring, true,
387 : &libraryhandle);
388 :
389 : /* Get the function information record (real or default) */
390 6706 : inforec = fetch_finfo_record(libraryhandle, prosrcstring);
391 :
392 : /* Cache the addresses for later calls */
393 6706 : record_C_func(procedureTuple, user_fn, inforec);
394 :
395 6706 : pfree(prosrcstring);
396 6706 : pfree(probinstring);
397 : }
398 :
399 95696 : switch (inforec->api_version)
400 : {
401 95696 : case 1:
402 : /* New style: call directly */
403 95696 : finfo->fn_addr = user_fn;
404 95696 : 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 95696 : }
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 32728 : fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
419 : {
420 32728 : Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
421 32728 : Oid language = procedureStruct->prolang;
422 : HeapTuple languageTuple;
423 : Form_pg_language languageStruct;
424 : FmgrInfo plfinfo;
425 :
426 32728 : languageTuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(language));
427 32728 : if (!HeapTupleIsValid(languageTuple))
428 0 : elog(ERROR, "cache lookup failed for language %u", language);
429 32728 : 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 32728 : fmgr_info_cxt_security(languageStruct->lanplcallfoid, &plfinfo,
437 : CurrentMemoryContext, true);
438 32728 : finfo->fn_addr = plfinfo.fn_addr;
439 :
440 32728 : ReleaseSysCache(languageTuple);
441 32728 : }
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 11700 : fetch_finfo_record(void *filehandle, const char *funcname)
456 : {
457 : char *infofuncname;
458 : PGFInfoFunction infofunc;
459 : const Pg_finfo_record *inforec;
460 :
461 11700 : infofuncname = psprintf("pg_finfo_%s", funcname);
462 :
463 : /* Try to look up the info function */
464 11700 : infofunc = (PGFInfoFunction) lookup_external_function(filehandle,
465 : infofuncname);
466 11700 : 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 11700 : inforec = (*infofunc) ();
478 :
479 : /* Validate result as best we can */
480 11700 : if (inforec == NULL)
481 0 : elog(ERROR, "null result from info function \"%s\"", infofuncname);
482 11700 : switch (inforec->api_version)
483 : {
484 11700 : case 1:
485 : /* OK, no additional fields to validate */
486 11700 : 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 11700 : pfree(infofuncname);
496 11700 : 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 95696 : lookup_C_func(HeapTuple procedureTuple)
516 : {
517 95696 : Oid fn_oid = ((Form_pg_proc) GETSTRUCT(procedureTuple))->oid;
518 : CFuncHashTabEntry *entry;
519 :
520 95696 : if (CFuncHash == NULL)
521 3112 : return NULL; /* no table yet */
522 : entry = (CFuncHashTabEntry *)
523 92584 : hash_search(CFuncHash,
524 : &fn_oid,
525 : HASH_FIND,
526 : NULL);
527 92584 : if (entry == NULL)
528 3592 : return NULL; /* no such entry */
529 177982 : if (entry->fn_xmin == HeapTupleHeaderGetRawXmin(procedureTuple->t_data) &&
530 88990 : ItemPointerEquals(&entry->fn_tid, &procedureTuple->t_self))
531 88990 : return entry; /* OK */
532 2 : 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 6706 : record_C_func(HeapTuple procedureTuple,
540 : PGFunction user_fn, const Pg_finfo_record *inforec)
541 : {
542 6706 : 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 6706 : if (CFuncHash == NULL)
548 : {
549 : HASHCTL hash_ctl;
550 :
551 3112 : hash_ctl.keysize = sizeof(Oid);
552 3112 : hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
553 3112 : CFuncHash = hash_create("CFuncHash",
554 : 100,
555 : &hash_ctl,
556 : HASH_ELEM | HASH_BLOBS);
557 : }
558 :
559 : entry = (CFuncHashTabEntry *)
560 6706 : hash_search(CFuncHash,
561 : &fn_oid,
562 : HASH_ENTER,
563 : &found);
564 : /* OID is already filled in */
565 6706 : entry->fn_xmin = HeapTupleHeaderGetRawXmin(procedureTuple->t_data);
566 6706 : entry->fn_tid = procedureTuple->t_self;
567 6706 : entry->user_fn = user_fn;
568 6706 : entry->inforec = inforec;
569 6706 : }
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 41153960 : fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
581 : MemoryContext destcxt)
582 : {
583 41153960 : memcpy(dstinfo, srcinfo, sizeof(FmgrInfo));
584 41153960 : dstinfo->fn_mcxt = destcxt;
585 41153960 : dstinfo->fn_extra = NULL;
586 41153960 : }
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 4584 : fmgr_internal_function(const char *proname)
596 : {
597 4584 : const FmgrBuiltin *fbp = fmgr_lookupByName(proname);
598 :
599 4584 : if (fbp == NULL)
600 6 : return InvalidOid;
601 4578 : 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 414 : 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 : volatile int save_nestlevel;
643 : PgStat_FunctionCallUsage fcusage;
644 :
645 414 : 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 382 : fcache = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
654 : sizeof(*fcache));
655 :
656 382 : fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo,
657 382 : fcinfo->flinfo->fn_mcxt, true);
658 382 : fcache->flinfo.fn_expr = fcinfo->flinfo->fn_expr;
659 :
660 382 : tuple = SearchSysCache1(PROCOID,
661 382 : ObjectIdGetDatum(fcinfo->flinfo->fn_oid));
662 382 : if (!HeapTupleIsValid(tuple))
663 0 : elog(ERROR, "cache lookup failed for function %u",
664 : fcinfo->flinfo->fn_oid);
665 382 : procedureStruct = (Form_pg_proc) GETSTRUCT(tuple);
666 :
667 382 : if (procedureStruct->prosecdef)
668 272 : fcache->userid = procedureStruct->proowner;
669 :
670 382 : datum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proconfig,
671 : &isnull);
672 382 : if (!isnull)
673 : {
674 : ArrayType *array;
675 : ListCell *lc;
676 :
677 116 : oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
678 116 : array = DatumGetArrayTypeP(datum);
679 116 : TransformGUCArray(array, &fcache->configNames,
680 116 : &fcache->configValues);
681 :
682 : /* transform names to config handles to avoid lookup cost */
683 116 : fcache->configHandles = NIL;
684 232 : foreach(lc, fcache->configNames)
685 : {
686 116 : char *name = (char *) lfirst(lc);
687 :
688 116 : fcache->configHandles = lappend(fcache->configHandles,
689 116 : get_config_handle(name));
690 : }
691 :
692 116 : MemoryContextSwitchTo(oldcxt);
693 : }
694 :
695 382 : ReleaseSysCache(tuple);
696 :
697 382 : fcinfo->flinfo->fn_extra = fcache;
698 : }
699 : else
700 32 : fcache = fcinfo->flinfo->fn_extra;
701 :
702 : /* GetUserIdAndSecContext is cheap enough that no harm in a wasted call */
703 414 : GetUserIdAndSecContext(&save_userid, &save_sec_context);
704 414 : if (fcache->configNames != NIL) /* Need a new GUC nesting level */
705 148 : save_nestlevel = NewGUCNestLevel();
706 : else
707 266 : save_nestlevel = 0; /* keep compiler quiet */
708 :
709 414 : if (OidIsValid(fcache->userid))
710 304 : SetUserIdAndSecContext(fcache->userid,
711 : save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
712 :
713 556 : forthree(lc1, fcache->configNames,
714 : lc2, fcache->configHandles,
715 : lc3, fcache->configValues)
716 : {
717 148 : GucContext context = superuser() ? PGC_SUSET : PGC_USERSET;
718 148 : GucSource source = PGC_S_SESSION;
719 148 : GucAction action = GUC_ACTION_SAVE;
720 148 : char *name = lfirst(lc1);
721 148 : config_handle *handle = lfirst(lc2);
722 148 : char *value = lfirst(lc3);
723 :
724 148 : (void) set_config_with_handle(name, handle, value,
725 : context, source, GetUserId(),
726 : action, true, 0, false);
727 : }
728 :
729 : /* function manager hook */
730 408 : 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 408 : save_flinfo = fcinfo->flinfo;
739 :
740 408 : PG_TRY();
741 : {
742 408 : fcinfo->flinfo = &fcache->flinfo;
743 :
744 : /* See notes in fmgr_info_cxt_security */
745 408 : pgstat_init_function_usage(fcinfo, &fcusage);
746 :
747 408 : 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 386 : pgstat_end_function_usage(&fcusage,
754 386 : (fcinfo->resultinfo == NULL ||
755 386 : !IsA(fcinfo->resultinfo, ReturnSetInfo) ||
756 0 : ((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 386 : PG_END_TRY();
766 :
767 386 : fcinfo->flinfo = save_flinfo;
768 :
769 386 : if (fcache->configNames != NIL)
770 122 : AtEOXact_GUC(true, save_nestlevel);
771 386 : if (OidIsValid(fcache->userid))
772 302 : SetUserIdAndSecContext(save_userid, save_sec_context);
773 386 : if (fmgr_hook)
774 0 : (*fmgr_hook) (FHET_END, &fcache->flinfo, &fcache->arg);
775 :
776 386 : 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 2858338 : DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
793 : {
794 2858338 : LOCAL_FCINFO(fcinfo, 1);
795 : Datum result;
796 :
797 2858338 : InitFunctionCallInfoData(*fcinfo, NULL, 1, collation, NULL, NULL);
798 :
799 2858338 : fcinfo->args[0].value = arg1;
800 2858338 : fcinfo->args[0].isnull = false;
801 :
802 2858338 : result = (*func) (fcinfo);
803 :
804 : /* Check for null result, since caller is clearly not expecting one */
805 2858284 : if (fcinfo->isnull)
806 0 : elog(ERROR, "function %p returned NULL", (void *) func);
807 :
808 2858284 : return result;
809 : }
810 :
811 : Datum
812 39720630 : DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
813 : {
814 39720630 : LOCAL_FCINFO(fcinfo, 2);
815 : Datum result;
816 :
817 39720630 : InitFunctionCallInfoData(*fcinfo, NULL, 2, collation, NULL, NULL);
818 :
819 39720630 : fcinfo->args[0].value = arg1;
820 39720630 : fcinfo->args[0].isnull = false;
821 39720630 : fcinfo->args[1].value = arg2;
822 39720630 : fcinfo->args[1].isnull = false;
823 :
824 39720630 : result = (*func) (fcinfo);
825 :
826 : /* Check for null result, since caller is clearly not expecting one */
827 39720540 : if (fcinfo->isnull)
828 0 : elog(ERROR, "function %p returned NULL", (void *) func);
829 :
830 39720540 : return result;
831 : }
832 :
833 : Datum
834 85150 : DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
835 : Datum arg3)
836 : {
837 85150 : LOCAL_FCINFO(fcinfo, 3);
838 : Datum result;
839 :
840 85150 : InitFunctionCallInfoData(*fcinfo, NULL, 3, collation, NULL, NULL);
841 :
842 85150 : fcinfo->args[0].value = arg1;
843 85150 : fcinfo->args[0].isnull = false;
844 85150 : fcinfo->args[1].value = arg2;
845 85150 : fcinfo->args[1].isnull = false;
846 85150 : fcinfo->args[2].value = arg3;
847 85150 : fcinfo->args[2].isnull = false;
848 :
849 85150 : result = (*func) (fcinfo);
850 :
851 : /* Check for null result, since caller is clearly not expecting one */
852 85112 : if (fcinfo->isnull)
853 0 : elog(ERROR, "function %p returned NULL", (void *) func);
854 :
855 85112 : return result;
856 : }
857 :
858 : Datum
859 1026 : DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
860 : Datum arg3, Datum arg4)
861 : {
862 1026 : LOCAL_FCINFO(fcinfo, 4);
863 : Datum result;
864 :
865 1026 : InitFunctionCallInfoData(*fcinfo, NULL, 4, collation, NULL, NULL);
866 :
867 1026 : fcinfo->args[0].value = arg1;
868 1026 : fcinfo->args[0].isnull = false;
869 1026 : fcinfo->args[1].value = arg2;
870 1026 : fcinfo->args[1].isnull = false;
871 1026 : fcinfo->args[2].value = arg3;
872 1026 : fcinfo->args[2].isnull = false;
873 1026 : fcinfo->args[3].value = arg4;
874 1026 : fcinfo->args[3].isnull = false;
875 :
876 1026 : result = (*func) (fcinfo);
877 :
878 : /* Check for null result, since caller is clearly not expecting one */
879 1026 : if (fcinfo->isnull)
880 0 : elog(ERROR, "function %p returned NULL", (void *) func);
881 :
882 1026 : return result;
883 : }
884 :
885 : Datum
886 4574 : DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
887 : Datum arg3, Datum arg4, Datum arg5)
888 : {
889 4574 : LOCAL_FCINFO(fcinfo, 5);
890 : Datum result;
891 :
892 4574 : InitFunctionCallInfoData(*fcinfo, NULL, 5, collation, NULL, NULL);
893 :
894 4574 : fcinfo->args[0].value = arg1;
895 4574 : fcinfo->args[0].isnull = false;
896 4574 : fcinfo->args[1].value = arg2;
897 4574 : fcinfo->args[1].isnull = false;
898 4574 : fcinfo->args[2].value = arg3;
899 4574 : fcinfo->args[2].isnull = false;
900 4574 : fcinfo->args[3].value = arg4;
901 4574 : fcinfo->args[3].isnull = false;
902 4574 : fcinfo->args[4].value = arg5;
903 4574 : fcinfo->args[4].isnull = false;
904 :
905 4574 : result = (*func) (fcinfo);
906 :
907 : /* Check for null result, since caller is clearly not expecting one */
908 4568 : if (fcinfo->isnull)
909 0 : elog(ERROR, "function %p returned NULL", (void *) func);
910 :
911 4568 : 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 410068 : CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
1086 : {
1087 410068 : LOCAL_FCINFO(fcinfo, 2);
1088 : Datum result;
1089 :
1090 410068 : InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
1091 :
1092 410068 : fcinfo->args[0].value = arg1;
1093 410068 : fcinfo->args[0].isnull = false;
1094 410068 : fcinfo->args[1].value = arg2;
1095 410068 : fcinfo->args[1].isnull = false;
1096 :
1097 410068 : result = (*func) (fcinfo);
1098 :
1099 : /* Check for null result, since caller is clearly not expecting one */
1100 410068 : if (fcinfo->isnull)
1101 0 : elog(ERROR, "function %p returned NULL", (void *) func);
1102 :
1103 410068 : 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 5046776 : FunctionCall0Coll(FmgrInfo *flinfo, Oid collation)
1113 : {
1114 5046776 : LOCAL_FCINFO(fcinfo, 0);
1115 : Datum result;
1116 :
1117 5046776 : InitFunctionCallInfoData(*fcinfo, flinfo, 0, collation, NULL, NULL);
1118 :
1119 5046776 : result = FunctionCallInvoke(fcinfo);
1120 :
1121 : /* Check for null result, since caller is clearly not expecting one */
1122 5046776 : if (fcinfo->isnull)
1123 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1124 :
1125 5046776 : return result;
1126 : }
1127 :
1128 : Datum
1129 66578678 : FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
1130 : {
1131 66578678 : LOCAL_FCINFO(fcinfo, 1);
1132 : Datum result;
1133 :
1134 66578678 : InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL);
1135 :
1136 66578678 : fcinfo->args[0].value = arg1;
1137 66578678 : fcinfo->args[0].isnull = false;
1138 :
1139 66578678 : result = FunctionCallInvoke(fcinfo);
1140 :
1141 : /* Check for null result, since caller is clearly not expecting one */
1142 66578024 : if (fcinfo->isnull)
1143 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1144 :
1145 66578024 : return result;
1146 : }
1147 :
1148 : Datum
1149 483094054 : FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
1150 : {
1151 483094054 : LOCAL_FCINFO(fcinfo, 2);
1152 : Datum result;
1153 :
1154 483094054 : InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
1155 :
1156 483094054 : fcinfo->args[0].value = arg1;
1157 483094054 : fcinfo->args[0].isnull = false;
1158 483094054 : fcinfo->args[1].value = arg2;
1159 483094054 : fcinfo->args[1].isnull = false;
1160 :
1161 483094054 : result = FunctionCallInvoke(fcinfo);
1162 :
1163 : /* Check for null result, since caller is clearly not expecting one */
1164 483093934 : if (fcinfo->isnull)
1165 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1166 :
1167 483093934 : return result;
1168 : }
1169 :
1170 : Datum
1171 48266134 : FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1172 : Datum arg3)
1173 : {
1174 48266134 : LOCAL_FCINFO(fcinfo, 3);
1175 : Datum result;
1176 :
1177 48266134 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, collation, NULL, NULL);
1178 :
1179 48266134 : fcinfo->args[0].value = arg1;
1180 48266134 : fcinfo->args[0].isnull = false;
1181 48266134 : fcinfo->args[1].value = arg2;
1182 48266134 : fcinfo->args[1].isnull = false;
1183 48266134 : fcinfo->args[2].value = arg3;
1184 48266134 : fcinfo->args[2].isnull = false;
1185 :
1186 48266134 : result = FunctionCallInvoke(fcinfo);
1187 :
1188 : /* Check for null result, since caller is clearly not expecting one */
1189 48266134 : if (fcinfo->isnull)
1190 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1191 :
1192 48266134 : return result;
1193 : }
1194 :
1195 : Datum
1196 1768372 : FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1197 : Datum arg3, Datum arg4)
1198 : {
1199 1768372 : LOCAL_FCINFO(fcinfo, 4);
1200 : Datum result;
1201 :
1202 1768372 : InitFunctionCallInfoData(*fcinfo, flinfo, 4, collation, NULL, NULL);
1203 :
1204 1768372 : fcinfo->args[0].value = arg1;
1205 1768372 : fcinfo->args[0].isnull = false;
1206 1768372 : fcinfo->args[1].value = arg2;
1207 1768372 : fcinfo->args[1].isnull = false;
1208 1768372 : fcinfo->args[2].value = arg3;
1209 1768372 : fcinfo->args[2].isnull = false;
1210 1768372 : fcinfo->args[3].value = arg4;
1211 1768372 : fcinfo->args[3].isnull = false;
1212 :
1213 1768372 : result = FunctionCallInvoke(fcinfo);
1214 :
1215 : /* Check for null result, since caller is clearly not expecting one */
1216 1768348 : if (fcinfo->isnull)
1217 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1218 :
1219 1768348 : return result;
1220 : }
1221 :
1222 : Datum
1223 2246886 : FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1224 : Datum arg3, Datum arg4, Datum arg5)
1225 : {
1226 2246886 : LOCAL_FCINFO(fcinfo, 5);
1227 : Datum result;
1228 :
1229 2246886 : InitFunctionCallInfoData(*fcinfo, flinfo, 5, collation, NULL, NULL);
1230 :
1231 2246886 : fcinfo->args[0].value = arg1;
1232 2246886 : fcinfo->args[0].isnull = false;
1233 2246886 : fcinfo->args[1].value = arg2;
1234 2246886 : fcinfo->args[1].isnull = false;
1235 2246886 : fcinfo->args[2].value = arg3;
1236 2246886 : fcinfo->args[2].isnull = false;
1237 2246886 : fcinfo->args[3].value = arg4;
1238 2246886 : fcinfo->args[3].isnull = false;
1239 2246886 : fcinfo->args[4].value = arg5;
1240 2246886 : fcinfo->args[4].isnull = false;
1241 :
1242 2246886 : result = FunctionCallInvoke(fcinfo);
1243 :
1244 : /* Check for null result, since caller is clearly not expecting one */
1245 2246790 : if (fcinfo->isnull)
1246 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1247 :
1248 2246790 : return result;
1249 : }
1250 :
1251 : Datum
1252 6886 : FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1253 : Datum arg3, Datum arg4, Datum arg5,
1254 : Datum arg6)
1255 : {
1256 6886 : LOCAL_FCINFO(fcinfo, 6);
1257 : Datum result;
1258 :
1259 6886 : InitFunctionCallInfoData(*fcinfo, flinfo, 6, collation, NULL, NULL);
1260 :
1261 6886 : fcinfo->args[0].value = arg1;
1262 6886 : fcinfo->args[0].isnull = false;
1263 6886 : fcinfo->args[1].value = arg2;
1264 6886 : fcinfo->args[1].isnull = false;
1265 6886 : fcinfo->args[2].value = arg3;
1266 6886 : fcinfo->args[2].isnull = false;
1267 6886 : fcinfo->args[3].value = arg4;
1268 6886 : fcinfo->args[3].isnull = false;
1269 6886 : fcinfo->args[4].value = arg5;
1270 6886 : fcinfo->args[4].isnull = false;
1271 6886 : fcinfo->args[5].value = arg6;
1272 6886 : fcinfo->args[5].isnull = false;
1273 :
1274 6886 : result = FunctionCallInvoke(fcinfo);
1275 :
1276 : /* Check for null result, since caller is clearly not expecting one */
1277 4546 : if (fcinfo->isnull)
1278 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1279 :
1280 4546 : return result;
1281 : }
1282 :
1283 : Datum
1284 972882 : FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1285 : Datum arg3, Datum arg4, Datum arg5,
1286 : Datum arg6, Datum arg7)
1287 : {
1288 972882 : LOCAL_FCINFO(fcinfo, 7);
1289 : Datum result;
1290 :
1291 972882 : InitFunctionCallInfoData(*fcinfo, flinfo, 7, collation, NULL, NULL);
1292 :
1293 972882 : fcinfo->args[0].value = arg1;
1294 972882 : fcinfo->args[0].isnull = false;
1295 972882 : fcinfo->args[1].value = arg2;
1296 972882 : fcinfo->args[1].isnull = false;
1297 972882 : fcinfo->args[2].value = arg3;
1298 972882 : fcinfo->args[2].isnull = false;
1299 972882 : fcinfo->args[3].value = arg4;
1300 972882 : fcinfo->args[3].isnull = false;
1301 972882 : fcinfo->args[4].value = arg5;
1302 972882 : fcinfo->args[4].isnull = false;
1303 972882 : fcinfo->args[5].value = arg6;
1304 972882 : fcinfo->args[5].isnull = false;
1305 972882 : fcinfo->args[6].value = arg7;
1306 972882 : fcinfo->args[6].isnull = false;
1307 :
1308 972882 : result = FunctionCallInvoke(fcinfo);
1309 :
1310 : /* Check for null result, since caller is clearly not expecting one */
1311 972882 : if (fcinfo->isnull)
1312 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1313 :
1314 972882 : return result;
1315 : }
1316 :
1317 : Datum
1318 37454 : 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 37454 : LOCAL_FCINFO(fcinfo, 8);
1323 : Datum result;
1324 :
1325 37454 : InitFunctionCallInfoData(*fcinfo, flinfo, 8, collation, NULL, NULL);
1326 :
1327 37454 : fcinfo->args[0].value = arg1;
1328 37454 : fcinfo->args[0].isnull = false;
1329 37454 : fcinfo->args[1].value = arg2;
1330 37454 : fcinfo->args[1].isnull = false;
1331 37454 : fcinfo->args[2].value = arg3;
1332 37454 : fcinfo->args[2].isnull = false;
1333 37454 : fcinfo->args[3].value = arg4;
1334 37454 : fcinfo->args[3].isnull = false;
1335 37454 : fcinfo->args[4].value = arg5;
1336 37454 : fcinfo->args[4].isnull = false;
1337 37454 : fcinfo->args[5].value = arg6;
1338 37454 : fcinfo->args[5].isnull = false;
1339 37454 : fcinfo->args[6].value = arg7;
1340 37454 : fcinfo->args[6].isnull = false;
1341 37454 : fcinfo->args[7].value = arg8;
1342 37454 : fcinfo->args[7].isnull = false;
1343 :
1344 37454 : result = FunctionCallInvoke(fcinfo);
1345 :
1346 : /* Check for null result, since caller is clearly not expecting one */
1347 37454 : if (fcinfo->isnull)
1348 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1349 :
1350 37454 : 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 5046776 : OidFunctionCall0Coll(Oid functionId, Oid collation)
1402 : {
1403 : FmgrInfo flinfo;
1404 :
1405 5046776 : fmgr_info(functionId, &flinfo);
1406 :
1407 5046776 : return FunctionCall0Coll(&flinfo, collation);
1408 : }
1409 :
1410 : Datum
1411 628410 : OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
1412 : {
1413 : FmgrInfo flinfo;
1414 :
1415 628410 : fmgr_info(functionId, &flinfo);
1416 :
1417 628410 : return FunctionCall1Coll(&flinfo, collation, arg1);
1418 : }
1419 :
1420 : Datum
1421 1114 : OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
1422 : {
1423 : FmgrInfo flinfo;
1424 :
1425 1114 : fmgr_info(functionId, &flinfo);
1426 :
1427 1114 : 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 616938 : OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1443 : Datum arg3, Datum arg4)
1444 : {
1445 : FmgrInfo flinfo;
1446 :
1447 616938 : fmgr_info(functionId, &flinfo);
1448 :
1449 616938 : return FunctionCall4Coll(&flinfo, collation, arg1, arg2, arg3, arg4);
1450 : }
1451 :
1452 : Datum
1453 198860 : OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1454 : Datum arg3, Datum arg4, Datum arg5)
1455 : {
1456 : FmgrInfo flinfo;
1457 :
1458 198860 : fmgr_info(functionId, &flinfo);
1459 :
1460 198860 : return FunctionCall5Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5);
1461 : }
1462 :
1463 : Datum
1464 6538 : 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 6538 : fmgr_info(functionId, &flinfo);
1471 :
1472 6538 : 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 35530866 : InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
1531 : {
1532 35530866 : LOCAL_FCINFO(fcinfo, 3);
1533 : Datum result;
1534 :
1535 35530866 : if (str == NULL && flinfo->fn_strict)
1536 7291054 : return (Datum) 0; /* just return null result */
1537 :
1538 28239812 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
1539 :
1540 28239812 : fcinfo->args[0].value = CStringGetDatum(str);
1541 28239812 : fcinfo->args[0].isnull = false;
1542 28239812 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1543 28239812 : fcinfo->args[1].isnull = false;
1544 28239812 : fcinfo->args[2].value = Int32GetDatum(typmod);
1545 28239812 : fcinfo->args[2].isnull = false;
1546 :
1547 28239812 : result = FunctionCallInvoke(fcinfo);
1548 :
1549 : /* Should get null result if and only if str is NULL */
1550 28235196 : 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 28235196 : if (fcinfo->isnull)
1559 0 : elog(ERROR, "input function %u returned NULL",
1560 : flinfo->fn_oid);
1561 : }
1562 :
1563 28235196 : 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 5922372 : InputFunctionCallSafe(FmgrInfo *flinfo, char *str,
1586 : Oid typioparam, int32 typmod,
1587 : fmNodePtr escontext,
1588 : Datum *result)
1589 : {
1590 5922372 : LOCAL_FCINFO(fcinfo, 3);
1591 :
1592 5922372 : if (str == NULL && flinfo->fn_strict)
1593 : {
1594 5910 : *result = (Datum) 0; /* just return null result */
1595 5910 : return true;
1596 : }
1597 :
1598 5916462 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, escontext, NULL);
1599 :
1600 5916462 : fcinfo->args[0].value = CStringGetDatum(str);
1601 5916462 : fcinfo->args[0].isnull = false;
1602 5916462 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1603 5916462 : fcinfo->args[1].isnull = false;
1604 5916462 : fcinfo->args[2].value = Int32GetDatum(typmod);
1605 5916462 : fcinfo->args[2].isnull = false;
1606 :
1607 5916462 : *result = FunctionCallInvoke(fcinfo);
1608 :
1609 : /* Result value is garbage, and could be null, if an error was reported */
1610 5916138 : if (SOFT_ERROR_OCCURRED(escontext))
1611 1794 : return false;
1612 :
1613 : /* Otherwise, should get null result if and only if str is NULL */
1614 5914344 : 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 5914308 : if (fcinfo->isnull)
1623 0 : elog(ERROR, "input function %u returned NULL",
1624 : flinfo->fn_oid);
1625 : }
1626 :
1627 5914344 : 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 730224 : DirectInputFunctionCallSafe(PGFunction func, char *str,
1641 : Oid typioparam, int32 typmod,
1642 : fmNodePtr escontext,
1643 : Datum *result)
1644 : {
1645 730224 : LOCAL_FCINFO(fcinfo, 3);
1646 :
1647 730224 : if (str == NULL)
1648 : {
1649 0 : *result = (Datum) 0; /* just return null result */
1650 0 : return true;
1651 : }
1652 :
1653 730224 : InitFunctionCallInfoData(*fcinfo, NULL, 3, InvalidOid, escontext, NULL);
1654 :
1655 730224 : fcinfo->args[0].value = CStringGetDatum(str);
1656 730224 : fcinfo->args[0].isnull = false;
1657 730224 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1658 730224 : fcinfo->args[1].isnull = false;
1659 730224 : fcinfo->args[2].value = Int32GetDatum(typmod);
1660 730224 : fcinfo->args[2].isnull = false;
1661 :
1662 730224 : *result = (*func) (fcinfo);
1663 :
1664 : /* Result value is garbage, and could be null, if an error was reported */
1665 730224 : if (SOFT_ERROR_OCCURRED(escontext))
1666 288 : return false;
1667 :
1668 : /* Otherwise, shouldn't get null result */
1669 729936 : if (fcinfo->isnull)
1670 0 : elog(ERROR, "input function %p returned NULL", (void *) func);
1671 :
1672 729936 : 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 42767212 : OutputFunctionCall(FmgrInfo *flinfo, Datum val)
1684 : {
1685 42767212 : 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 312090 : ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
1698 : Oid typioparam, int32 typmod)
1699 : {
1700 312090 : LOCAL_FCINFO(fcinfo, 3);
1701 : Datum result;
1702 :
1703 312090 : if (buf == NULL && flinfo->fn_strict)
1704 30 : return (Datum) 0; /* just return null result */
1705 :
1706 312060 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
1707 :
1708 312060 : fcinfo->args[0].value = PointerGetDatum(buf);
1709 312060 : fcinfo->args[0].isnull = false;
1710 312060 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1711 312060 : fcinfo->args[1].isnull = false;
1712 312060 : fcinfo->args[2].value = Int32GetDatum(typmod);
1713 312060 : fcinfo->args[2].isnull = false;
1714 :
1715 312060 : result = FunctionCallInvoke(fcinfo);
1716 :
1717 : /* Should get null result if and only if buf is NULL */
1718 312060 : 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 312060 : if (fcinfo->isnull)
1727 0 : elog(ERROR, "receive function %u returned NULL",
1728 : flinfo->fn_oid);
1729 : }
1730 :
1731 312060 : 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 247122 : SendFunctionCall(FmgrInfo *flinfo, Datum val)
1745 : {
1746 247122 : 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 12548076 : OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
1755 : {
1756 : FmgrInfo flinfo;
1757 :
1758 12548076 : fmgr_info(functionId, &flinfo);
1759 12548076 : return InputFunctionCall(&flinfo, str, typioparam, typmod);
1760 : }
1761 :
1762 : char *
1763 1046176 : OidOutputFunctionCall(Oid functionId, Datum val)
1764 : {
1765 : FmgrInfo flinfo;
1766 :
1767 1046176 : fmgr_info(functionId, &flinfo);
1768 1046176 : return OutputFunctionCall(&flinfo, val);
1769 : }
1770 :
1771 : Datum
1772 311746 : OidReceiveFunctionCall(Oid functionId, StringInfo buf,
1773 : Oid typioparam, int32 typmod)
1774 : {
1775 : FmgrInfo flinfo;
1776 :
1777 311746 : fmgr_info(functionId, &flinfo);
1778 311746 : return ReceiveFunctionCall(&flinfo, buf, typioparam, typmod);
1779 : }
1780 :
1781 : bytea *
1782 232170 : OidSendFunctionCall(Oid functionId, Datum val)
1783 : {
1784 : FmgrInfo flinfo;
1785 :
1786 232170 : fmgr_info(functionId, &flinfo);
1787 232170 : return SendFunctionCall(&flinfo, val);
1788 : }
1789 :
1790 :
1791 : /*-------------------------------------------------------------------------
1792 : * Support routines for standard maybe-pass-by-reference datatypes
1793 : *
1794 : * int8 and float8 can be passed by value if Datum is wide enough.
1795 : * (For backwards-compatibility reasons, we allow pass-by-ref to be chosen
1796 : * at compile time even if pass-by-val is possible.)
1797 : *
1798 : * Note: there is only one switch controlling the pass-by-value option for
1799 : * both int8 and float8; this is to avoid making things unduly complicated
1800 : * for the timestamp types, which might have either representation.
1801 : *-------------------------------------------------------------------------
1802 : */
1803 :
1804 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
1805 :
1806 : Datum
1807 : Int64GetDatum(int64 X)
1808 : {
1809 : int64 *retval = (int64 *) palloc(sizeof(int64));
1810 :
1811 : *retval = X;
1812 : return PointerGetDatum(retval);
1813 : }
1814 :
1815 : Datum
1816 : Float8GetDatum(float8 X)
1817 : {
1818 : float8 *retval = (float8 *) palloc(sizeof(float8));
1819 :
1820 : *retval = X;
1821 : return PointerGetDatum(retval);
1822 : }
1823 : #endif /* USE_FLOAT8_BYVAL */
1824 :
1825 :
1826 : /*-------------------------------------------------------------------------
1827 : * Support routines for toastable datatypes
1828 : *-------------------------------------------------------------------------
1829 : */
1830 :
1831 : struct varlena *
1832 89060156 : pg_detoast_datum(struct varlena *datum)
1833 : {
1834 89060156 : if (VARATT_IS_EXTENDED(datum))
1835 23490512 : return detoast_attr(datum);
1836 : else
1837 65569644 : return datum;
1838 : }
1839 :
1840 : struct varlena *
1841 5277002 : pg_detoast_datum_copy(struct varlena *datum)
1842 : {
1843 5277002 : if (VARATT_IS_EXTENDED(datum))
1844 2847128 : return detoast_attr(datum);
1845 : else
1846 : {
1847 : /* Make a modifiable copy of the varlena object */
1848 2429874 : Size len = VARSIZE(datum);
1849 2429874 : struct varlena *result = (struct varlena *) palloc(len);
1850 :
1851 2429874 : memcpy(result, datum, len);
1852 2429874 : return result;
1853 : }
1854 : }
1855 :
1856 : struct varlena *
1857 4356 : pg_detoast_datum_slice(struct varlena *datum, int32 first, int32 count)
1858 : {
1859 : /* Only get the specified portion from the toast rel */
1860 4356 : return detoast_attr_slice(datum, first, count);
1861 : }
1862 :
1863 : struct varlena *
1864 200039554 : pg_detoast_datum_packed(struct varlena *datum)
1865 : {
1866 200039554 : if (VARATT_IS_COMPRESSED(datum) || VARATT_IS_EXTERNAL(datum))
1867 48450 : return detoast_attr(datum);
1868 : else
1869 199991104 : return datum;
1870 : }
1871 :
1872 : /*-------------------------------------------------------------------------
1873 : * Support routines for extracting info from fn_expr parse tree
1874 : *
1875 : * These are needed by polymorphic functions, which accept multiple possible
1876 : * input types and need help from the parser to know what they've got.
1877 : * Also, some functions might be interested in whether a parameter is constant.
1878 : * Functions taking VARIADIC ANY also need to know about the VARIADIC keyword.
1879 : *-------------------------------------------------------------------------
1880 : */
1881 :
1882 : /*
1883 : * Get the actual type OID of the function return type
1884 : *
1885 : * Returns InvalidOid if information is not available
1886 : */
1887 : Oid
1888 138294 : get_fn_expr_rettype(FmgrInfo *flinfo)
1889 : {
1890 : Node *expr;
1891 :
1892 : /*
1893 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
1894 : * node has not been initialized
1895 : */
1896 138294 : if (!flinfo || !flinfo->fn_expr)
1897 0 : return InvalidOid;
1898 :
1899 138294 : expr = flinfo->fn_expr;
1900 :
1901 138294 : return exprType(expr);
1902 : }
1903 :
1904 : /*
1905 : * Get the actual type OID of a specific function argument (counting from 0)
1906 : *
1907 : * Returns InvalidOid if information is not available
1908 : */
1909 : Oid
1910 1992876 : get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
1911 : {
1912 : /*
1913 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
1914 : * node has not been initialized
1915 : */
1916 1992876 : if (!flinfo || !flinfo->fn_expr)
1917 0 : return InvalidOid;
1918 :
1919 1992876 : return get_call_expr_argtype(flinfo->fn_expr, argnum);
1920 : }
1921 :
1922 : /*
1923 : * Get the actual type OID of a specific function argument (counting from 0),
1924 : * but working from the calling expression tree instead of FmgrInfo
1925 : *
1926 : * Returns InvalidOid if information is not available
1927 : */
1928 : Oid
1929 1999592 : get_call_expr_argtype(Node *expr, int argnum)
1930 : {
1931 : List *args;
1932 : Oid argtype;
1933 :
1934 1999592 : if (expr == NULL)
1935 0 : return InvalidOid;
1936 :
1937 1999592 : if (IsA(expr, FuncExpr))
1938 1999550 : args = ((FuncExpr *) expr)->args;
1939 42 : else if (IsA(expr, OpExpr))
1940 42 : args = ((OpExpr *) expr)->args;
1941 0 : else if (IsA(expr, DistinctExpr))
1942 0 : args = ((DistinctExpr *) expr)->args;
1943 0 : else if (IsA(expr, ScalarArrayOpExpr))
1944 0 : args = ((ScalarArrayOpExpr *) expr)->args;
1945 0 : else if (IsA(expr, NullIfExpr))
1946 0 : args = ((NullIfExpr *) expr)->args;
1947 0 : else if (IsA(expr, WindowFunc))
1948 0 : args = ((WindowFunc *) expr)->args;
1949 : else
1950 0 : return InvalidOid;
1951 :
1952 1999592 : if (argnum < 0 || argnum >= list_length(args))
1953 0 : return InvalidOid;
1954 :
1955 1999592 : argtype = exprType((Node *) list_nth(args, argnum));
1956 :
1957 : /*
1958 : * special hack for ScalarArrayOpExpr: what the underlying function will
1959 : * actually get passed is the element type of the array.
1960 : */
1961 1999592 : if (IsA(expr, ScalarArrayOpExpr) &&
1962 : argnum == 1)
1963 0 : argtype = get_base_element_type(argtype);
1964 :
1965 1999592 : return argtype;
1966 : }
1967 :
1968 : /*
1969 : * Find out whether a specific function argument is constant for the
1970 : * duration of a query
1971 : *
1972 : * Returns false if information is not available
1973 : */
1974 : bool
1975 5282 : get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
1976 : {
1977 : /*
1978 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
1979 : * node has not been initialized
1980 : */
1981 5282 : if (!flinfo || !flinfo->fn_expr)
1982 0 : return false;
1983 :
1984 5282 : return get_call_expr_arg_stable(flinfo->fn_expr, argnum);
1985 : }
1986 :
1987 : /*
1988 : * Find out whether a specific function argument is constant for the
1989 : * duration of a query, but working from the calling expression tree
1990 : *
1991 : * Returns false if information is not available
1992 : */
1993 : bool
1994 5282 : get_call_expr_arg_stable(Node *expr, int argnum)
1995 : {
1996 : List *args;
1997 : Node *arg;
1998 :
1999 5282 : if (expr == NULL)
2000 0 : return false;
2001 :
2002 5282 : if (IsA(expr, FuncExpr))
2003 4256 : args = ((FuncExpr *) expr)->args;
2004 1026 : else if (IsA(expr, OpExpr))
2005 0 : args = ((OpExpr *) expr)->args;
2006 1026 : else if (IsA(expr, DistinctExpr))
2007 0 : args = ((DistinctExpr *) expr)->args;
2008 1026 : else if (IsA(expr, ScalarArrayOpExpr))
2009 0 : args = ((ScalarArrayOpExpr *) expr)->args;
2010 1026 : else if (IsA(expr, NullIfExpr))
2011 0 : args = ((NullIfExpr *) expr)->args;
2012 1026 : else if (IsA(expr, WindowFunc))
2013 1026 : args = ((WindowFunc *) expr)->args;
2014 : else
2015 0 : return false;
2016 :
2017 5282 : if (argnum < 0 || argnum >= list_length(args))
2018 0 : return false;
2019 :
2020 5282 : arg = (Node *) list_nth(args, argnum);
2021 :
2022 : /*
2023 : * Either a true Const or an external Param will have a value that doesn't
2024 : * change during the execution of the query. In future we might want to
2025 : * consider other cases too, e.g. now().
2026 : */
2027 5282 : if (IsA(arg, Const))
2028 4974 : return true;
2029 308 : if (IsA(arg, Param) &&
2030 4 : ((Param *) arg)->paramkind == PARAM_EXTERN)
2031 0 : return true;
2032 :
2033 308 : return false;
2034 : }
2035 :
2036 : /*
2037 : * Get the VARIADIC flag from the function invocation
2038 : *
2039 : * Returns false (the default assumption) if information is not available
2040 : *
2041 : * Note this is generally only of interest to VARIADIC ANY functions
2042 : */
2043 : bool
2044 33362 : get_fn_expr_variadic(FmgrInfo *flinfo)
2045 : {
2046 : Node *expr;
2047 :
2048 : /*
2049 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
2050 : * node has not been initialized
2051 : */
2052 33362 : if (!flinfo || !flinfo->fn_expr)
2053 0 : return false;
2054 :
2055 33362 : expr = flinfo->fn_expr;
2056 :
2057 33362 : if (IsA(expr, FuncExpr))
2058 33362 : return ((FuncExpr *) expr)->funcvariadic;
2059 : else
2060 0 : return false;
2061 : }
2062 :
2063 : /*
2064 : * Set options to FmgrInfo of opclass support function.
2065 : *
2066 : * Opclass support functions are called outside of expressions. Thanks to that
2067 : * we can use fn_expr to store opclass options as bytea constant.
2068 : */
2069 : void
2070 1112916 : set_fn_opclass_options(FmgrInfo *flinfo, bytea *options)
2071 : {
2072 1112916 : flinfo->fn_expr = (Node *) makeConst(BYTEAOID, -1, InvalidOid, -1,
2073 : PointerGetDatum(options),
2074 : options == NULL, false);
2075 1112916 : }
2076 :
2077 : /*
2078 : * Check if options are defined for opclass support function.
2079 : */
2080 : bool
2081 5414516 : has_fn_opclass_options(FmgrInfo *flinfo)
2082 : {
2083 5414516 : if (flinfo && flinfo->fn_expr && IsA(flinfo->fn_expr, Const))
2084 : {
2085 5414516 : Const *expr = (Const *) flinfo->fn_expr;
2086 :
2087 5414516 : if (expr->consttype == BYTEAOID)
2088 5414516 : return !expr->constisnull;
2089 : }
2090 0 : return false;
2091 : }
2092 :
2093 : /*
2094 : * Get options for opclass support function.
2095 : */
2096 : bytea *
2097 5622818 : get_fn_opclass_options(FmgrInfo *flinfo)
2098 : {
2099 5622818 : if (flinfo && flinfo->fn_expr && IsA(flinfo->fn_expr, Const))
2100 : {
2101 5622818 : Const *expr = (Const *) flinfo->fn_expr;
2102 :
2103 5622818 : if (expr->consttype == BYTEAOID)
2104 5622818 : return expr->constisnull ? NULL : DatumGetByteaP(expr->constvalue);
2105 : }
2106 :
2107 0 : ereport(ERROR,
2108 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2109 : errmsg("operator class options info is absent in function call context")));
2110 :
2111 : return NULL;
2112 : }
2113 :
2114 : /*-------------------------------------------------------------------------
2115 : * Support routines for procedural language implementations
2116 : *-------------------------------------------------------------------------
2117 : */
2118 :
2119 : /*
2120 : * Verify that a validator is actually associated with the language of a
2121 : * particular function and that the user has access to both the language and
2122 : * the function. All validators should call this before doing anything
2123 : * substantial. Doing so ensures a user cannot achieve anything with explicit
2124 : * calls to validators that he could not achieve with CREATE FUNCTION or by
2125 : * simply calling an existing function.
2126 : *
2127 : * When this function returns false, callers should skip all validation work
2128 : * and call PG_RETURN_VOID(). This never happens at present; it is reserved
2129 : * for future expansion.
2130 : *
2131 : * In particular, checking that the validator corresponds to the function's
2132 : * language allows untrusted language validators to assume they process only
2133 : * superuser-chosen source code. (Untrusted language call handlers, by
2134 : * definition, do assume that.) A user lacking the USAGE language privilege
2135 : * would be unable to reach the validator through CREATE FUNCTION, so we check
2136 : * that to block explicit calls as well. Checking the EXECUTE privilege on
2137 : * the function is often superfluous, because most users can clone the
2138 : * function to get an executable copy. It is meaningful against users with no
2139 : * database TEMP right and no permanent schema CREATE right, thereby unable to
2140 : * create any function. Also, if the function tracks persistent state by
2141 : * function OID or name, validating the original function might permit more
2142 : * mischief than creating and validating a clone thereof.
2143 : */
2144 : bool
2145 22536 : CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
2146 : {
2147 : HeapTuple procTup;
2148 : HeapTuple langTup;
2149 : Form_pg_proc procStruct;
2150 : Form_pg_language langStruct;
2151 : AclResult aclresult;
2152 :
2153 : /*
2154 : * Get the function's pg_proc entry. Throw a user-facing error for bad
2155 : * OID, because validators can be called with user-specified OIDs.
2156 : */
2157 22536 : procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionOid));
2158 22536 : if (!HeapTupleIsValid(procTup))
2159 0 : ereport(ERROR,
2160 : (errcode(ERRCODE_UNDEFINED_FUNCTION),
2161 : errmsg("function with OID %u does not exist", functionOid)));
2162 22536 : procStruct = (Form_pg_proc) GETSTRUCT(procTup);
2163 :
2164 : /*
2165 : * Fetch pg_language entry to know if this is the correct validation
2166 : * function for that pg_proc entry.
2167 : */
2168 22536 : langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(procStruct->prolang));
2169 22536 : if (!HeapTupleIsValid(langTup))
2170 0 : elog(ERROR, "cache lookup failed for language %u", procStruct->prolang);
2171 22536 : langStruct = (Form_pg_language) GETSTRUCT(langTup);
2172 :
2173 22536 : if (langStruct->lanvalidator != validatorOid)
2174 0 : ereport(ERROR,
2175 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2176 : errmsg("language validation function %u called for language %u instead of %u",
2177 : validatorOid, procStruct->prolang,
2178 : langStruct->lanvalidator)));
2179 :
2180 : /* first validate that we have permissions to use the language */
2181 22536 : aclresult = object_aclcheck(LanguageRelationId, procStruct->prolang, GetUserId(),
2182 : ACL_USAGE);
2183 22536 : if (aclresult != ACLCHECK_OK)
2184 0 : aclcheck_error(aclresult, OBJECT_LANGUAGE,
2185 0 : NameStr(langStruct->lanname));
2186 :
2187 : /*
2188 : * Check whether we are allowed to execute the function itself. If we can
2189 : * execute it, there should be no possible side-effect of
2190 : * compiling/validation that execution can't have.
2191 : */
2192 22536 : aclresult = object_aclcheck(ProcedureRelationId, functionOid, GetUserId(), ACL_EXECUTE);
2193 22536 : if (aclresult != ACLCHECK_OK)
2194 0 : aclcheck_error(aclresult, OBJECT_FUNCTION, NameStr(procStruct->proname));
2195 :
2196 22536 : ReleaseSysCache(procTup);
2197 22536 : ReleaseSysCache(langTup);
2198 :
2199 22536 : return true;
2200 : }
|