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

Generated by: LCOV version 2.0-1