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