LCOV - code coverage report
Current view: top level - src/backend/utils/fmgr - fmgr.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 546 852 64.1 %
Date: 2017-09-29 15:12:54 Functions: 52 65 80.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11