LCOV - code coverage report
Current view: top level - src/backend/utils/fmgr - fmgr.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 71.4 % 994 710
Test Date: 2026-01-26 10:56:24 Functions: 82.6 % 69 57
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 38.1 % 478 182

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

Generated by: LCOV version 2.3.2-1