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