LCOV - differential code coverage report
Current view: top level - src/backend/tcop - fastpath.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 69.7 % 132 92 12 16 12 3 63 2 24 25 56
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 4 4 4 4
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 100.0 % 2 2 2
Legend: Lines: hit not hit (240..) days: 69.2 % 130 90 12 16 12 3 63 24 25 56
Function coverage date bins:
(240..) days: 50.0 % 8 4 4 4

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * fastpath.c
                                  4                 :  *    routines to handle function requests from the frontend
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :  *
                                  9                 :  *
                                 10                 :  * IDENTIFICATION
                                 11                 :  *    src/backend/tcop/fastpath.c
                                 12                 :  *
                                 13                 :  * NOTES
                                 14                 :  *    This cruft is the server side of PQfn.
                                 15                 :  *
                                 16                 :  *-------------------------------------------------------------------------
                                 17                 :  */
                                 18                 : #include "postgres.h"
                                 19                 : 
                                 20                 : #include "access/htup_details.h"
                                 21                 : #include "access/xact.h"
                                 22                 : #include "catalog/objectaccess.h"
                                 23                 : #include "catalog/pg_namespace.h"
                                 24                 : #include "catalog/pg_proc.h"
                                 25                 : #include "libpq/libpq.h"
                                 26                 : #include "libpq/pqformat.h"
                                 27                 : #include "mb/pg_wchar.h"
                                 28                 : #include "miscadmin.h"
                                 29                 : #include "port/pg_bswap.h"
                                 30                 : #include "tcop/fastpath.h"
                                 31                 : #include "tcop/tcopprot.h"
                                 32                 : #include "utils/acl.h"
                                 33                 : #include "utils/lsyscache.h"
                                 34                 : #include "utils/snapmgr.h"
                                 35                 : #include "utils/syscache.h"
                                 36                 : 
                                 37                 : 
                                 38                 : /*
                                 39                 :  * Formerly, this code attempted to cache the function and type info
                                 40                 :  * looked up by fetch_fp_info, but only for the duration of a single
                                 41                 :  * transaction command (since in theory the info could change between
                                 42                 :  * commands).  This was utterly useless, because postgres.c executes
                                 43                 :  * each fastpath call as a separate transaction command, and so the
                                 44                 :  * cached data could never actually have been reused.  If it had worked
                                 45                 :  * as intended, it would have had problems anyway with dangling references
                                 46                 :  * in the FmgrInfo struct.  So, forget about caching and just repeat the
                                 47                 :  * syscache fetches on each usage.  They're not *that* expensive.
                                 48                 :  */
                                 49                 : struct fp_info
                                 50                 : {
                                 51                 :     Oid         funcid;
                                 52                 :     FmgrInfo    flinfo;         /* function lookup info for funcid */
                                 53                 :     Oid         namespace;      /* other stuff from pg_proc */
                                 54                 :     Oid         rettype;
                                 55                 :     Oid         argtypes[FUNC_MAX_ARGS];
                                 56                 :     char        fname[NAMEDATALEN]; /* function name for logging */
                                 57                 : };
                                 58                 : 
                                 59                 : 
                                 60                 : static int16 parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
                                 61                 :                                    FunctionCallInfo fcinfo);
                                 62                 : 
                                 63                 : /* ----------------
                                 64                 :  *      SendFunctionResult
                                 65                 :  * ----------------
                                 66                 :  */
                                 67                 : static void
 7275 tgl                        68 GIC        1063 : SendFunctionResult(Datum retval, bool isnull, Oid rettype, int16 format)
 9770 scrappy                    69 ECB             : {
                                 70                 :     StringInfoData buf;
                                 71                 : 
 7292 tgl                        72 GIC        1063 :     pq_beginmessage(&buf, 'V');
 9345 bruce                      73 ECB             : 
 7275 tgl                        74 GIC        1063 :     if (isnull)
 9345 bruce                      75 ECB             :     {
  766 heikki.linnakangas         76 UIC           0 :         pq_sendint32(&buf, -1);
 7276 tgl                        77 EUB             :     }
                                 78                 :     else
                                 79                 :     {
 7275 tgl                        80 GIC        1063 :         if (format == 0)
 7275 tgl                        81 ECB             :         {
                                 82                 :             Oid         typoutput;
                                 83                 :             bool        typisvarlena;
                                 84                 :             char       *outputstr;
                                 85                 : 
 6552 tgl                        86 UIC           0 :             getTypeOutputInfo(rettype, &typoutput, &typisvarlena);
 6214 tgl                        87 UBC           0 :             outputstr = OidOutputFunctionCall(typoutput, retval);
 7275                            88               0 :             pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
                                 89               0 :             pfree(outputstr);
 9345 bruce                      90 EUB             :         }
 7275 tgl                        91 GIC        1063 :         else if (format == 1)
 7275 tgl                        92 ECB             :         {
                                 93                 :             Oid         typsend;
                                 94                 :             bool        typisvarlena;
                                 95                 :             bytea      *outputbytes;
                                 96                 : 
 6552 tgl                        97 GIC        1063 :             getTypeBinaryOutputInfo(rettype, &typsend, &typisvarlena);
 6214 tgl                        98 CBC        1063 :             outputbytes = OidSendFunctionCall(typsend, retval);
 2006 andres                     99            1063 :             pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
 7275 tgl                       100            1063 :             pq_sendbytes(&buf, VARDATA(outputbytes),
                                101            1063 :                          VARSIZE(outputbytes) - VARHDRSZ);
                                102            1063 :             pfree(outputbytes);
 7275 tgl                       103 ECB             :         }
                                104                 :         else
 7201 tgl                       105 UIC           0 :             ereport(ERROR,
 7201 tgl                       106 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                107                 :                      errmsg("unsupported format code: %d", format)));
                                108                 :     }
                                109                 : 
 8750 tgl                       110 GIC        1063 :     pq_endmessage(&buf);
 9770 scrappy                   111 CBC        1063 : }
 9770 scrappy                   112 ECB             : 
                                113                 : /*
                                114                 :  * fetch_fp_info
                                115                 :  *
                                116                 :  * Performs catalog lookups to load a struct fp_info 'fip' for the
                                117                 :  * function 'func_id'.
                                118                 :  */
                                119                 : static void
 2118 tgl                       120 GIC        1063 : fetch_fp_info(Oid func_id, struct fp_info *fip)
 9770 scrappy                   121 ECB             : {
                                122                 :     HeapTuple   func_htp;
                                123                 :     Form_pg_proc pp;
                                124                 : 
 7032 neilc                     125 GIC        1063 :     Assert(fip != NULL);
 9345 bruce                     126 ECB             : 
                                127                 :     /*
                                128                 :      * Since the validity of this structure is determined by whether the
                                129                 :      * funcid is OK, we clear the funcid here.  It must not be set to the
                                130                 :      * correct value until we are about to return with a good struct fp_info,
                                131                 :      * since we can be interrupted (i.e., with an ereport(ERROR, ...)) at any
                                132                 :      * time.  [No longer really an issue since we don't save the struct
                                133                 :      * fp_info across transactions anymore, but keep it anyway.]
                                134                 :      */
 6585 tgl                       135 GIC       71221 :     MemSet(fip, 0, sizeof(struct fp_info));
 9345 bruce                     136 CBC        1063 :     fip->funcid = InvalidOid;
 9345 bruce                     137 ECB             : 
 4802 rhaas                     138 GIC        1063 :     func_htp = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_id));
 9345 bruce                     139 CBC        1063 :     if (!HeapTupleIsValid(func_htp))
 7201 tgl                       140 LBC           0 :         ereport(ERROR,
 7201 tgl                       141 EUB             :                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
                                142                 :                  errmsg("function with OID %u does not exist", func_id)));
 9345 bruce                     143 GIC        1063 :     pp = (Form_pg_proc) GETSTRUCT(func_htp);
 9345 bruce                     144 ECB             : 
                                145                 :     /* reject pg_proc entries that are unsafe to call via fastpath */
  709 tgl                       146 GIC        1063 :     if (pp->prokind != PROKIND_FUNCTION || pp->proretset)
  709 tgl                       147 LBC           0 :         ereport(ERROR,
  709 tgl                       148 EUB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                149                 :                  errmsg("cannot call function \"%s\" via fastpath interface",
                                150                 :                         NameStr(pp->proname))));
                                151                 : 
                                152                 :     /* watch out for catalog entries with more than FUNC_MAX_ARGS args */
 6585 tgl                       153 GIC        1063 :     if (pp->pronargs > FUNC_MAX_ARGS)
 6585 tgl                       154 LBC           0 :         elog(ERROR, "function %s has more than %d arguments",
 6585 tgl                       155 EUB             :              NameStr(pp->proname), FUNC_MAX_ARGS);
                                156                 : 
 7275 tgl                       157 GIC        1063 :     fip->namespace = pp->pronamespace;
 7275 tgl                       158 CBC        1063 :     fip->rettype = pp->prorettype;
 6585                           159            1063 :     memcpy(fip->argtypes, pp->proargtypes.values, pp->pronargs * sizeof(Oid));
 6016                           160            1063 :     strlcpy(fip->fname, NameStr(pp->proname), NAMEDATALEN);
 9345 bruce                     161 ECB             : 
 8179 tgl                       162 GIC        1063 :     ReleaseSysCache(func_htp);
 8179 tgl                       163 ECB             : 
  709 tgl                       164 GIC        1063 :     fmgr_info(func_id, &fip->flinfo);
  709 tgl                       165 ECB             : 
                                166                 :     /*
                                167                 :      * This must be last!
                                168                 :      */
 9345 bruce                     169 GIC        1063 :     fip->funcid = func_id;
 9770 scrappy                   170 CBC        1063 : }
 9345 bruce                     171 ECB             : 
                                172                 : 
                                173                 : /*
                                174                 :  * HandleFunctionRequest
                                175                 :  *
                                176                 :  * Server side of PQfn (fastpath function calls from the frontend).
                                177                 :  * This corresponds to the libpq protocol symbol "F".
                                178                 :  *
                                179                 :  * INPUT:
                                180                 :  *      postgres.c has already read the message body and will pass it in
                                181                 :  *      msgBuf.
                                182                 :  *
                                183                 :  * Note: palloc()s done here and in the called function do not need to be
                                184                 :  * cleaned up explicitly.  We are called from PostgresMain() in the
                                185                 :  * MessageContext memory context, which will be automatically reset when
                                186                 :  * control returns to PostgresMain.
                                187                 :  */
                                188                 : void
 7295 tgl                       189 GIC        1063 : HandleFunctionRequest(StringInfo msgBuf)
 9770 scrappy                   190 ECB             : {
 1534 andres                    191 GIC        1063 :     LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
 9344 bruce                     192 ECB             :     Oid         fid;
                                193                 :     AclResult   aclresult;
                                194                 :     int16       rformat;
                                195                 :     Datum       retval;
                                196                 :     struct fp_info my_fp;
                                197                 :     struct fp_info *fip;
                                198                 :     bool        callit;
 6057 tgl                       199 GIC        1063 :     bool        was_logged = false;
 6057 tgl                       200 ECB             :     char        msec_str[32];
                                201                 : 
                                202                 :     /*
                                203                 :      * We only accept COMMIT/ABORT if we are in an aborted transaction, and
                                204                 :      * COMMIT/ABORT cannot be executed through the fastpath interface.
                                205                 :      */
 7295 tgl                       206 GIC        1063 :     if (IsAbortedTransactionBlockState())
 7201 tgl                       207 LBC           0 :         ereport(ERROR,
 7201 tgl                       208 EUB             :                 (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
                                209                 :                  errmsg("current transaction is aborted, "
                                210                 :                         "commands ignored until end of transaction block")));
                                211                 : 
                                212                 :     /*
                                213                 :      * Now that we know we are in a valid transaction, set snapshot in case
                                214                 :      * needed by function itself or one of the datatype I/O routines.
                                215                 :      */
 5445 alvherre                  216 GIC        1063 :     PushActiveSnapshot(GetTransactionSnapshot());
 6146 tgl                       217 ECB             : 
                                218                 :     /*
                                219                 :      * Begin parsing the buffer contents.
                                220                 :      */
 2118 tgl                       221 GIC        1063 :     fid = (Oid) pq_getmsgint(msgBuf, 4);    /* function oid */
 9345 bruce                     222 ECB             : 
                                223                 :     /*
                                224                 :      * There used to be a lame attempt at caching lookup info here. Now we
                                225                 :      * just do the lookups on every call.
                                226                 :      */
 7982 tgl                       227 GIC        1063 :     fip = &my_fp;
 7982 tgl                       228 CBC        1063 :     fetch_fp_info(fid, fip);
 9345 bruce                     229 ECB             : 
                                230                 :     /* Log as soon as we have the function OID and name */
 6016 tgl                       231 GIC        1063 :     if (log_statement == LOGSTMT_ALL)
 6016 tgl                       232 ECB             :     {
 6016 tgl                       233 GIC         804 :         ereport(LOG,
 6016 tgl                       234 ECB             :                 (errmsg("fastpath function call: \"%s\" (OID %u)",
                                235                 :                         fip->fname, fid)));
 6016 tgl                       236 GIC         804 :         was_logged = true;
 6016 tgl                       237 ECB             :     }
                                238                 : 
                                239                 :     /*
                                240                 :      * Check permission to access and call function.  Since we didn't go
                                241                 :      * through a normal name lookup, we need to check schema usage too.
                                242                 :      */
  147 peter                     243 GNC        1063 :     aclresult = object_aclcheck(NamespaceRelationId, fip->namespace, GetUserId(), ACL_USAGE);
 7275 tgl                       244 CBC        1063 :     if (aclresult != ACLCHECK_OK)
 1954 peter_e                   245 LBC           0 :         aclcheck_error(aclresult, OBJECT_SCHEMA,
 7191 tgl                       246 UBC           0 :                        get_namespace_name(fip->namespace));
 3656 rhaas                     247 GBC        1063 :     InvokeNamespaceSearchHook(fip->namespace, true);
 7275 tgl                       248 ECB             : 
  147 peter                     249 GNC        1063 :     aclresult = object_aclcheck(ProcedureRelationId, fid, GetUserId(), ACL_EXECUTE);
 7295 tgl                       250 CBC        1063 :     if (aclresult != ACLCHECK_OK)
 1954 peter_e                   251 LBC           0 :         aclcheck_error(aclresult, OBJECT_FUNCTION,
 7191 tgl                       252 UBC           0 :                        get_func_name(fid));
 3649 rhaas                     253 GBC        1063 :     InvokeFunctionExecuteHook(fid);
 7295 tgl                       254 ECB             : 
                                255                 :     /*
                                256                 :      * Prepare function call info block and insert arguments.
                                257                 :      *
                                258                 :      * Note: for now we pass collation = InvalidOid, so collation-sensitive
                                259                 :      * functions can't be called this way.  Perhaps we should pass
                                260                 :      * DEFAULT_COLLATION_OID, instead?
                                261                 :      */
 1534 andres                    262 GIC        1063 :     InitFunctionCallInfoData(*fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
 7276 tgl                       263 ECB             : 
  766 heikki.linnakangas        264 GIC        1063 :     rformat = parse_fcall_arguments(msgBuf, fip, fcinfo);
 7276 tgl                       265 ECB             : 
                                266                 :     /* Verify we reached the end of the message where expected. */
 7276 tgl                       267 GIC        1063 :     pq_getmsgend(msgBuf);
 7276 tgl                       268 ECB             : 
                                269                 :     /*
                                270                 :      * If func is strict, must not call it for null args.
                                271                 :      */
 7275 tgl                       272 GIC        1063 :     callit = true;
 7275 tgl                       273 CBC        1063 :     if (fip->flinfo.fn_strict)
 7275 tgl                       274 ECB             :     {
                                275                 :         int         i;
                                276                 : 
 1534 andres                    277 GIC        3080 :         for (i = 0; i < fcinfo->nargs; i++)
 7275 tgl                       278 ECB             :         {
 1534 andres                    279 GIC        2017 :             if (fcinfo->args[i].isnull)
 7275 tgl                       280 ECB             :             {
 7275 tgl                       281 UIC           0 :                 callit = false;
 7275 tgl                       282 UBC           0 :                 break;
 7275 tgl                       283 EUB             :             }
                                284                 :         }
                                285                 :     }
                                286                 : 
 7275 tgl                       287 GIC        1063 :     if (callit)
 7275 tgl                       288 ECB             :     {
                                289                 :         /* Okay, do it ... */
 1534 andres                    290 GIC        1063 :         retval = FunctionCallInvoke(fcinfo);
 7275 tgl                       291 ECB             :     }
                                292                 :     else
                                293                 :     {
 1534 andres                    294 UIC           0 :         fcinfo->isnull = true;
 7275 tgl                       295 UBC           0 :         retval = (Datum) 0;
 7275 tgl                       296 EUB             :     }
                                297                 : 
                                298                 :     /* ensure we do at least one CHECK_FOR_INTERRUPTS per function call */
 6143 tgl                       299 GIC        1063 :     CHECK_FOR_INTERRUPTS();
 6143 tgl                       300 ECB             : 
 1534 andres                    301 GIC        1063 :     SendFunctionResult(retval, fcinfo->isnull, fip->rettype, rformat);
 7276 tgl                       302 ECB             : 
                                303                 :     /* We no longer need the snapshot */
 5445 alvherre                  304 GIC        1063 :     PopActiveSnapshot();
 5445 alvherre                  305 ECB             : 
                                306                 :     /*
                                307                 :      * Emit duration logging if appropriate.
                                308                 :      */
 6057 tgl                       309 GIC        1063 :     switch (check_log_duration(msec_str, was_logged))
 6057 tgl                       310 ECB             :     {
 6057 tgl                       311 UIC           0 :         case 1:
 6057 tgl                       312 UBC           0 :             ereport(LOG,
 6057 tgl                       313 EUB             :                     (errmsg("duration: %s ms", msec_str)));
 6057 tgl                       314 UIC           0 :             break;
 6057 tgl                       315 UBC           0 :         case 2:
                                316               0 :             ereport(LOG,
 6016 tgl                       317 EUB             :                     (errmsg("duration: %s ms  fastpath function call: \"%s\" (OID %u)",
                                318                 :                             msec_str, fip->fname, fid)));
 6057 tgl                       319 UIC           0 :             break;
 6057 tgl                       320 EUB             :     }
 7276 tgl                       321 GIC        1063 : }
 7276 tgl                       322 ECB             : 
                                323                 : /*
                                324                 :  * Parse function arguments in a 3.0 protocol message
                                325                 :  *
                                326                 :  * Argument values are loaded into *fcinfo, and the desired result format
                                327                 :  * is returned.
                                328                 :  */
                                329                 : static int16
 2118 tgl                       330 GIC        1063 : parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
 7276 tgl                       331 ECB             :                       FunctionCallInfo fcinfo)
                                332                 : {
                                333                 :     int         nargs;
                                334                 :     int         i;
                                335                 :     int         numAFormats;
 7276 tgl                       336 GIC        1063 :     int16      *aformats = NULL;
 7275 tgl                       337 ECB             :     StringInfoData abuf;
                                338                 : 
                                339                 :     /* Get the argument format codes */
 7276 tgl                       340 GIC        1063 :     numAFormats = pq_getmsgint(msgBuf, 2);
 7276 tgl                       341 CBC        1063 :     if (numAFormats > 0)
 7276 tgl                       342 ECB             :     {
 7276 tgl                       343 GIC        1063 :         aformats = (int16 *) palloc(numAFormats * sizeof(int16));
 7276 tgl                       344 CBC        2126 :         for (i = 0; i < numAFormats; i++)
                                345            1063 :             aformats[i] = pq_getmsgint(msgBuf, 2);
 7276 tgl                       346 ECB             :     }
                                347                 : 
 7276 tgl                       348 GIC        1063 :     nargs = pq_getmsgint(msgBuf, 2);    /* # of arguments */
 7276 tgl                       349 ECB             : 
 8351 tgl                       350 GIC        1063 :     if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)
 7201 tgl                       351 LBC           0 :         ereport(ERROR,
 7201 tgl                       352 EUB             :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                353                 :                  errmsg("function call message contains %d arguments but function requires %d",
                                354                 :                         nargs, fip->flinfo.fn_nargs)));
                                355                 : 
 7276 tgl                       356 GIC        1063 :     fcinfo->nargs = nargs;
 8351 tgl                       357 ECB             : 
 7275 tgl                       358 GIC        1063 :     if (numAFormats > 1 && numAFormats != nargs)
 7201 tgl                       359 LBC           0 :         ereport(ERROR,
 7201 tgl                       360 EUB             :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                361                 :                  errmsg("function call message contains %d argument formats but %d arguments",
                                362                 :                         numAFormats, nargs)));
                                363                 : 
 7275 tgl                       364 GIC        1063 :     initStringInfo(&abuf);
 7275 tgl                       365 ECB             : 
                                366                 :     /*
                                367                 :      * Copy supplied arguments into arg vector.
                                368                 :      */
 8351 tgl                       369 GIC        3080 :     for (i = 0; i < nargs; ++i)
 9345 bruce                     370 ECB             :     {
                                371                 :         int         argsize;
                                372                 :         int16       aformat;
                                373                 : 
 7295 tgl                       374 GIC        2017 :         argsize = pq_getmsgint(msgBuf, 4);
 7275 tgl                       375 CBC        2017 :         if (argsize == -1)
 7275 tgl                       376 ECB             :         {
 1534 andres                    377 UIC           0 :             fcinfo->args[i].isnull = true;
 8351 tgl                       378 EUB             :         }
                                379                 :         else
                                380                 :         {
 1534 andres                    381 GIC        2017 :             fcinfo->args[i].isnull = false;
 6214 tgl                       382 CBC        2017 :             if (argsize < 0)
 6214 tgl                       383 LBC           0 :                 ereport(ERROR,
 6214 tgl                       384 EUB             :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                385                 :                          errmsg("invalid argument size %d in function call message",
                                386                 :                                 argsize)));
                                387                 : 
                                388                 :             /* Reset abuf to empty, and insert raw data into it */
 5881 neilc                     389 GIC        2017 :             resetStringInfo(&abuf);
 6214 tgl                       390 CBC        2017 :             appendBinaryStringInfo(&abuf,
                                391            2017 :                                    pq_getmsgbytes(msgBuf, argsize),
 6214 tgl                       392 ECB             :                                    argsize);
                                393                 :         }
                                394                 : 
 7275 tgl                       395 GIC        2017 :         if (numAFormats > 1)
 7275 tgl                       396 LBC           0 :             aformat = aformats[i];
 7275 tgl                       397 GBC        2017 :         else if (numAFormats > 0)
 7275 tgl                       398 CBC        2017 :             aformat = aformats[0];
 8351 tgl                       399 ECB             :         else
 7275 tgl                       400 UIC           0 :             aformat = 0;        /* default = text */
 7275 tgl                       401 EUB             : 
 7275 tgl                       402 GIC        2017 :         if (aformat == 0)
 7275 tgl                       403 ECB             :         {
                                404                 :             Oid         typinput;
                                405                 :             Oid         typioparam;
                                406                 :             char       *pstring;
                                407                 : 
 6881 tgl                       408 UIC           0 :             getTypeInputInfo(fip->argtypes[i], &typinput, &typioparam);
 7188 bruce                     409 EUB             : 
                                410                 :             /*
                                411                 :              * Since stringinfo.c keeps a trailing null in place even for
                                412                 :              * binary data, the contents of abuf are a valid C string.  We
                                413                 :              * have to do encoding conversion before calling the typinput
                                414                 :              * routine, though.
                                415                 :              */
 6214 tgl                       416 UIC           0 :             if (argsize == -1)
 6214 tgl                       417 UBC           0 :                 pstring = NULL;
 6214 tgl                       418 EUB             :             else
 6214 tgl                       419 UIC           0 :                 pstring = pg_client_to_server(abuf.data, argsize);
 6214 tgl                       420 EUB             : 
 1534 andres                    421 UIC           0 :             fcinfo->args[i].value = OidInputFunctionCall(typinput, pstring,
 1534 andres                    422 EUB             :                                                          typioparam, -1);
                                423                 :             /* Free result of encoding conversion, if any */
 6214 tgl                       424 UIC           0 :             if (pstring && pstring != abuf.data)
 7275 tgl                       425 UBC           0 :                 pfree(pstring);
 7275 tgl                       426 EUB             :         }
 7275 tgl                       427 GIC        2017 :         else if (aformat == 1)
 7275 tgl                       428 ECB             :         {
                                429                 :             Oid         typreceive;
                                430                 :             Oid         typioparam;
                                431                 :             StringInfo  bufptr;
                                432                 : 
                                433                 :             /* Call the argument type's binary input converter */
 6881 tgl                       434 GIC        2017 :             getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
 7275 tgl                       435 ECB             : 
 6214 tgl                       436 GIC        2017 :             if (argsize == -1)
 6214 tgl                       437 LBC           0 :                 bufptr = NULL;
 6214 tgl                       438 EUB             :             else
 6214 tgl                       439 GIC        2017 :                 bufptr = &abuf;
 6214 tgl                       440 ECB             : 
 1534 andres                    441 GIC        2017 :             fcinfo->args[i].value = OidReceiveFunctionCall(typreceive, bufptr,
 1534 andres                    442 ECB             :                                                            typioparam, -1);
                                443                 : 
                                444                 :             /* Trouble if it didn't eat the whole buffer */
 6214 tgl                       445 GIC        2017 :             if (argsize != -1 && abuf.cursor != abuf.len)
 7201 tgl                       446 LBC           0 :                 ereport(ERROR,
 7201 tgl                       447 EUB             :                         (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                448                 :                          errmsg("incorrect binary data format in function argument %d",
                                449                 :                                 i + 1)));
                                450                 :         }
                                451                 :         else
 7201 tgl                       452 UIC           0 :             ereport(ERROR,
 7201 tgl                       453 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                454                 :                      errmsg("unsupported format code: %d", aformat)));
                                455                 :     }
                                456                 : 
                                457                 :     /* Return result format code */
 7275 tgl                       458 GIC        1063 :     return (int16) pq_getmsgint(msgBuf, 2);
 7276 tgl                       459 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a