Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * fmgr.c
4 : * The Postgres function manager.
5 : *
6 : * Portions Copyright (c) 1996-2023, 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 28233346 : fmgr_isbuiltin(Oid id)
77 : {
78 : uint16 index;
79 :
80 : /* fast lookup only possible if original oid still assigned */
81 28233346 : if (id > fmgr_last_builtin_oid)
82 126002 : 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 28107344 : index = fmgr_builtin_oid_index[id];
89 28107344 : if (index == InvalidOidBuiltinMapping)
90 9068 : return NULL;
91 :
92 28098276 : 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 5560 : fmgr_lookupByName(const char *name)
102 : {
103 : int i;
104 :
105 6570884 : for (i = 0; i < fmgr_nbuiltins; i++)
106 : {
107 6570878 : if (strcmp(name, fmgr_builtins[i].funcName) == 0)
108 5554 : 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 26324580 : fmgr_info(Oid functionId, FmgrInfo *finfo)
128 : {
129 26324580 : fmgr_info_cxt_security(functionId, finfo, CurrentMemoryContext, false);
130 26324580 : }
131 :
132 : /*
133 : * Fill a FmgrInfo struct, specifying a memory context in which its
134 : * subsidiary data should go.
135 : */
136 : void
137 1879360 : fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
138 : {
139 1879360 : fmgr_info_cxt_security(functionId, finfo, mcxt, false);
140 1879360 : }
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 28233346 : 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 28233346 : finfo->fn_oid = InvalidOid;
162 28233346 : finfo->fn_extra = NULL;
163 28233346 : finfo->fn_mcxt = mcxt;
164 28233346 : finfo->fn_expr = NULL; /* caller may set this later */
165 :
166 28233346 : if ((fbp = fmgr_isbuiltin(functionId)) != NULL)
167 : {
168 : /*
169 : * Fast path for builtin functions: don't bother consulting pg_proc
170 : */
171 28098276 : finfo->fn_nargs = fbp->nargs;
172 28098276 : finfo->fn_strict = fbp->strict;
173 28098276 : finfo->fn_retset = fbp->retset;
174 28098276 : finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
175 28098276 : finfo->fn_addr = fbp->func;
176 28098276 : finfo->fn_oid = functionId;
177 28098276 : return;
178 : }
179 :
180 : /* Otherwise we need the pg_proc entry */
181 135070 : procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
182 135070 : if (!HeapTupleIsValid(procedureTuple))
183 0 : elog(ERROR, "cache lookup failed for function %u", functionId);
184 135070 : procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
185 :
186 135070 : finfo->fn_nargs = procedureStruct->pronargs;
187 135070 : finfo->fn_strict = procedureStruct->proisstrict;
188 135070 : 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 135070 : if (!ignore_security &&
205 105664 : (procedureStruct->prosecdef ||
206 105648 : !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig, NULL) ||
207 105604 : FmgrHookIsNeeded(functionId)))
208 : {
209 60 : finfo->fn_addr = fmgr_security_definer;
210 60 : finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
211 60 : finfo->fn_oid = functionId;
212 60 : ReleaseSysCache(procedureTuple);
213 60 : return;
214 : }
215 :
216 135010 : switch (procedureStruct->prolang)
217 : {
218 2514 : 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 2514 : prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
230 : Anum_pg_proc_prosrc);
231 2514 : prosrc = TextDatumGetCString(prosrcdatum);
232 2514 : fbp = fmgr_lookupByName(prosrc);
233 2514 : 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 2514 : pfree(prosrc);
239 : /* Should we check that nargs, strict, retset match the table? */
240 2514 : finfo->fn_addr = fbp->func;
241 : /* note this policy is also assumed in fast path above */
242 2514 : finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
243 2514 : break;
244 :
245 86296 : case ClanguageId:
246 86296 : fmgr_info_C_lang(functionId, finfo, procedureTuple);
247 86296 : finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
248 86296 : break;
249 :
250 16854 : case SQLlanguageId:
251 16854 : finfo->fn_addr = fmgr_sql;
252 16854 : finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
253 16854 : break;
254 :
255 29346 : default:
256 29346 : fmgr_info_other_lang(functionId, finfo, procedureTuple);
257 29346 : finfo->fn_stats = TRACK_FUNC_OFF; /* ie, track if not OFF */
258 29346 : break;
259 : }
260 :
261 135010 : finfo->fn_oid = functionId;
262 135010 : 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 5542 : 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 5542 : procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
289 5542 : if (!HeapTupleIsValid(procedureTuple))
290 0 : elog(ERROR, "cache lookup failed for function %u", functionId);
291 5542 : procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
292 :
293 5542 : if (procedureStruct->prosecdef ||
294 5542 : !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig, NULL) ||
295 5542 : 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 5542 : switch (procedureStruct->prolang)
305 : {
306 5496 : case INTERNALlanguageId:
307 5496 : prosrcattr = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
308 : Anum_pg_proc_prosrc);
309 :
310 5496 : *mod = NULL; /* core binary */
311 5496 : *fn = TextDatumGetCString(prosrcattr);
312 5496 : break;
313 :
314 38 : case ClanguageId:
315 38 : prosrcattr = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
316 : Anum_pg_proc_prosrc);
317 :
318 38 : 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 38 : *mod = TextDatumGetCString(probinattr);
326 38 : *fn = TextDatumGetCString(prosrcattr);
327 38 : break;
328 :
329 4 : case SQLlanguageId:
330 4 : *mod = NULL; /* core binary */
331 4 : *fn = pstrdup("fmgr_sql");
332 4 : break;
333 :
334 4 : default:
335 4 : *mod = NULL;
336 4 : *fn = NULL; /* unknown, pass pointer */
337 4 : break;
338 : }
339 :
340 5542 : 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 86296 : 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 86296 : hashentry = lookup_C_func(procedureTuple);
359 86296 : if (hashentry)
360 : {
361 80664 : user_fn = hashentry->user_fn;
362 80664 : 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 5632 : prosrcattr = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
378 : Anum_pg_proc_prosrc);
379 5632 : prosrcstring = TextDatumGetCString(prosrcattr);
380 :
381 5632 : probinattr = SysCacheGetAttrNotNull(PROCOID, procedureTuple,
382 : Anum_pg_proc_probin);
383 5632 : probinstring = TextDatumGetCString(probinattr);
384 :
385 : /* Look up the function itself */
386 5632 : user_fn = load_external_function(probinstring, prosrcstring, true,
387 : &libraryhandle);
388 :
389 : /* Get the function information record (real or default) */
390 5632 : inforec = fetch_finfo_record(libraryhandle, prosrcstring);
391 :
392 : /* Cache the addresses for later calls */
393 5632 : record_C_func(procedureTuple, user_fn, inforec);
394 :
395 5632 : pfree(prosrcstring);
396 5632 : pfree(probinstring);
397 : }
398 :
399 86296 : switch (inforec->api_version)
400 : {
401 86296 : case 1:
402 : /* New style: call directly */
403 86296 : finfo->fn_addr = user_fn;
404 86296 : 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 86296 : }
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 29346 : fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
419 : {
420 29346 : Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
421 29346 : Oid language = procedureStruct->prolang;
422 : HeapTuple languageTuple;
423 : Form_pg_language languageStruct;
424 : FmgrInfo plfinfo;
425 :
426 29346 : languageTuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(language));
427 29346 : if (!HeapTupleIsValid(languageTuple))
428 0 : elog(ERROR, "cache lookup failed for language %u", language);
429 29346 : 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 29346 : fmgr_info_cxt_security(languageStruct->lanplcallfoid, &plfinfo,
437 : CurrentMemoryContext, true);
438 29346 : finfo->fn_addr = plfinfo.fn_addr;
439 :
440 29346 : ReleaseSysCache(languageTuple);
441 29346 : }
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 9906 : fetch_finfo_record(void *filehandle, const char *funcname)
456 : {
457 : char *infofuncname;
458 : PGFInfoFunction infofunc;
459 : const Pg_finfo_record *inforec;
460 :
461 9906 : infofuncname = psprintf("pg_finfo_%s", funcname);
462 :
463 : /* Try to look up the info function */
464 9906 : infofunc = (PGFInfoFunction) lookup_external_function(filehandle,
465 : infofuncname);
466 9906 : 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 9906 : inforec = (*infofunc) ();
478 :
479 : /* Validate result as best we can */
480 9906 : if (inforec == NULL)
481 0 : elog(ERROR, "null result from info function \"%s\"", infofuncname);
482 9906 : switch (inforec->api_version)
483 : {
484 9906 : case 1:
485 : /* OK, no additional fields to validate */
486 9906 : 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 9906 : pfree(infofuncname);
496 9906 : 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 86296 : lookup_C_func(HeapTuple procedureTuple)
516 : {
517 86296 : Oid fn_oid = ((Form_pg_proc) GETSTRUCT(procedureTuple))->oid;
518 : CFuncHashTabEntry *entry;
519 :
520 86296 : if (CFuncHash == NULL)
521 2316 : return NULL; /* no table yet */
522 : entry = (CFuncHashTabEntry *)
523 83980 : hash_search(CFuncHash,
524 : &fn_oid,
525 : HASH_FIND,
526 : NULL);
527 83980 : if (entry == NULL)
528 3310 : return NULL; /* no such entry */
529 161334 : if (entry->fn_xmin == HeapTupleHeaderGetRawXmin(procedureTuple->t_data) &&
530 80664 : ItemPointerEquals(&entry->fn_tid, &procedureTuple->t_self))
531 80664 : return entry; /* OK */
532 6 : 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 5632 : record_C_func(HeapTuple procedureTuple,
540 : PGFunction user_fn, const Pg_finfo_record *inforec)
541 : {
542 5632 : 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 5632 : if (CFuncHash == NULL)
548 : {
549 : HASHCTL hash_ctl;
550 :
551 2316 : hash_ctl.keysize = sizeof(Oid);
552 2316 : hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
553 2316 : CFuncHash = hash_create("CFuncHash",
554 : 100,
555 : &hash_ctl,
556 : HASH_ELEM | HASH_BLOBS);
557 : }
558 :
559 : entry = (CFuncHashTabEntry *)
560 5632 : hash_search(CFuncHash,
561 : &fn_oid,
562 : HASH_ENTER,
563 : &found);
564 : /* OID is already filled in */
565 5632 : entry->fn_xmin = HeapTupleHeaderGetRawXmin(procedureTuple->t_data);
566 5632 : entry->fn_tid = procedureTuple->t_self;
567 5632 : entry->user_fn = user_fn;
568 5632 : entry->inforec = inforec;
569 5632 : }
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 32979494 : fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
581 : MemoryContext destcxt)
582 : {
583 32979494 : memcpy(dstinfo, srcinfo, sizeof(FmgrInfo));
584 32979494 : dstinfo->fn_mcxt = destcxt;
585 32979494 : dstinfo->fn_extra = NULL;
586 32979494 : }
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 3046 : fmgr_internal_function(const char *proname)
596 : {
597 3046 : const FmgrBuiltin *fbp = fmgr_lookupByName(proname);
598 :
599 3046 : if (fbp == NULL)
600 6 : return InvalidOid;
601 3040 : 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 *configValues; /* GUC values to set, or NIL */
617 : Datum arg; /* passthrough argument for plugin modules */
618 : };
619 :
620 : /*
621 : * Function handler for security-definer/proconfig/plugin-hooked functions.
622 : * We extract the OID of the actual function and do a fmgr lookup again.
623 : * Then we fetch the pg_proc row and copy the owner ID and proconfig fields.
624 : * (All this info is cached for the duration of the current query.)
625 : * To execute a call, we temporarily replace the flinfo with the cached
626 : * and looked-up one, while keeping the outer fcinfo (which contains all
627 : * the actual arguments, etc.) intact. This is not re-entrant, but then
628 : * the fcinfo itself can't be used reentrantly anyway.
629 : */
630 : extern Datum
631 60 : fmgr_security_definer(PG_FUNCTION_ARGS)
632 : {
633 : Datum result;
634 : struct fmgr_security_definer_cache *volatile fcache;
635 : FmgrInfo *save_flinfo;
636 : Oid save_userid;
637 : int save_sec_context;
638 : ListCell *lc1;
639 : ListCell *lc2;
640 : volatile int save_nestlevel;
641 : PgStat_FunctionCallUsage fcusage;
642 :
643 60 : if (!fcinfo->flinfo->fn_extra)
644 : {
645 : HeapTuple tuple;
646 : Form_pg_proc procedureStruct;
647 : Datum datum;
648 : bool isnull;
649 : MemoryContext oldcxt;
650 :
651 60 : fcache = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
652 : sizeof(*fcache));
653 :
654 60 : fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo,
655 60 : fcinfo->flinfo->fn_mcxt, true);
656 60 : fcache->flinfo.fn_expr = fcinfo->flinfo->fn_expr;
657 :
658 60 : tuple = SearchSysCache1(PROCOID,
659 60 : ObjectIdGetDatum(fcinfo->flinfo->fn_oid));
660 60 : if (!HeapTupleIsValid(tuple))
661 0 : elog(ERROR, "cache lookup failed for function %u",
662 : fcinfo->flinfo->fn_oid);
663 60 : procedureStruct = (Form_pg_proc) GETSTRUCT(tuple);
664 :
665 60 : if (procedureStruct->prosecdef)
666 16 : fcache->userid = procedureStruct->proowner;
667 :
668 60 : datum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proconfig,
669 : &isnull);
670 60 : if (!isnull)
671 : {
672 : ArrayType *array;
673 :
674 44 : oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
675 44 : array = DatumGetArrayTypeP(datum);
676 44 : TransformGUCArray(array, &fcache->configNames,
677 44 : &fcache->configValues);
678 44 : MemoryContextSwitchTo(oldcxt);
679 : }
680 :
681 60 : ReleaseSysCache(tuple);
682 :
683 60 : fcinfo->flinfo->fn_extra = fcache;
684 : }
685 : else
686 0 : fcache = fcinfo->flinfo->fn_extra;
687 :
688 : /* GetUserIdAndSecContext is cheap enough that no harm in a wasted call */
689 60 : GetUserIdAndSecContext(&save_userid, &save_sec_context);
690 60 : if (fcache->configNames != NIL) /* Need a new GUC nesting level */
691 44 : save_nestlevel = NewGUCNestLevel();
692 : else
693 16 : save_nestlevel = 0; /* keep compiler quiet */
694 :
695 60 : if (OidIsValid(fcache->userid))
696 16 : SetUserIdAndSecContext(fcache->userid,
697 : save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
698 :
699 98 : forboth(lc1, fcache->configNames, lc2, fcache->configValues)
700 : {
701 44 : GucContext context = superuser() ? PGC_SUSET : PGC_USERSET;
702 44 : GucSource source = PGC_S_SESSION;
703 44 : GucAction action = GUC_ACTION_SAVE;
704 44 : char *name = lfirst(lc1);
705 44 : char *value = lfirst(lc2);
706 :
707 44 : (void) set_config_option(name, value,
708 : context, source,
709 : action, true, 0, false);
710 : }
711 :
712 : /* function manager hook */
713 54 : if (fmgr_hook)
714 0 : (*fmgr_hook) (FHET_START, &fcache->flinfo, &fcache->arg);
715 :
716 : /*
717 : * We don't need to restore GUC or userid settings on error, because the
718 : * ensuing xact or subxact abort will do that. The PG_TRY block is only
719 : * needed to clean up the flinfo link.
720 : */
721 54 : save_flinfo = fcinfo->flinfo;
722 :
723 54 : PG_TRY();
724 : {
725 54 : fcinfo->flinfo = &fcache->flinfo;
726 :
727 : /* See notes in fmgr_info_cxt_security */
728 54 : pgstat_init_function_usage(fcinfo, &fcusage);
729 :
730 54 : result = FunctionCallInvoke(fcinfo);
731 :
732 : /*
733 : * We could be calling either a regular or a set-returning function,
734 : * so we have to test to see what finalize flag to use.
735 : */
736 44 : pgstat_end_function_usage(&fcusage,
737 44 : (fcinfo->resultinfo == NULL ||
738 44 : !IsA(fcinfo->resultinfo, ReturnSetInfo) ||
739 0 : ((ReturnSetInfo *) fcinfo->resultinfo)->isDone != ExprMultipleResult));
740 : }
741 10 : PG_CATCH();
742 : {
743 10 : fcinfo->flinfo = save_flinfo;
744 10 : if (fmgr_hook)
745 0 : (*fmgr_hook) (FHET_ABORT, &fcache->flinfo, &fcache->arg);
746 10 : PG_RE_THROW();
747 : }
748 44 : PG_END_TRY();
749 :
750 44 : fcinfo->flinfo = save_flinfo;
751 :
752 44 : if (fcache->configNames != NIL)
753 30 : AtEOXact_GUC(true, save_nestlevel);
754 44 : if (OidIsValid(fcache->userid))
755 14 : SetUserIdAndSecContext(save_userid, save_sec_context);
756 44 : if (fmgr_hook)
757 0 : (*fmgr_hook) (FHET_END, &fcache->flinfo, &fcache->arg);
758 :
759 44 : return result;
760 : }
761 :
762 :
763 : /*-------------------------------------------------------------------------
764 : * Support routines for callers of fmgr-compatible functions
765 : *-------------------------------------------------------------------------
766 : */
767 :
768 : /*
769 : * These are for invocation of a specifically named function with a
770 : * directly-computed parameter list. Note that neither arguments nor result
771 : * are allowed to be NULL. Also, the function cannot be one that needs to
772 : * look at FmgrInfo, since there won't be any.
773 : */
774 : Datum
775 2576696 : DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
776 : {
777 2576696 : LOCAL_FCINFO(fcinfo, 1);
778 : Datum result;
779 :
780 2576696 : InitFunctionCallInfoData(*fcinfo, NULL, 1, collation, NULL, NULL);
781 :
782 2576696 : fcinfo->args[0].value = arg1;
783 2576696 : fcinfo->args[0].isnull = false;
784 :
785 2576696 : result = (*func) (fcinfo);
786 :
787 : /* Check for null result, since caller is clearly not expecting one */
788 2576672 : if (fcinfo->isnull)
789 0 : elog(ERROR, "function %p returned NULL", (void *) func);
790 :
791 2576672 : return result;
792 : }
793 :
794 : Datum
795 39846218 : DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
796 : {
797 39846218 : LOCAL_FCINFO(fcinfo, 2);
798 : Datum result;
799 :
800 39846218 : InitFunctionCallInfoData(*fcinfo, NULL, 2, collation, NULL, NULL);
801 :
802 39846218 : fcinfo->args[0].value = arg1;
803 39846218 : fcinfo->args[0].isnull = false;
804 39846218 : fcinfo->args[1].value = arg2;
805 39846218 : fcinfo->args[1].isnull = false;
806 :
807 39846218 : result = (*func) (fcinfo);
808 :
809 : /* Check for null result, since caller is clearly not expecting one */
810 39846182 : if (fcinfo->isnull)
811 0 : elog(ERROR, "function %p returned NULL", (void *) func);
812 :
813 39846182 : return result;
814 : }
815 :
816 : Datum
817 1141906 : DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
818 : Datum arg3)
819 : {
820 1141906 : LOCAL_FCINFO(fcinfo, 3);
821 : Datum result;
822 :
823 1141906 : InitFunctionCallInfoData(*fcinfo, NULL, 3, collation, NULL, NULL);
824 :
825 1141906 : fcinfo->args[0].value = arg1;
826 1141906 : fcinfo->args[0].isnull = false;
827 1141906 : fcinfo->args[1].value = arg2;
828 1141906 : fcinfo->args[1].isnull = false;
829 1141906 : fcinfo->args[2].value = arg3;
830 1141906 : fcinfo->args[2].isnull = false;
831 :
832 1141906 : result = (*func) (fcinfo);
833 :
834 : /* Check for null result, since caller is clearly not expecting one */
835 1141892 : if (fcinfo->isnull)
836 0 : elog(ERROR, "function %p returned NULL", (void *) func);
837 :
838 1141892 : return result;
839 : }
840 :
841 : Datum
842 830 : DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
843 : Datum arg3, Datum arg4)
844 : {
845 830 : LOCAL_FCINFO(fcinfo, 4);
846 : Datum result;
847 :
848 830 : InitFunctionCallInfoData(*fcinfo, NULL, 4, collation, NULL, NULL);
849 :
850 830 : fcinfo->args[0].value = arg1;
851 830 : fcinfo->args[0].isnull = false;
852 830 : fcinfo->args[1].value = arg2;
853 830 : fcinfo->args[1].isnull = false;
854 830 : fcinfo->args[2].value = arg3;
855 830 : fcinfo->args[2].isnull = false;
856 830 : fcinfo->args[3].value = arg4;
857 830 : fcinfo->args[3].isnull = false;
858 :
859 830 : result = (*func) (fcinfo);
860 :
861 : /* Check for null result, since caller is clearly not expecting one */
862 830 : if (fcinfo->isnull)
863 0 : elog(ERROR, "function %p returned NULL", (void *) func);
864 :
865 830 : return result;
866 : }
867 :
868 : Datum
869 4204 : DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
870 : Datum arg3, Datum arg4, Datum arg5)
871 : {
872 4204 : LOCAL_FCINFO(fcinfo, 5);
873 : Datum result;
874 :
875 4204 : InitFunctionCallInfoData(*fcinfo, NULL, 5, collation, NULL, NULL);
876 :
877 4204 : fcinfo->args[0].value = arg1;
878 4204 : fcinfo->args[0].isnull = false;
879 4204 : fcinfo->args[1].value = arg2;
880 4204 : fcinfo->args[1].isnull = false;
881 4204 : fcinfo->args[2].value = arg3;
882 4204 : fcinfo->args[2].isnull = false;
883 4204 : fcinfo->args[3].value = arg4;
884 4204 : fcinfo->args[3].isnull = false;
885 4204 : fcinfo->args[4].value = arg5;
886 4204 : fcinfo->args[4].isnull = false;
887 :
888 4204 : result = (*func) (fcinfo);
889 :
890 : /* Check for null result, since caller is clearly not expecting one */
891 4198 : if (fcinfo->isnull)
892 0 : elog(ERROR, "function %p returned NULL", (void *) func);
893 :
894 4198 : return result;
895 : }
896 :
897 : Datum
898 0 : DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
899 : Datum arg3, Datum arg4, Datum arg5,
900 : Datum arg6)
901 : {
902 0 : LOCAL_FCINFO(fcinfo, 6);
903 : Datum result;
904 :
905 0 : InitFunctionCallInfoData(*fcinfo, NULL, 6, collation, NULL, NULL);
906 :
907 0 : fcinfo->args[0].value = arg1;
908 0 : fcinfo->args[0].isnull = false;
909 0 : fcinfo->args[1].value = arg2;
910 0 : fcinfo->args[1].isnull = false;
911 0 : fcinfo->args[2].value = arg3;
912 0 : fcinfo->args[2].isnull = false;
913 0 : fcinfo->args[3].value = arg4;
914 0 : fcinfo->args[3].isnull = false;
915 0 : fcinfo->args[4].value = arg5;
916 0 : fcinfo->args[4].isnull = false;
917 0 : fcinfo->args[5].value = arg6;
918 0 : fcinfo->args[5].isnull = false;
919 :
920 0 : result = (*func) (fcinfo);
921 :
922 : /* Check for null result, since caller is clearly not expecting one */
923 0 : if (fcinfo->isnull)
924 0 : elog(ERROR, "function %p returned NULL", (void *) func);
925 :
926 0 : return result;
927 : }
928 :
929 : Datum
930 0 : DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
931 : Datum arg3, Datum arg4, Datum arg5,
932 : Datum arg6, Datum arg7)
933 : {
934 0 : LOCAL_FCINFO(fcinfo, 7);
935 : Datum result;
936 :
937 0 : InitFunctionCallInfoData(*fcinfo, NULL, 7, collation, NULL, NULL);
938 :
939 0 : fcinfo->args[0].value = arg1;
940 0 : fcinfo->args[0].isnull = false;
941 0 : fcinfo->args[1].value = arg2;
942 0 : fcinfo->args[1].isnull = false;
943 0 : fcinfo->args[2].value = arg3;
944 0 : fcinfo->args[2].isnull = false;
945 0 : fcinfo->args[3].value = arg4;
946 0 : fcinfo->args[3].isnull = false;
947 0 : fcinfo->args[4].value = arg5;
948 0 : fcinfo->args[4].isnull = false;
949 0 : fcinfo->args[5].value = arg6;
950 0 : fcinfo->args[5].isnull = false;
951 0 : fcinfo->args[6].value = arg7;
952 0 : fcinfo->args[6].isnull = false;
953 :
954 0 : result = (*func) (fcinfo);
955 :
956 : /* Check for null result, since caller is clearly not expecting one */
957 0 : if (fcinfo->isnull)
958 0 : elog(ERROR, "function %p returned NULL", (void *) func);
959 :
960 0 : return result;
961 : }
962 :
963 : Datum
964 0 : DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
965 : Datum arg3, Datum arg4, Datum arg5,
966 : Datum arg6, Datum arg7, Datum arg8)
967 : {
968 0 : LOCAL_FCINFO(fcinfo, 8);
969 : Datum result;
970 :
971 0 : InitFunctionCallInfoData(*fcinfo, NULL, 8, collation, NULL, NULL);
972 :
973 0 : fcinfo->args[0].value = arg1;
974 0 : fcinfo->args[0].isnull = false;
975 0 : fcinfo->args[1].value = arg2;
976 0 : fcinfo->args[1].isnull = false;
977 0 : fcinfo->args[2].value = arg3;
978 0 : fcinfo->args[2].isnull = false;
979 0 : fcinfo->args[3].value = arg4;
980 0 : fcinfo->args[3].isnull = false;
981 0 : fcinfo->args[4].value = arg5;
982 0 : fcinfo->args[4].isnull = false;
983 0 : fcinfo->args[5].value = arg6;
984 0 : fcinfo->args[5].isnull = false;
985 0 : fcinfo->args[6].value = arg7;
986 0 : fcinfo->args[6].isnull = false;
987 0 : fcinfo->args[7].value = arg8;
988 0 : fcinfo->args[7].isnull = false;
989 :
990 0 : result = (*func) (fcinfo);
991 :
992 : /* Check for null result, since caller is clearly not expecting one */
993 0 : if (fcinfo->isnull)
994 0 : elog(ERROR, "function %p returned NULL", (void *) func);
995 :
996 0 : return result;
997 : }
998 :
999 : Datum
1000 0 : DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
1001 : Datum arg3, Datum arg4, Datum arg5,
1002 : Datum arg6, Datum arg7, Datum arg8,
1003 : Datum arg9)
1004 : {
1005 0 : LOCAL_FCINFO(fcinfo, 9);
1006 : Datum result;
1007 :
1008 0 : InitFunctionCallInfoData(*fcinfo, NULL, 9, collation, NULL, NULL);
1009 :
1010 0 : fcinfo->args[0].value = arg1;
1011 0 : fcinfo->args[0].isnull = false;
1012 0 : fcinfo->args[1].value = arg2;
1013 0 : fcinfo->args[1].isnull = false;
1014 0 : fcinfo->args[2].value = arg3;
1015 0 : fcinfo->args[2].isnull = false;
1016 0 : fcinfo->args[3].value = arg4;
1017 0 : fcinfo->args[3].isnull = false;
1018 0 : fcinfo->args[4].value = arg5;
1019 0 : fcinfo->args[4].isnull = false;
1020 0 : fcinfo->args[5].value = arg6;
1021 0 : fcinfo->args[5].isnull = false;
1022 0 : fcinfo->args[6].value = arg7;
1023 0 : fcinfo->args[6].isnull = false;
1024 0 : fcinfo->args[7].value = arg8;
1025 0 : fcinfo->args[7].isnull = false;
1026 0 : fcinfo->args[8].value = arg9;
1027 0 : fcinfo->args[8].isnull = false;
1028 :
1029 0 : result = (*func) (fcinfo);
1030 :
1031 : /* Check for null result, since caller is clearly not expecting one */
1032 0 : if (fcinfo->isnull)
1033 0 : elog(ERROR, "function %p returned NULL", (void *) func);
1034 :
1035 0 : return result;
1036 : }
1037 :
1038 : /*
1039 : * These functions work like the DirectFunctionCall functions except that
1040 : * they use the flinfo parameter to initialise the fcinfo for the call.
1041 : * It's recommended that the callee only use the fn_extra and fn_mcxt
1042 : * fields, as other fields will typically describe the calling function
1043 : * not the callee. Conversely, the calling function should not have
1044 : * used fn_extra, unless its use is known to be compatible with the callee's.
1045 : */
1046 :
1047 : Datum
1048 0 : CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1)
1049 : {
1050 0 : LOCAL_FCINFO(fcinfo, 1);
1051 : Datum result;
1052 :
1053 0 : InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL);
1054 :
1055 0 : fcinfo->args[0].value = arg1;
1056 0 : fcinfo->args[0].isnull = false;
1057 :
1058 0 : result = (*func) (fcinfo);
1059 :
1060 : /* Check for null result, since caller is clearly not expecting one */
1061 0 : if (fcinfo->isnull)
1062 0 : elog(ERROR, "function %p returned NULL", (void *) func);
1063 :
1064 0 : return result;
1065 : }
1066 :
1067 : Datum
1068 410060 : CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
1069 : {
1070 410060 : LOCAL_FCINFO(fcinfo, 2);
1071 : Datum result;
1072 :
1073 410060 : InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
1074 :
1075 410060 : fcinfo->args[0].value = arg1;
1076 410060 : fcinfo->args[0].isnull = false;
1077 410060 : fcinfo->args[1].value = arg2;
1078 410060 : fcinfo->args[1].isnull = false;
1079 :
1080 410060 : result = (*func) (fcinfo);
1081 :
1082 : /* Check for null result, since caller is clearly not expecting one */
1083 410060 : if (fcinfo->isnull)
1084 0 : elog(ERROR, "function %p returned NULL", (void *) func);
1085 :
1086 410060 : return result;
1087 : }
1088 :
1089 : /*
1090 : * These are for invocation of a previously-looked-up function with a
1091 : * directly-computed parameter list. Note that neither arguments nor result
1092 : * are allowed to be NULL.
1093 : */
1094 : Datum
1095 3691934 : FunctionCall0Coll(FmgrInfo *flinfo, Oid collation)
1096 : {
1097 3691934 : LOCAL_FCINFO(fcinfo, 0);
1098 : Datum result;
1099 :
1100 3691934 : InitFunctionCallInfoData(*fcinfo, flinfo, 0, collation, NULL, NULL);
1101 :
1102 3691934 : result = FunctionCallInvoke(fcinfo);
1103 :
1104 : /* Check for null result, since caller is clearly not expecting one */
1105 3691934 : if (fcinfo->isnull)
1106 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1107 :
1108 3691934 : return result;
1109 : }
1110 :
1111 : Datum
1112 81681396 : FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
1113 : {
1114 81681396 : LOCAL_FCINFO(fcinfo, 1);
1115 : Datum result;
1116 :
1117 81681396 : InitFunctionCallInfoData(*fcinfo, flinfo, 1, collation, NULL, NULL);
1118 :
1119 81681396 : fcinfo->args[0].value = arg1;
1120 81681396 : fcinfo->args[0].isnull = false;
1121 :
1122 81681396 : result = FunctionCallInvoke(fcinfo);
1123 :
1124 : /* Check for null result, since caller is clearly not expecting one */
1125 81680784 : if (fcinfo->isnull)
1126 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1127 :
1128 81680784 : return result;
1129 : }
1130 :
1131 : Datum
1132 399173360 : FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
1133 : {
1134 399173360 : LOCAL_FCINFO(fcinfo, 2);
1135 : Datum result;
1136 :
1137 399173360 : InitFunctionCallInfoData(*fcinfo, flinfo, 2, collation, NULL, NULL);
1138 :
1139 399173360 : fcinfo->args[0].value = arg1;
1140 399173360 : fcinfo->args[0].isnull = false;
1141 399173360 : fcinfo->args[1].value = arg2;
1142 399173360 : fcinfo->args[1].isnull = false;
1143 :
1144 399173360 : result = FunctionCallInvoke(fcinfo);
1145 :
1146 : /* Check for null result, since caller is clearly not expecting one */
1147 399173242 : if (fcinfo->isnull)
1148 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1149 :
1150 399173242 : return result;
1151 : }
1152 :
1153 : Datum
1154 48264778 : FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1155 : Datum arg3)
1156 : {
1157 48264778 : LOCAL_FCINFO(fcinfo, 3);
1158 : Datum result;
1159 :
1160 48264778 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, collation, NULL, NULL);
1161 :
1162 48264778 : fcinfo->args[0].value = arg1;
1163 48264778 : fcinfo->args[0].isnull = false;
1164 48264778 : fcinfo->args[1].value = arg2;
1165 48264778 : fcinfo->args[1].isnull = false;
1166 48264778 : fcinfo->args[2].value = arg3;
1167 48264778 : fcinfo->args[2].isnull = false;
1168 :
1169 48264778 : result = FunctionCallInvoke(fcinfo);
1170 :
1171 : /* Check for null result, since caller is clearly not expecting one */
1172 48264778 : if (fcinfo->isnull)
1173 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1174 :
1175 48264778 : return result;
1176 : }
1177 :
1178 : Datum
1179 1564282 : FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1180 : Datum arg3, Datum arg4)
1181 : {
1182 1564282 : LOCAL_FCINFO(fcinfo, 4);
1183 : Datum result;
1184 :
1185 1564282 : InitFunctionCallInfoData(*fcinfo, flinfo, 4, collation, NULL, NULL);
1186 :
1187 1564282 : fcinfo->args[0].value = arg1;
1188 1564282 : fcinfo->args[0].isnull = false;
1189 1564282 : fcinfo->args[1].value = arg2;
1190 1564282 : fcinfo->args[1].isnull = false;
1191 1564282 : fcinfo->args[2].value = arg3;
1192 1564282 : fcinfo->args[2].isnull = false;
1193 1564282 : fcinfo->args[3].value = arg4;
1194 1564282 : fcinfo->args[3].isnull = false;
1195 :
1196 1564282 : result = FunctionCallInvoke(fcinfo);
1197 :
1198 : /* Check for null result, since caller is clearly not expecting one */
1199 1564274 : if (fcinfo->isnull)
1200 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1201 :
1202 1564274 : return result;
1203 : }
1204 :
1205 : Datum
1206 2202296 : FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1207 : Datum arg3, Datum arg4, Datum arg5)
1208 : {
1209 2202296 : LOCAL_FCINFO(fcinfo, 5);
1210 : Datum result;
1211 :
1212 2202296 : InitFunctionCallInfoData(*fcinfo, flinfo, 5, collation, NULL, NULL);
1213 :
1214 2202296 : fcinfo->args[0].value = arg1;
1215 2202296 : fcinfo->args[0].isnull = false;
1216 2202296 : fcinfo->args[1].value = arg2;
1217 2202296 : fcinfo->args[1].isnull = false;
1218 2202296 : fcinfo->args[2].value = arg3;
1219 2202296 : fcinfo->args[2].isnull = false;
1220 2202296 : fcinfo->args[3].value = arg4;
1221 2202296 : fcinfo->args[3].isnull = false;
1222 2202296 : fcinfo->args[4].value = arg5;
1223 2202296 : fcinfo->args[4].isnull = false;
1224 :
1225 2202296 : result = FunctionCallInvoke(fcinfo);
1226 :
1227 : /* Check for null result, since caller is clearly not expecting one */
1228 2202260 : if (fcinfo->isnull)
1229 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1230 :
1231 2202260 : return result;
1232 : }
1233 :
1234 : Datum
1235 6862 : FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1236 : Datum arg3, Datum arg4, Datum arg5,
1237 : Datum arg6)
1238 : {
1239 6862 : LOCAL_FCINFO(fcinfo, 6);
1240 : Datum result;
1241 :
1242 6862 : InitFunctionCallInfoData(*fcinfo, flinfo, 6, collation, NULL, NULL);
1243 :
1244 6862 : fcinfo->args[0].value = arg1;
1245 6862 : fcinfo->args[0].isnull = false;
1246 6862 : fcinfo->args[1].value = arg2;
1247 6862 : fcinfo->args[1].isnull = false;
1248 6862 : fcinfo->args[2].value = arg3;
1249 6862 : fcinfo->args[2].isnull = false;
1250 6862 : fcinfo->args[3].value = arg4;
1251 6862 : fcinfo->args[3].isnull = false;
1252 6862 : fcinfo->args[4].value = arg5;
1253 6862 : fcinfo->args[4].isnull = false;
1254 6862 : fcinfo->args[5].value = arg6;
1255 6862 : fcinfo->args[5].isnull = false;
1256 :
1257 6862 : result = FunctionCallInvoke(fcinfo);
1258 :
1259 : /* Check for null result, since caller is clearly not expecting one */
1260 4522 : if (fcinfo->isnull)
1261 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1262 :
1263 4522 : return result;
1264 : }
1265 :
1266 : Datum
1267 969574 : FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1268 : Datum arg3, Datum arg4, Datum arg5,
1269 : Datum arg6, Datum arg7)
1270 : {
1271 969574 : LOCAL_FCINFO(fcinfo, 7);
1272 : Datum result;
1273 :
1274 969574 : InitFunctionCallInfoData(*fcinfo, flinfo, 7, collation, NULL, NULL);
1275 :
1276 969574 : fcinfo->args[0].value = arg1;
1277 969574 : fcinfo->args[0].isnull = false;
1278 969574 : fcinfo->args[1].value = arg2;
1279 969574 : fcinfo->args[1].isnull = false;
1280 969574 : fcinfo->args[2].value = arg3;
1281 969574 : fcinfo->args[2].isnull = false;
1282 969574 : fcinfo->args[3].value = arg4;
1283 969574 : fcinfo->args[3].isnull = false;
1284 969574 : fcinfo->args[4].value = arg5;
1285 969574 : fcinfo->args[4].isnull = false;
1286 969574 : fcinfo->args[5].value = arg6;
1287 969574 : fcinfo->args[5].isnull = false;
1288 969574 : fcinfo->args[6].value = arg7;
1289 969574 : fcinfo->args[6].isnull = false;
1290 :
1291 969574 : result = FunctionCallInvoke(fcinfo);
1292 :
1293 : /* Check for null result, since caller is clearly not expecting one */
1294 969574 : if (fcinfo->isnull)
1295 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1296 :
1297 969574 : return result;
1298 : }
1299 :
1300 : Datum
1301 37442 : FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1302 : Datum arg3, Datum arg4, Datum arg5,
1303 : Datum arg6, Datum arg7, Datum arg8)
1304 : {
1305 37442 : LOCAL_FCINFO(fcinfo, 8);
1306 : Datum result;
1307 :
1308 37442 : InitFunctionCallInfoData(*fcinfo, flinfo, 8, collation, NULL, NULL);
1309 :
1310 37442 : fcinfo->args[0].value = arg1;
1311 37442 : fcinfo->args[0].isnull = false;
1312 37442 : fcinfo->args[1].value = arg2;
1313 37442 : fcinfo->args[1].isnull = false;
1314 37442 : fcinfo->args[2].value = arg3;
1315 37442 : fcinfo->args[2].isnull = false;
1316 37442 : fcinfo->args[3].value = arg4;
1317 37442 : fcinfo->args[3].isnull = false;
1318 37442 : fcinfo->args[4].value = arg5;
1319 37442 : fcinfo->args[4].isnull = false;
1320 37442 : fcinfo->args[5].value = arg6;
1321 37442 : fcinfo->args[5].isnull = false;
1322 37442 : fcinfo->args[6].value = arg7;
1323 37442 : fcinfo->args[6].isnull = false;
1324 37442 : fcinfo->args[7].value = arg8;
1325 37442 : fcinfo->args[7].isnull = false;
1326 :
1327 37442 : result = FunctionCallInvoke(fcinfo);
1328 :
1329 : /* Check for null result, since caller is clearly not expecting one */
1330 37442 : if (fcinfo->isnull)
1331 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1332 :
1333 37442 : return result;
1334 : }
1335 :
1336 : Datum
1337 0 : FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
1338 : Datum arg3, Datum arg4, Datum arg5,
1339 : Datum arg6, Datum arg7, Datum arg8,
1340 : Datum arg9)
1341 : {
1342 0 : LOCAL_FCINFO(fcinfo, 9);
1343 : Datum result;
1344 :
1345 0 : InitFunctionCallInfoData(*fcinfo, flinfo, 9, collation, NULL, NULL);
1346 :
1347 0 : fcinfo->args[0].value = arg1;
1348 0 : fcinfo->args[0].isnull = false;
1349 0 : fcinfo->args[1].value = arg2;
1350 0 : fcinfo->args[1].isnull = false;
1351 0 : fcinfo->args[2].value = arg3;
1352 0 : fcinfo->args[2].isnull = false;
1353 0 : fcinfo->args[3].value = arg4;
1354 0 : fcinfo->args[3].isnull = false;
1355 0 : fcinfo->args[4].value = arg5;
1356 0 : fcinfo->args[4].isnull = false;
1357 0 : fcinfo->args[5].value = arg6;
1358 0 : fcinfo->args[5].isnull = false;
1359 0 : fcinfo->args[6].value = arg7;
1360 0 : fcinfo->args[6].isnull = false;
1361 0 : fcinfo->args[7].value = arg8;
1362 0 : fcinfo->args[7].isnull = false;
1363 0 : fcinfo->args[8].value = arg9;
1364 0 : fcinfo->args[8].isnull = false;
1365 :
1366 0 : result = FunctionCallInvoke(fcinfo);
1367 :
1368 : /* Check for null result, since caller is clearly not expecting one */
1369 0 : if (fcinfo->isnull)
1370 0 : elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
1371 :
1372 0 : return result;
1373 : }
1374 :
1375 :
1376 : /*
1377 : * These are for invocation of a function identified by OID with a
1378 : * directly-computed parameter list. Note that neither arguments nor result
1379 : * are allowed to be NULL. These are essentially fmgr_info() followed
1380 : * by FunctionCallN(). If the same function is to be invoked repeatedly,
1381 : * do the fmgr_info() once and then use FunctionCallN().
1382 : */
1383 : Datum
1384 3691934 : OidFunctionCall0Coll(Oid functionId, Oid collation)
1385 : {
1386 : FmgrInfo flinfo;
1387 :
1388 3691934 : fmgr_info(functionId, &flinfo);
1389 :
1390 3691934 : return FunctionCall0Coll(&flinfo, collation);
1391 : }
1392 :
1393 : Datum
1394 510382 : OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
1395 : {
1396 : FmgrInfo flinfo;
1397 :
1398 510382 : fmgr_info(functionId, &flinfo);
1399 :
1400 510382 : return FunctionCall1Coll(&flinfo, collation, arg1);
1401 : }
1402 :
1403 : Datum
1404 956 : OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
1405 : {
1406 : FmgrInfo flinfo;
1407 :
1408 956 : fmgr_info(functionId, &flinfo);
1409 :
1410 956 : return FunctionCall2Coll(&flinfo, collation, arg1, arg2);
1411 : }
1412 :
1413 : Datum
1414 4 : OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1415 : Datum arg3)
1416 : {
1417 : FmgrInfo flinfo;
1418 :
1419 4 : fmgr_info(functionId, &flinfo);
1420 :
1421 4 : return FunctionCall3Coll(&flinfo, collation, arg1, arg2, arg3);
1422 : }
1423 :
1424 : Datum
1425 517462 : OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1426 : Datum arg3, Datum arg4)
1427 : {
1428 : FmgrInfo flinfo;
1429 :
1430 517462 : fmgr_info(functionId, &flinfo);
1431 :
1432 517462 : return FunctionCall4Coll(&flinfo, collation, arg1, arg2, arg3, arg4);
1433 : }
1434 :
1435 : Datum
1436 173492 : OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1437 : Datum arg3, Datum arg4, Datum arg5)
1438 : {
1439 : FmgrInfo flinfo;
1440 :
1441 173492 : fmgr_info(functionId, &flinfo);
1442 :
1443 173492 : return FunctionCall5Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5);
1444 : }
1445 :
1446 : Datum
1447 6538 : OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1448 : Datum arg3, Datum arg4, Datum arg5,
1449 : Datum arg6)
1450 : {
1451 : FmgrInfo flinfo;
1452 :
1453 6538 : fmgr_info(functionId, &flinfo);
1454 :
1455 6538 : return FunctionCall6Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1456 : arg6);
1457 : }
1458 :
1459 : Datum
1460 0 : OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1461 : Datum arg3, Datum arg4, Datum arg5,
1462 : Datum arg6, Datum arg7)
1463 : {
1464 : FmgrInfo flinfo;
1465 :
1466 0 : fmgr_info(functionId, &flinfo);
1467 :
1468 0 : return FunctionCall7Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1469 : arg6, arg7);
1470 : }
1471 :
1472 : Datum
1473 0 : OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1474 : Datum arg3, Datum arg4, Datum arg5,
1475 : Datum arg6, Datum arg7, Datum arg8)
1476 : {
1477 : FmgrInfo flinfo;
1478 :
1479 0 : fmgr_info(functionId, &flinfo);
1480 :
1481 0 : return FunctionCall8Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1482 : arg6, arg7, arg8);
1483 : }
1484 :
1485 : Datum
1486 0 : OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
1487 : Datum arg3, Datum arg4, Datum arg5,
1488 : Datum arg6, Datum arg7, Datum arg8,
1489 : Datum arg9)
1490 : {
1491 : FmgrInfo flinfo;
1492 :
1493 0 : fmgr_info(functionId, &flinfo);
1494 :
1495 0 : return FunctionCall9Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
1496 : arg6, arg7, arg8, arg9);
1497 : }
1498 :
1499 :
1500 : /*
1501 : * Special cases for convenient invocation of datatype I/O functions.
1502 : */
1503 :
1504 : /*
1505 : * Call a previously-looked-up datatype input function.
1506 : *
1507 : * "str" may be NULL to indicate we are reading a NULL. In this case
1508 : * the caller should assume the result is NULL, but we'll call the input
1509 : * function anyway if it's not strict. So this is almost but not quite
1510 : * the same as FunctionCall3.
1511 : */
1512 : Datum
1513 37288768 : InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
1514 : {
1515 37288768 : LOCAL_FCINFO(fcinfo, 3);
1516 : Datum result;
1517 :
1518 37288768 : if (str == NULL && flinfo->fn_strict)
1519 7774348 : return (Datum) 0; /* just return null result */
1520 :
1521 29514420 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
1522 :
1523 29514420 : fcinfo->args[0].value = CStringGetDatum(str);
1524 29514420 : fcinfo->args[0].isnull = false;
1525 29514420 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1526 29514420 : fcinfo->args[1].isnull = false;
1527 29514420 : fcinfo->args[2].value = Int32GetDatum(typmod);
1528 29514420 : fcinfo->args[2].isnull = false;
1529 :
1530 29514420 : result = FunctionCallInvoke(fcinfo);
1531 :
1532 : /* Should get null result if and only if str is NULL */
1533 29509974 : if (str == NULL)
1534 : {
1535 36 : if (!fcinfo->isnull)
1536 0 : elog(ERROR, "input function %u returned non-NULL",
1537 : flinfo->fn_oid);
1538 : }
1539 : else
1540 : {
1541 29509938 : if (fcinfo->isnull)
1542 0 : elog(ERROR, "input function %u returned NULL",
1543 : flinfo->fn_oid);
1544 : }
1545 :
1546 29509974 : return result;
1547 : }
1548 :
1549 : /*
1550 : * Call a previously-looked-up datatype input function, with non-exception
1551 : * handling of "soft" errors.
1552 : *
1553 : * This is basically like InputFunctionCall, but the converted Datum is
1554 : * returned into *result while the function result is true for success or
1555 : * false for failure. Also, the caller may pass an ErrorSaveContext node.
1556 : * (We declare that as "fmNodePtr" to avoid including nodes.h in fmgr.h.)
1557 : *
1558 : * If escontext points to an ErrorSaveContext, any "soft" errors detected by
1559 : * the input function will be reported by filling the escontext struct and
1560 : * returning false. (The caller can choose to test SOFT_ERROR_OCCURRED(),
1561 : * but checking the function result instead is usually cheaper.)
1562 : *
1563 : * If escontext does not point to an ErrorSaveContext, errors are reported
1564 : * via ereport(ERROR), so that there is no functional difference from
1565 : * InputFunctionCall; the result will always be true if control returns.
1566 : */
1567 : bool
1568 1197012 : InputFunctionCallSafe(FmgrInfo *flinfo, char *str,
1569 : Oid typioparam, int32 typmod,
1570 : fmNodePtr escontext,
1571 : Datum *result)
1572 : {
1573 1197012 : LOCAL_FCINFO(fcinfo, 3);
1574 :
1575 1197012 : if (str == NULL && flinfo->fn_strict)
1576 : {
1577 1048 : *result = (Datum) 0; /* just return null result */
1578 1048 : return true;
1579 : }
1580 :
1581 1195964 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, escontext, NULL);
1582 :
1583 1195964 : fcinfo->args[0].value = CStringGetDatum(str);
1584 1195964 : fcinfo->args[0].isnull = false;
1585 1195964 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1586 1195964 : fcinfo->args[1].isnull = false;
1587 1195964 : fcinfo->args[2].value = Int32GetDatum(typmod);
1588 1195964 : fcinfo->args[2].isnull = false;
1589 :
1590 1195964 : *result = FunctionCallInvoke(fcinfo);
1591 :
1592 : /* Result value is garbage, and could be null, if an error was reported */
1593 1195852 : if (SOFT_ERROR_OCCURRED(escontext))
1594 1418 : return false;
1595 :
1596 : /* Otherwise, should get null result if and only if str is NULL */
1597 1194434 : if (str == NULL)
1598 : {
1599 0 : if (!fcinfo->isnull)
1600 0 : elog(ERROR, "input function %u returned non-NULL",
1601 : flinfo->fn_oid);
1602 : }
1603 : else
1604 : {
1605 1194434 : if (fcinfo->isnull)
1606 0 : elog(ERROR, "input function %u returned NULL",
1607 : flinfo->fn_oid);
1608 : }
1609 :
1610 1194434 : return true;
1611 : }
1612 :
1613 : /*
1614 : * Call a directly-named datatype input function, with non-exception
1615 : * handling of "soft" errors.
1616 : *
1617 : * This is like InputFunctionCallSafe, except that it is given a direct
1618 : * pointer to the C function to call. We assume that that function is
1619 : * strict. Also, the function cannot be one that needs to
1620 : * look at FmgrInfo, since there won't be any.
1621 : */
1622 : bool
1623 505820 : DirectInputFunctionCallSafe(PGFunction func, char *str,
1624 : Oid typioparam, int32 typmod,
1625 : fmNodePtr escontext,
1626 : Datum *result)
1627 : {
1628 505820 : LOCAL_FCINFO(fcinfo, 3);
1629 :
1630 505820 : if (str == NULL)
1631 : {
1632 0 : *result = (Datum) 0; /* just return null result */
1633 0 : return true;
1634 : }
1635 :
1636 505820 : InitFunctionCallInfoData(*fcinfo, NULL, 3, InvalidOid, escontext, NULL);
1637 :
1638 505820 : fcinfo->args[0].value = CStringGetDatum(str);
1639 505820 : fcinfo->args[0].isnull = false;
1640 505820 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1641 505820 : fcinfo->args[1].isnull = false;
1642 505820 : fcinfo->args[2].value = Int32GetDatum(typmod);
1643 505820 : fcinfo->args[2].isnull = false;
1644 :
1645 505820 : *result = (*func) (fcinfo);
1646 :
1647 : /* Result value is garbage, and could be null, if an error was reported */
1648 505820 : if (SOFT_ERROR_OCCURRED(escontext))
1649 144 : return false;
1650 :
1651 : /* Otherwise, shouldn't get null result */
1652 505676 : if (fcinfo->isnull)
1653 0 : elog(ERROR, "input function %p returned NULL", (void *) func);
1654 :
1655 505676 : return true;
1656 : }
1657 :
1658 : /*
1659 : * Call a previously-looked-up datatype output function.
1660 : *
1661 : * Do not call this on NULL datums.
1662 : *
1663 : * This is currently little more than window dressing for FunctionCall1.
1664 : */
1665 : char *
1666 33969220 : OutputFunctionCall(FmgrInfo *flinfo, Datum val)
1667 : {
1668 33969220 : return DatumGetCString(FunctionCall1(flinfo, val));
1669 : }
1670 :
1671 : /*
1672 : * Call a previously-looked-up datatype binary-input function.
1673 : *
1674 : * "buf" may be NULL to indicate we are reading a NULL. In this case
1675 : * the caller should assume the result is NULL, but we'll call the receive
1676 : * function anyway if it's not strict. So this is almost but not quite
1677 : * the same as FunctionCall3.
1678 : */
1679 : Datum
1680 312812 : ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
1681 : Oid typioparam, int32 typmod)
1682 : {
1683 312812 : LOCAL_FCINFO(fcinfo, 3);
1684 : Datum result;
1685 :
1686 312812 : if (buf == NULL && flinfo->fn_strict)
1687 30 : return (Datum) 0; /* just return null result */
1688 :
1689 312782 : InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
1690 :
1691 312782 : fcinfo->args[0].value = PointerGetDatum(buf);
1692 312782 : fcinfo->args[0].isnull = false;
1693 312782 : fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
1694 312782 : fcinfo->args[1].isnull = false;
1695 312782 : fcinfo->args[2].value = Int32GetDatum(typmod);
1696 312782 : fcinfo->args[2].isnull = false;
1697 :
1698 312782 : result = FunctionCallInvoke(fcinfo);
1699 :
1700 : /* Should get null result if and only if buf is NULL */
1701 312782 : if (buf == NULL)
1702 : {
1703 0 : if (!fcinfo->isnull)
1704 0 : elog(ERROR, "receive function %u returned non-NULL",
1705 : flinfo->fn_oid);
1706 : }
1707 : else
1708 : {
1709 312782 : if (fcinfo->isnull)
1710 0 : elog(ERROR, "receive function %u returned NULL",
1711 : flinfo->fn_oid);
1712 : }
1713 :
1714 312782 : return result;
1715 : }
1716 :
1717 : /*
1718 : * Call a previously-looked-up datatype binary-output function.
1719 : *
1720 : * Do not call this on NULL datums.
1721 : *
1722 : * This is little more than window dressing for FunctionCall1, but it does
1723 : * guarantee a non-toasted result, which strictly speaking the underlying
1724 : * function doesn't.
1725 : */
1726 : bytea *
1727 247020 : SendFunctionCall(FmgrInfo *flinfo, Datum val)
1728 : {
1729 247020 : return DatumGetByteaP(FunctionCall1(flinfo, val));
1730 : }
1731 :
1732 : /*
1733 : * As above, for I/O functions identified by OID. These are only to be used
1734 : * in seldom-executed code paths. They are not only slow but leak memory.
1735 : */
1736 : Datum
1737 8728346 : OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
1738 : {
1739 : FmgrInfo flinfo;
1740 :
1741 8728346 : fmgr_info(functionId, &flinfo);
1742 8728346 : return InputFunctionCall(&flinfo, str, typioparam, typmod);
1743 : }
1744 :
1745 : char *
1746 1022320 : OidOutputFunctionCall(Oid functionId, Datum val)
1747 : {
1748 : FmgrInfo flinfo;
1749 :
1750 1022320 : fmgr_info(functionId, &flinfo);
1751 1022320 : return OutputFunctionCall(&flinfo, val);
1752 : }
1753 :
1754 : Datum
1755 312468 : OidReceiveFunctionCall(Oid functionId, StringInfo buf,
1756 : Oid typioparam, int32 typmod)
1757 : {
1758 : FmgrInfo flinfo;
1759 :
1760 312468 : fmgr_info(functionId, &flinfo);
1761 312468 : return ReceiveFunctionCall(&flinfo, buf, typioparam, typmod);
1762 : }
1763 :
1764 : bytea *
1765 232170 : OidSendFunctionCall(Oid functionId, Datum val)
1766 : {
1767 : FmgrInfo flinfo;
1768 :
1769 232170 : fmgr_info(functionId, &flinfo);
1770 232170 : return SendFunctionCall(&flinfo, val);
1771 : }
1772 :
1773 :
1774 : /*-------------------------------------------------------------------------
1775 : * Support routines for standard maybe-pass-by-reference datatypes
1776 : *
1777 : * int8 and float8 can be passed by value if Datum is wide enough.
1778 : * (For backwards-compatibility reasons, we allow pass-by-ref to be chosen
1779 : * at compile time even if pass-by-val is possible.)
1780 : *
1781 : * Note: there is only one switch controlling the pass-by-value option for
1782 : * both int8 and float8; this is to avoid making things unduly complicated
1783 : * for the timestamp types, which might have either representation.
1784 : *-------------------------------------------------------------------------
1785 : */
1786 :
1787 : #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
1788 :
1789 : Datum
1790 : Int64GetDatum(int64 X)
1791 : {
1792 : int64 *retval = (int64 *) palloc(sizeof(int64));
1793 :
1794 : *retval = X;
1795 : return PointerGetDatum(retval);
1796 : }
1797 :
1798 : Datum
1799 : Float8GetDatum(float8 X)
1800 : {
1801 : float8 *retval = (float8 *) palloc(sizeof(float8));
1802 :
1803 : *retval = X;
1804 : return PointerGetDatum(retval);
1805 : }
1806 : #endif /* USE_FLOAT8_BYVAL */
1807 :
1808 :
1809 : /*-------------------------------------------------------------------------
1810 : * Support routines for toastable datatypes
1811 : *-------------------------------------------------------------------------
1812 : */
1813 :
1814 : struct varlena *
1815 85895054 : pg_detoast_datum(struct varlena *datum)
1816 : {
1817 85895054 : if (VARATT_IS_EXTENDED(datum))
1818 22159778 : return detoast_attr(datum);
1819 : else
1820 63735276 : return datum;
1821 : }
1822 :
1823 : struct varlena *
1824 5039890 : pg_detoast_datum_copy(struct varlena *datum)
1825 : {
1826 5039890 : if (VARATT_IS_EXTENDED(datum))
1827 2660040 : return detoast_attr(datum);
1828 : else
1829 : {
1830 : /* Make a modifiable copy of the varlena object */
1831 2379850 : Size len = VARSIZE(datum);
1832 2379850 : struct varlena *result = (struct varlena *) palloc(len);
1833 :
1834 2379850 : memcpy(result, datum, len);
1835 2379850 : return result;
1836 : }
1837 : }
1838 :
1839 : struct varlena *
1840 1595658 : pg_detoast_datum_slice(struct varlena *datum, int32 first, int32 count)
1841 : {
1842 : /* Only get the specified portion from the toast rel */
1843 1595658 : return detoast_attr_slice(datum, first, count);
1844 : }
1845 :
1846 : struct varlena *
1847 160745298 : pg_detoast_datum_packed(struct varlena *datum)
1848 : {
1849 160745298 : if (VARATT_IS_COMPRESSED(datum) || VARATT_IS_EXTERNAL(datum))
1850 37668 : return detoast_attr(datum);
1851 : else
1852 160707630 : return datum;
1853 : }
1854 :
1855 : /*-------------------------------------------------------------------------
1856 : * Support routines for extracting info from fn_expr parse tree
1857 : *
1858 : * These are needed by polymorphic functions, which accept multiple possible
1859 : * input types and need help from the parser to know what they've got.
1860 : * Also, some functions might be interested in whether a parameter is constant.
1861 : * Functions taking VARIADIC ANY also need to know about the VARIADIC keyword.
1862 : *-------------------------------------------------------------------------
1863 : */
1864 :
1865 : /*
1866 : * Get the actual type OID of the function return type
1867 : *
1868 : * Returns InvalidOid if information is not available
1869 : */
1870 : Oid
1871 134758 : get_fn_expr_rettype(FmgrInfo *flinfo)
1872 : {
1873 : Node *expr;
1874 :
1875 : /*
1876 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
1877 : * node has not been initialized
1878 : */
1879 134758 : if (!flinfo || !flinfo->fn_expr)
1880 0 : return InvalidOid;
1881 :
1882 134758 : expr = flinfo->fn_expr;
1883 :
1884 134758 : return exprType(expr);
1885 : }
1886 :
1887 : /*
1888 : * Get the actual type OID of a specific function argument (counting from 0)
1889 : *
1890 : * Returns InvalidOid if information is not available
1891 : */
1892 : Oid
1893 1715738 : get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
1894 : {
1895 : /*
1896 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
1897 : * node has not been initialized
1898 : */
1899 1715738 : if (!flinfo || !flinfo->fn_expr)
1900 0 : return InvalidOid;
1901 :
1902 1715738 : return get_call_expr_argtype(flinfo->fn_expr, argnum);
1903 : }
1904 :
1905 : /*
1906 : * Get the actual type OID of a specific function argument (counting from 0),
1907 : * but working from the calling expression tree instead of FmgrInfo
1908 : *
1909 : * Returns InvalidOid if information is not available
1910 : */
1911 : Oid
1912 1721518 : get_call_expr_argtype(Node *expr, int argnum)
1913 : {
1914 : List *args;
1915 : Oid argtype;
1916 :
1917 1721518 : if (expr == NULL)
1918 0 : return InvalidOid;
1919 :
1920 1721518 : if (IsA(expr, FuncExpr))
1921 1721476 : args = ((FuncExpr *) expr)->args;
1922 42 : else if (IsA(expr, OpExpr))
1923 42 : args = ((OpExpr *) expr)->args;
1924 0 : else if (IsA(expr, DistinctExpr))
1925 0 : args = ((DistinctExpr *) expr)->args;
1926 0 : else if (IsA(expr, ScalarArrayOpExpr))
1927 0 : args = ((ScalarArrayOpExpr *) expr)->args;
1928 0 : else if (IsA(expr, NullIfExpr))
1929 0 : args = ((NullIfExpr *) expr)->args;
1930 0 : else if (IsA(expr, WindowFunc))
1931 0 : args = ((WindowFunc *) expr)->args;
1932 : else
1933 0 : return InvalidOid;
1934 :
1935 1721518 : if (argnum < 0 || argnum >= list_length(args))
1936 0 : return InvalidOid;
1937 :
1938 1721518 : argtype = exprType((Node *) list_nth(args, argnum));
1939 :
1940 : /*
1941 : * special hack for ScalarArrayOpExpr: what the underlying function will
1942 : * actually get passed is the element type of the array.
1943 : */
1944 1721518 : if (IsA(expr, ScalarArrayOpExpr) &&
1945 : argnum == 1)
1946 0 : argtype = get_base_element_type(argtype);
1947 :
1948 1721518 : return argtype;
1949 : }
1950 :
1951 : /*
1952 : * Find out whether a specific function argument is constant for the
1953 : * duration of a query
1954 : *
1955 : * Returns false if information is not available
1956 : */
1957 : bool
1958 3272 : get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum)
1959 : {
1960 : /*
1961 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
1962 : * node has not been initialized
1963 : */
1964 3272 : if (!flinfo || !flinfo->fn_expr)
1965 0 : return false;
1966 :
1967 3272 : return get_call_expr_arg_stable(flinfo->fn_expr, argnum);
1968 : }
1969 :
1970 : /*
1971 : * Find out whether a specific function argument is constant for the
1972 : * duration of a query, but working from the calling expression tree
1973 : *
1974 : * Returns false if information is not available
1975 : */
1976 : bool
1977 3272 : get_call_expr_arg_stable(Node *expr, int argnum)
1978 : {
1979 : List *args;
1980 : Node *arg;
1981 :
1982 3272 : if (expr == NULL)
1983 0 : return false;
1984 :
1985 3272 : if (IsA(expr, FuncExpr))
1986 2246 : args = ((FuncExpr *) expr)->args;
1987 1026 : else if (IsA(expr, OpExpr))
1988 0 : args = ((OpExpr *) expr)->args;
1989 1026 : else if (IsA(expr, DistinctExpr))
1990 0 : args = ((DistinctExpr *) expr)->args;
1991 1026 : else if (IsA(expr, ScalarArrayOpExpr))
1992 0 : args = ((ScalarArrayOpExpr *) expr)->args;
1993 1026 : else if (IsA(expr, NullIfExpr))
1994 0 : args = ((NullIfExpr *) expr)->args;
1995 1026 : else if (IsA(expr, WindowFunc))
1996 1026 : args = ((WindowFunc *) expr)->args;
1997 : else
1998 0 : return false;
1999 :
2000 3272 : if (argnum < 0 || argnum >= list_length(args))
2001 0 : return false;
2002 :
2003 3272 : arg = (Node *) list_nth(args, argnum);
2004 :
2005 : /*
2006 : * Either a true Const or an external Param will have a value that doesn't
2007 : * change during the execution of the query. In future we might want to
2008 : * consider other cases too, e.g. now().
2009 : */
2010 3272 : if (IsA(arg, Const))
2011 2964 : return true;
2012 308 : if (IsA(arg, Param) &&
2013 4 : ((Param *) arg)->paramkind == PARAM_EXTERN)
2014 0 : return true;
2015 :
2016 308 : return false;
2017 : }
2018 :
2019 : /*
2020 : * Get the VARIADIC flag from the function invocation
2021 : *
2022 : * Returns false (the default assumption) if information is not available
2023 : *
2024 : * Note this is generally only of interest to VARIADIC ANY functions
2025 : */
2026 : bool
2027 28170 : get_fn_expr_variadic(FmgrInfo *flinfo)
2028 : {
2029 : Node *expr;
2030 :
2031 : /*
2032 : * can't return anything useful if we have no FmgrInfo or if its fn_expr
2033 : * node has not been initialized
2034 : */
2035 28170 : if (!flinfo || !flinfo->fn_expr)
2036 0 : return false;
2037 :
2038 28170 : expr = flinfo->fn_expr;
2039 :
2040 28170 : if (IsA(expr, FuncExpr))
2041 28170 : return ((FuncExpr *) expr)->funcvariadic;
2042 : else
2043 0 : return false;
2044 : }
2045 :
2046 : /*
2047 : * Set options to FmgrInfo of opclass support function.
2048 : *
2049 : * Opclass support functions are called outside of expressions. Thanks to that
2050 : * we can use fn_expr to store opclass options as bytea constant.
2051 : */
2052 : void
2053 855564 : set_fn_opclass_options(FmgrInfo *flinfo, bytea *options)
2054 : {
2055 855564 : flinfo->fn_expr = (Node *) makeConst(BYTEAOID, -1, InvalidOid, -1,
2056 : PointerGetDatum(options),
2057 : options == NULL, false);
2058 855564 : }
2059 :
2060 : /*
2061 : * Check if options are defined for opclass support function.
2062 : */
2063 : bool
2064 5441960 : has_fn_opclass_options(FmgrInfo *flinfo)
2065 : {
2066 5441960 : if (flinfo && flinfo->fn_expr && IsA(flinfo->fn_expr, Const))
2067 : {
2068 5441960 : Const *expr = (Const *) flinfo->fn_expr;
2069 :
2070 5441960 : if (expr->consttype == BYTEAOID)
2071 5441960 : return !expr->constisnull;
2072 : }
2073 0 : return false;
2074 : }
2075 :
2076 : /*
2077 : * Get options for opclass support function.
2078 : */
2079 : bytea *
2080 5604274 : get_fn_opclass_options(FmgrInfo *flinfo)
2081 : {
2082 5604274 : if (flinfo && flinfo->fn_expr && IsA(flinfo->fn_expr, Const))
2083 : {
2084 5604274 : Const *expr = (Const *) flinfo->fn_expr;
2085 :
2086 5604274 : if (expr->consttype == BYTEAOID)
2087 5604274 : return expr->constisnull ? NULL : DatumGetByteaP(expr->constvalue);
2088 : }
2089 :
2090 0 : ereport(ERROR,
2091 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2092 : errmsg("operator class options info is absent in function call context")));
2093 :
2094 : return NULL;
2095 : }
2096 :
2097 : /*-------------------------------------------------------------------------
2098 : * Support routines for procedural language implementations
2099 : *-------------------------------------------------------------------------
2100 : */
2101 :
2102 : /*
2103 : * Verify that a validator is actually associated with the language of a
2104 : * particular function and that the user has access to both the language and
2105 : * the function. All validators should call this before doing anything
2106 : * substantial. Doing so ensures a user cannot achieve anything with explicit
2107 : * calls to validators that he could not achieve with CREATE FUNCTION or by
2108 : * simply calling an existing function.
2109 : *
2110 : * When this function returns false, callers should skip all validation work
2111 : * and call PG_RETURN_VOID(). This never happens at present; it is reserved
2112 : * for future expansion.
2113 : *
2114 : * In particular, checking that the validator corresponds to the function's
2115 : * language allows untrusted language validators to assume they process only
2116 : * superuser-chosen source code. (Untrusted language call handlers, by
2117 : * definition, do assume that.) A user lacking the USAGE language privilege
2118 : * would be unable to reach the validator through CREATE FUNCTION, so we check
2119 : * that to block explicit calls as well. Checking the EXECUTE privilege on
2120 : * the function is often superfluous, because most users can clone the
2121 : * function to get an executable copy. It is meaningful against users with no
2122 : * database TEMP right and no permanent schema CREATE right, thereby unable to
2123 : * create any function. Also, if the function tracks persistent state by
2124 : * function OID or name, validating the original function might permit more
2125 : * mischief than creating and validating a clone thereof.
2126 : */
2127 : bool
2128 18224 : CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid)
2129 : {
2130 : HeapTuple procTup;
2131 : HeapTuple langTup;
2132 : Form_pg_proc procStruct;
2133 : Form_pg_language langStruct;
2134 : AclResult aclresult;
2135 :
2136 : /*
2137 : * Get the function's pg_proc entry. Throw a user-facing error for bad
2138 : * OID, because validators can be called with user-specified OIDs.
2139 : */
2140 18224 : procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionOid));
2141 18224 : if (!HeapTupleIsValid(procTup))
2142 0 : ereport(ERROR,
2143 : (errcode(ERRCODE_UNDEFINED_FUNCTION),
2144 : errmsg("function with OID %u does not exist", functionOid)));
2145 18224 : procStruct = (Form_pg_proc) GETSTRUCT(procTup);
2146 :
2147 : /*
2148 : * Fetch pg_language entry to know if this is the correct validation
2149 : * function for that pg_proc entry.
2150 : */
2151 18224 : langTup = SearchSysCache1(LANGOID, ObjectIdGetDatum(procStruct->prolang));
2152 18224 : if (!HeapTupleIsValid(langTup))
2153 0 : elog(ERROR, "cache lookup failed for language %u", procStruct->prolang);
2154 18224 : langStruct = (Form_pg_language) GETSTRUCT(langTup);
2155 :
2156 18224 : if (langStruct->lanvalidator != validatorOid)
2157 0 : ereport(ERROR,
2158 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2159 : errmsg("language validation function %u called for language %u instead of %u",
2160 : validatorOid, procStruct->prolang,
2161 : langStruct->lanvalidator)));
2162 :
2163 : /* first validate that we have permissions to use the language */
2164 18224 : aclresult = object_aclcheck(LanguageRelationId, procStruct->prolang, GetUserId(),
2165 : ACL_USAGE);
2166 18224 : if (aclresult != ACLCHECK_OK)
2167 0 : aclcheck_error(aclresult, OBJECT_LANGUAGE,
2168 0 : NameStr(langStruct->lanname));
2169 :
2170 : /*
2171 : * Check whether we are allowed to execute the function itself. If we can
2172 : * execute it, there should be no possible side-effect of
2173 : * compiling/validation that execution can't have.
2174 : */
2175 18224 : aclresult = object_aclcheck(ProcedureRelationId, functionOid, GetUserId(), ACL_EXECUTE);
2176 18224 : if (aclresult != ACLCHECK_OK)
2177 0 : aclcheck_error(aclresult, OBJECT_FUNCTION, NameStr(procStruct->proname));
2178 :
2179 18224 : ReleaseSysCache(procTup);
2180 18224 : ReleaseSysCache(langTup);
2181 :
2182 18224 : return true;
2183 : }
|