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