LCOV - code coverage report
Current view: top level - src/backend/utils/fmgr - fmgr.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 617 826 74.7 %
Date: 2024-02-28 21:11:04 Functions: 60 69 87.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14