LCOV - code coverage report
Current view: top level - src/backend/utils/fmgr - fmgr.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 74.1 % 826 612
Test Date: 2026-03-24 02:15:55 Functions: 87.0 % 69 60
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.0-1