LCOV - code coverage report
Current view: top level - src/backend/nodes - params.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 72 78 92.3 %
Date: 2019-09-22 07:07:17 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * params.c
       4             :  *    Support for finding the values associated with Param nodes.
       5             :  *
       6             :  *
       7             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/nodes/params.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres.h"
      17             : 
      18             : #include "nodes/bitmapset.h"
      19             : #include "nodes/params.h"
      20             : #include "storage/shmem.h"
      21             : #include "utils/datum.h"
      22             : #include "utils/lsyscache.h"
      23             : 
      24             : 
      25             : /*
      26             :  * Allocate and initialize a new ParamListInfo structure.
      27             :  *
      28             :  * To make a new structure for the "dynamic" way (with hooks), pass 0 for
      29             :  * numParams and set numParams manually.
      30             :  */
      31             : ParamListInfo
      32      102250 : makeParamList(int numParams)
      33             : {
      34             :     ParamListInfo retval;
      35             :     Size        size;
      36             : 
      37      102250 :     size = offsetof(ParamListInfoData, params) +
      38      102250 :         numParams * sizeof(ParamExternData);
      39             : 
      40      102250 :     retval = (ParamListInfo) palloc(size);
      41      102250 :     retval->paramFetch = NULL;
      42      102250 :     retval->paramFetchArg = NULL;
      43      102250 :     retval->paramCompile = NULL;
      44      102250 :     retval->paramCompileArg = NULL;
      45      102250 :     retval->parserSetup = NULL;
      46      102250 :     retval->parserSetupArg = NULL;
      47      102250 :     retval->numParams = numParams;
      48             : 
      49      102250 :     return retval;
      50             : }
      51             : 
      52             : /*
      53             :  * Copy a ParamListInfo structure.
      54             :  *
      55             :  * The result is allocated in CurrentMemoryContext.
      56             :  *
      57             :  * Note: the intent of this function is to make a static, self-contained
      58             :  * set of parameter values.  If dynamic parameter hooks are present, we
      59             :  * intentionally do not copy them into the result.  Rather, we forcibly
      60             :  * instantiate all available parameter values and copy the datum values.
      61             :  */
      62             : ParamListInfo
      63        2640 : copyParamList(ParamListInfo from)
      64             : {
      65             :     ParamListInfo retval;
      66             : 
      67        2640 :     if (from == NULL || from->numParams <= 0)
      68        1230 :         return NULL;
      69             : 
      70        1410 :     retval = makeParamList(from->numParams);
      71             : 
      72        7184 :     for (int i = 0; i < from->numParams; i++)
      73             :     {
      74             :         ParamExternData *oprm;
      75        5774 :         ParamExternData *nprm = &retval->params[i];
      76             :         ParamExternData prmdata;
      77             :         int16       typLen;
      78             :         bool        typByVal;
      79             : 
      80             :         /* give hook a chance in case parameter is dynamic */
      81        5774 :         if (from->paramFetch != NULL)
      82        4636 :             oprm = from->paramFetch(from, i + 1, false, &prmdata);
      83             :         else
      84        1138 :             oprm = &from->params[i];
      85             : 
      86             :         /* flat-copy the parameter info */
      87        5774 :         *nprm = *oprm;
      88             : 
      89             :         /* need datumCopy in case it's a pass-by-reference datatype */
      90        5774 :         if (nprm->isnull || !OidIsValid(nprm->ptype))
      91        3914 :             continue;
      92        1860 :         get_typlenbyval(nprm->ptype, &typLen, &typByVal);
      93        1860 :         nprm->value = datumCopy(nprm->value, typByVal, typLen);
      94             :     }
      95             : 
      96        1410 :     return retval;
      97             : }
      98             : 
      99             : /*
     100             :  * Estimate the amount of space required to serialize a ParamListInfo.
     101             :  */
     102             : Size
     103         406 : EstimateParamListSpace(ParamListInfo paramLI)
     104             : {
     105             :     int         i;
     106         406 :     Size        sz = sizeof(int);
     107             : 
     108         406 :     if (paramLI == NULL || paramLI->numParams <= 0)
     109         342 :         return sz;
     110             : 
     111         220 :     for (i = 0; i < paramLI->numParams; i++)
     112             :     {
     113             :         ParamExternData *prm;
     114             :         ParamExternData prmdata;
     115             :         Oid         typeOid;
     116             :         int16       typLen;
     117             :         bool        typByVal;
     118             : 
     119             :         /* give hook a chance in case parameter is dynamic */
     120         156 :         if (paramLI->paramFetch != NULL)
     121           0 :             prm = paramLI->paramFetch(paramLI, i + 1, false, &prmdata);
     122             :         else
     123         156 :             prm = &paramLI->params[i];
     124             : 
     125         156 :         typeOid = prm->ptype;
     126             : 
     127         156 :         sz = add_size(sz, sizeof(Oid)); /* space for type OID */
     128         156 :         sz = add_size(sz, sizeof(uint16));  /* space for pflags */
     129             : 
     130             :         /* space for datum/isnull */
     131         156 :         if (OidIsValid(typeOid))
     132         156 :             get_typlenbyval(typeOid, &typLen, &typByVal);
     133             :         else
     134             :         {
     135             :             /* If no type OID, assume by-value, like copyParamList does. */
     136           0 :             typLen = sizeof(Datum);
     137           0 :             typByVal = true;
     138             :         }
     139         312 :         sz = add_size(sz,
     140         156 :                       datumEstimateSpace(prm->value, prm->isnull, typByVal, typLen));
     141             :     }
     142             : 
     143          64 :     return sz;
     144             : }
     145             : 
     146             : /*
     147             :  * Serialize a ParamListInfo structure into caller-provided storage.
     148             :  *
     149             :  * We write the number of parameters first, as a 4-byte integer, and then
     150             :  * write details for each parameter in turn.  The details for each parameter
     151             :  * consist of a 4-byte type OID, 2 bytes of flags, and then the datum as
     152             :  * serialized by datumSerialize().  The caller is responsible for ensuring
     153             :  * that there is enough storage to store the number of bytes that will be
     154             :  * written; use EstimateParamListSpace to find out how many will be needed.
     155             :  * *start_address is updated to point to the byte immediately following those
     156             :  * written.
     157             :  *
     158             :  * RestoreParamList can be used to recreate a ParamListInfo based on the
     159             :  * serialized representation; this will be a static, self-contained copy
     160             :  * just as copyParamList would create.
     161             :  */
     162             : void
     163         406 : SerializeParamList(ParamListInfo paramLI, char **start_address)
     164             : {
     165             :     int         nparams;
     166             :     int         i;
     167             : 
     168             :     /* Write number of parameters. */
     169         406 :     if (paramLI == NULL || paramLI->numParams <= 0)
     170         342 :         nparams = 0;
     171             :     else
     172          64 :         nparams = paramLI->numParams;
     173         406 :     memcpy(*start_address, &nparams, sizeof(int));
     174         406 :     *start_address += sizeof(int);
     175             : 
     176             :     /* Write each parameter in turn. */
     177         562 :     for (i = 0; i < nparams; i++)
     178             :     {
     179             :         ParamExternData *prm;
     180             :         ParamExternData prmdata;
     181             :         Oid         typeOid;
     182             :         int16       typLen;
     183             :         bool        typByVal;
     184             : 
     185             :         /* give hook a chance in case parameter is dynamic */
     186         156 :         if (paramLI->paramFetch != NULL)
     187           0 :             prm = paramLI->paramFetch(paramLI, i + 1, false, &prmdata);
     188             :         else
     189         156 :             prm = &paramLI->params[i];
     190             : 
     191         156 :         typeOid = prm->ptype;
     192             : 
     193             :         /* Write type OID. */
     194         156 :         memcpy(*start_address, &typeOid, sizeof(Oid));
     195         156 :         *start_address += sizeof(Oid);
     196             : 
     197             :         /* Write flags. */
     198         156 :         memcpy(*start_address, &prm->pflags, sizeof(uint16));
     199         156 :         *start_address += sizeof(uint16);
     200             : 
     201             :         /* Write datum/isnull. */
     202         156 :         if (OidIsValid(typeOid))
     203         156 :             get_typlenbyval(typeOid, &typLen, &typByVal);
     204             :         else
     205             :         {
     206             :             /* If no type OID, assume by-value, like copyParamList does. */
     207           0 :             typLen = sizeof(Datum);
     208           0 :             typByVal = true;
     209             :         }
     210         156 :         datumSerialize(prm->value, prm->isnull, typByVal, typLen,
     211             :                        start_address);
     212             :     }
     213         406 : }
     214             : 
     215             : /*
     216             :  * Copy a ParamListInfo structure.
     217             :  *
     218             :  * The result is allocated in CurrentMemoryContext.
     219             :  *
     220             :  * Note: the intent of this function is to make a static, self-contained
     221             :  * set of parameter values.  If dynamic parameter hooks are present, we
     222             :  * intentionally do not copy them into the result.  Rather, we forcibly
     223             :  * instantiate all available parameter values and copy the datum values.
     224             :  */
     225             : ParamListInfo
     226        1532 : RestoreParamList(char **start_address)
     227             : {
     228             :     ParamListInfo paramLI;
     229             :     int         nparams;
     230             : 
     231        1532 :     memcpy(&nparams, *start_address, sizeof(int));
     232        1532 :     *start_address += sizeof(int);
     233             : 
     234        1532 :     paramLI = makeParamList(nparams);
     235             : 
     236        1860 :     for (int i = 0; i < nparams; i++)
     237             :     {
     238         328 :         ParamExternData *prm = &paramLI->params[i];
     239             : 
     240             :         /* Read type OID. */
     241         328 :         memcpy(&prm->ptype, *start_address, sizeof(Oid));
     242         328 :         *start_address += sizeof(Oid);
     243             : 
     244             :         /* Read flags. */
     245         328 :         memcpy(&prm->pflags, *start_address, sizeof(uint16));
     246         328 :         *start_address += sizeof(uint16);
     247             : 
     248             :         /* Read datum/isnull. */
     249         328 :         prm->value = datumRestore(start_address, &prm->isnull);
     250             :     }
     251             : 
     252        1532 :     return paramLI;
     253             : }

Generated by: LCOV version 1.13