LCOV - code coverage report
Current view: top level - src/backend/nodes - params.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 50 95 52.6 %
Date: 2017-09-29 15:12:54 Functions: 4 4 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-2017, 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             :  * Copy a ParamListInfo structure.
      27             :  *
      28             :  * The result is allocated in CurrentMemoryContext.
      29             :  *
      30             :  * Note: the intent of this function is to make a static, self-contained
      31             :  * set of parameter values.  If dynamic parameter hooks are present, we
      32             :  * intentionally do not copy them into the result.  Rather, we forcibly
      33             :  * instantiate all available parameter values and copy the datum values.
      34             :  */
      35             : ParamListInfo
      36         118 : copyParamList(ParamListInfo from)
      37             : {
      38             :     ParamListInfo retval;
      39             :     Size        size;
      40             :     int         i;
      41             : 
      42         118 :     if (from == NULL || from->numParams <= 0)
      43          94 :         return NULL;
      44             : 
      45          24 :     size = offsetof(ParamListInfoData, params) +
      46          24 :         from->numParams * sizeof(ParamExternData);
      47             : 
      48          24 :     retval = (ParamListInfo) palloc(size);
      49          24 :     retval->paramFetch = NULL;
      50          24 :     retval->paramFetchArg = NULL;
      51          24 :     retval->parserSetup = NULL;
      52          24 :     retval->parserSetupArg = NULL;
      53          24 :     retval->numParams = from->numParams;
      54          24 :     retval->paramMask = NULL;
      55             : 
      56         168 :     for (i = 0; i < from->numParams; i++)
      57             :     {
      58         144 :         ParamExternData *oprm = &from->params[i];
      59         144 :         ParamExternData *nprm = &retval->params[i];
      60             :         int16       typLen;
      61             :         bool        typByVal;
      62             : 
      63             :         /* Ignore parameters we don't need, to save cycles and space. */
      64         144 :         if (from->paramMask != NULL &&
      65           0 :             !bms_is_member(i, from->paramMask))
      66             :         {
      67           0 :             nprm->value = (Datum) 0;
      68           0 :             nprm->isnull = true;
      69           0 :             nprm->pflags = 0;
      70           0 :             nprm->ptype = InvalidOid;
      71         109 :             continue;
      72             :         }
      73             : 
      74             :         /* give hook a chance in case parameter is dynamic */
      75         144 :         if (!OidIsValid(oprm->ptype) && from->paramFetch != NULL)
      76         109 :             (*from->paramFetch) (from, i + 1);
      77             : 
      78             :         /* flat-copy the parameter info */
      79         144 :         *nprm = *oprm;
      80             : 
      81             :         /* need datumCopy in case it's a pass-by-reference datatype */
      82         144 :         if (nprm->isnull || !OidIsValid(nprm->ptype))
      83         109 :             continue;
      84          35 :         get_typlenbyval(nprm->ptype, &typLen, &typByVal);
      85          35 :         nprm->value = datumCopy(nprm->value, typByVal, typLen);
      86             :     }
      87             : 
      88          24 :     return retval;
      89             : }
      90             : 
      91             : /*
      92             :  * Estimate the amount of space required to serialize a ParamListInfo.
      93             :  */
      94             : Size
      95          17 : EstimateParamListSpace(ParamListInfo paramLI)
      96             : {
      97             :     int         i;
      98          17 :     Size        sz = sizeof(int);
      99             : 
     100          17 :     if (paramLI == NULL || paramLI->numParams <= 0)
     101          17 :         return sz;
     102             : 
     103           0 :     for (i = 0; i < paramLI->numParams; i++)
     104             :     {
     105           0 :         ParamExternData *prm = &paramLI->params[i];
     106             :         Oid         typeOid;
     107             :         int16       typLen;
     108             :         bool        typByVal;
     109             : 
     110             :         /* Ignore parameters we don't need, to save cycles and space. */
     111           0 :         if (paramLI->paramMask != NULL &&
     112           0 :             !bms_is_member(i, paramLI->paramMask))
     113           0 :             typeOid = InvalidOid;
     114             :         else
     115             :         {
     116             :             /* give hook a chance in case parameter is dynamic */
     117           0 :             if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL)
     118           0 :                 (*paramLI->paramFetch) (paramLI, i + 1);
     119           0 :             typeOid = prm->ptype;
     120             :         }
     121             : 
     122           0 :         sz = add_size(sz, sizeof(Oid)); /* space for type OID */
     123           0 :         sz = add_size(sz, sizeof(uint16));  /* space for pflags */
     124             : 
     125             :         /* space for datum/isnull */
     126           0 :         if (OidIsValid(typeOid))
     127           0 :             get_typlenbyval(typeOid, &typLen, &typByVal);
     128             :         else
     129             :         {
     130             :             /* If no type OID, assume by-value, like copyParamList does. */
     131           0 :             typLen = sizeof(Datum);
     132           0 :             typByVal = true;
     133             :         }
     134           0 :         sz = add_size(sz,
     135           0 :                       datumEstimateSpace(prm->value, prm->isnull, typByVal, typLen));
     136             :     }
     137             : 
     138           0 :     return sz;
     139             : }
     140             : 
     141             : /*
     142             :  * Serialize a paramListInfo structure into caller-provided storage.
     143             :  *
     144             :  * We write the number of parameters first, as a 4-byte integer, and then
     145             :  * write details for each parameter in turn.  The details for each parameter
     146             :  * consist of a 4-byte type OID, 2 bytes of flags, and then the datum as
     147             :  * serialized by datumSerialize().  The caller is responsible for ensuring
     148             :  * that there is enough storage to store the number of bytes that will be
     149             :  * written; use EstimateParamListSpace to find out how many will be needed.
     150             :  * *start_address is updated to point to the byte immediately following those
     151             :  * written.
     152             :  *
     153             :  * RestoreParamList can be used to recreate a ParamListInfo based on the
     154             :  * serialized representation; this will be a static, self-contained copy
     155             :  * just as copyParamList would create.
     156             :  */
     157             : void
     158          17 : SerializeParamList(ParamListInfo paramLI, char **start_address)
     159             : {
     160             :     int         nparams;
     161             :     int         i;
     162             : 
     163             :     /* Write number of parameters. */
     164          17 :     if (paramLI == NULL || paramLI->numParams <= 0)
     165          17 :         nparams = 0;
     166             :     else
     167           0 :         nparams = paramLI->numParams;
     168          17 :     memcpy(*start_address, &nparams, sizeof(int));
     169          17 :     *start_address += sizeof(int);
     170             : 
     171             :     /* Write each parameter in turn. */
     172          17 :     for (i = 0; i < nparams; i++)
     173             :     {
     174           0 :         ParamExternData *prm = &paramLI->params[i];
     175             :         Oid         typeOid;
     176             :         int16       typLen;
     177             :         bool        typByVal;
     178             : 
     179             :         /* Ignore parameters we don't need, to save cycles and space. */
     180           0 :         if (paramLI->paramMask != NULL &&
     181           0 :             !bms_is_member(i, paramLI->paramMask))
     182           0 :             typeOid = InvalidOid;
     183             :         else
     184             :         {
     185             :             /* give hook a chance in case parameter is dynamic */
     186           0 :             if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL)
     187           0 :                 (*paramLI->paramFetch) (paramLI, i + 1);
     188           0 :             typeOid = prm->ptype;
     189             :         }
     190             : 
     191             :         /* Write type OID. */
     192           0 :         memcpy(*start_address, &typeOid, sizeof(Oid));
     193           0 :         *start_address += sizeof(Oid);
     194             : 
     195             :         /* Write flags. */
     196           0 :         memcpy(*start_address, &prm->pflags, sizeof(uint16));
     197           0 :         *start_address += sizeof(uint16);
     198             : 
     199             :         /* Write datum/isnull. */
     200           0 :         if (OidIsValid(typeOid))
     201           0 :             get_typlenbyval(typeOid, &typLen, &typByVal);
     202             :         else
     203             :         {
     204             :             /* If no type OID, assume by-value, like copyParamList does. */
     205           0 :             typLen = sizeof(Datum);
     206           0 :             typByVal = true;
     207             :         }
     208           0 :         datumSerialize(prm->value, prm->isnull, typByVal, typLen,
     209             :                        start_address);
     210             :     }
     211          17 : }
     212             : 
     213             : /*
     214             :  * Copy a ParamListInfo structure.
     215             :  *
     216             :  * The result is allocated in CurrentMemoryContext.
     217             :  *
     218             :  * Note: the intent of this function is to make a static, self-contained
     219             :  * set of parameter values.  If dynamic parameter hooks are present, we
     220             :  * intentionally do not copy them into the result.  Rather, we forcibly
     221             :  * instantiate all available parameter values and copy the datum values.
     222             :  */
     223             : ParamListInfo
     224         115 : RestoreParamList(char **start_address)
     225             : {
     226             :     ParamListInfo paramLI;
     227             :     Size        size;
     228             :     int         i;
     229             :     int         nparams;
     230             : 
     231         115 :     memcpy(&nparams, *start_address, sizeof(int));
     232         115 :     *start_address += sizeof(int);
     233             : 
     234         115 :     size = offsetof(ParamListInfoData, params) +
     235         115 :         nparams * sizeof(ParamExternData);
     236             : 
     237         115 :     paramLI = (ParamListInfo) palloc(size);
     238         115 :     paramLI->paramFetch = NULL;
     239         115 :     paramLI->paramFetchArg = NULL;
     240         115 :     paramLI->parserSetup = NULL;
     241         115 :     paramLI->parserSetupArg = NULL;
     242         115 :     paramLI->numParams = nparams;
     243         115 :     paramLI->paramMask = NULL;
     244             : 
     245         115 :     for (i = 0; i < nparams; i++)
     246             :     {
     247           0 :         ParamExternData *prm = &paramLI->params[i];
     248             : 
     249             :         /* Read type OID. */
     250           0 :         memcpy(&prm->ptype, *start_address, sizeof(Oid));
     251           0 :         *start_address += sizeof(Oid);
     252             : 
     253             :         /* Read flags. */
     254           0 :         memcpy(&prm->pflags, *start_address, sizeof(uint16));
     255           0 :         *start_address += sizeof(uint16);
     256             : 
     257             :         /* Read datum/isnull. */
     258           0 :         prm->value = datumRestore(start_address, &prm->isnull);
     259             :     }
     260             : 
     261         115 :     return paramLI;
     262             : }

Generated by: LCOV version 1.11