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