LCOV - code coverage report
Current view: top level - src/backend/executor - execJunk.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 71 75 94.7 %
Date: 2019-06-18 07:06:57 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * execJunk.c
       4             :  *    Junk attribute support stuff....
       5             :  *
       6             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/executor/execJunk.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "executor/executor.h"
      18             : 
      19             : /*-------------------------------------------------------------------------
      20             :  *      XXX this stuff should be rewritten to take advantage
      21             :  *          of ExecProject() and the ProjectionInfo node.
      22             :  *          -cim 6/3/91
      23             :  *
      24             :  * An attribute of a tuple living inside the executor, can be
      25             :  * either a normal attribute or a "junk" attribute. "junk" attributes
      26             :  * never make it out of the executor, i.e. they are never printed,
      27             :  * returned or stored on disk. Their only purpose in life is to
      28             :  * store some information useful only to the executor, mainly the values
      29             :  * of system attributes like "ctid", or sort key columns that are not to
      30             :  * be output.
      31             :  *
      32             :  * The general idea is the following: A target list consists of a list of
      33             :  * TargetEntry nodes containing expressions. Each TargetEntry has a field
      34             :  * called 'resjunk'. If the value of this field is true then the
      35             :  * corresponding attribute is a "junk" attribute.
      36             :  *
      37             :  * When we initialize a plan we call ExecInitJunkFilter to create a filter.
      38             :  *
      39             :  * We then execute the plan, treating the resjunk attributes like any others.
      40             :  *
      41             :  * Finally, when at the top level we get back a tuple, we can call
      42             :  * ExecFindJunkAttribute/ExecGetJunkAttribute to retrieve the values of the
      43             :  * junk attributes we are interested in, and ExecFilterJunk to remove all the
      44             :  * junk attributes from a tuple.  This new "clean" tuple is then printed,
      45             :  * inserted, or updated.
      46             :  *
      47             :  *-------------------------------------------------------------------------
      48             :  */
      49             : 
      50             : /*
      51             :  * ExecInitJunkFilter
      52             :  *
      53             :  * Initialize the Junk filter.
      54             :  *
      55             :  * The source targetlist is passed in.  The output tuple descriptor is
      56             :  * built from the non-junk tlist entries.
      57             :  * An optional resultSlot can be passed as well.
      58             :  */
      59             : JunkFilter *
      60       36208 : ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
      61             : {
      62             :     JunkFilter *junkfilter;
      63             :     TupleDesc   cleanTupType;
      64             :     int         cleanLength;
      65             :     AttrNumber *cleanMap;
      66             :     ListCell   *t;
      67             :     AttrNumber  cleanResno;
      68             : 
      69             :     /*
      70             :      * Compute the tuple descriptor for the cleaned tuple.
      71             :      */
      72       36208 :     cleanTupType = ExecCleanTypeFromTL(targetList);
      73             : 
      74             :     /*
      75             :      * Use the given slot, or make a new slot if we weren't given one.
      76             :      */
      77       36208 :     if (slot)
      78       36208 :         ExecSetSlotDescriptor(slot, cleanTupType);
      79             :     else
      80           0 :         slot = MakeSingleTupleTableSlot(cleanTupType, &TTSOpsVirtual);
      81             : 
      82             :     /*
      83             :      * Now calculate the mapping between the original tuple's attributes and
      84             :      * the "clean" tuple's attributes.
      85             :      *
      86             :      * The "map" is an array of "cleanLength" attribute numbers, i.e. one
      87             :      * entry for every attribute of the "clean" tuple. The value of this entry
      88             :      * is the attribute number of the corresponding attribute of the
      89             :      * "original" tuple.  (Zero indicates a NULL output attribute, but we do
      90             :      * not use that feature in this routine.)
      91             :      */
      92       36208 :     cleanLength = cleanTupType->natts;
      93       36208 :     if (cleanLength > 0)
      94             :     {
      95       33160 :         cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
      96       33160 :         cleanResno = 1;
      97      211324 :         foreach(t, targetList)
      98             :         {
      99      178164 :             TargetEntry *tle = lfirst(t);
     100             : 
     101      178164 :             if (!tle->resjunk)
     102             :             {
     103      152946 :                 cleanMap[cleanResno - 1] = tle->resno;
     104      152946 :                 cleanResno++;
     105             :             }
     106             :         }
     107             :     }
     108             :     else
     109        3048 :         cleanMap = NULL;
     110             : 
     111             :     /*
     112             :      * Finally create and initialize the JunkFilter struct.
     113             :      */
     114       36208 :     junkfilter = makeNode(JunkFilter);
     115             : 
     116       36208 :     junkfilter->jf_targetList = targetList;
     117       36208 :     junkfilter->jf_cleanTupType = cleanTupType;
     118       36208 :     junkfilter->jf_cleanMap = cleanMap;
     119       36208 :     junkfilter->jf_resultSlot = slot;
     120             : 
     121       36208 :     return junkfilter;
     122             : }
     123             : 
     124             : /*
     125             :  * ExecInitJunkFilterConversion
     126             :  *
     127             :  * Initialize a JunkFilter for rowtype conversions.
     128             :  *
     129             :  * Here, we are given the target "clean" tuple descriptor rather than
     130             :  * inferring it from the targetlist.  The target descriptor can contain
     131             :  * deleted columns.  It is assumed that the caller has checked that the
     132             :  * non-deleted columns match up with the non-junk columns of the targetlist.
     133             :  */
     134             : JunkFilter *
     135         632 : ExecInitJunkFilterConversion(List *targetList,
     136             :                              TupleDesc cleanTupType,
     137             :                              TupleTableSlot *slot)
     138             : {
     139             :     JunkFilter *junkfilter;
     140             :     int         cleanLength;
     141             :     AttrNumber *cleanMap;
     142             :     ListCell   *t;
     143             :     int         i;
     144             : 
     145             :     /*
     146             :      * Use the given slot, or make a new slot if we weren't given one.
     147             :      */
     148         632 :     if (slot)
     149         632 :         ExecSetSlotDescriptor(slot, cleanTupType);
     150             :     else
     151           0 :         slot = MakeSingleTupleTableSlot(cleanTupType, &TTSOpsVirtual);
     152             : 
     153             :     /*
     154             :      * Calculate the mapping between the original tuple's attributes and the
     155             :      * "clean" tuple's attributes.
     156             :      *
     157             :      * The "map" is an array of "cleanLength" attribute numbers, i.e. one
     158             :      * entry for every attribute of the "clean" tuple. The value of this entry
     159             :      * is the attribute number of the corresponding attribute of the
     160             :      * "original" tuple.  We store zero for any deleted attributes, marking
     161             :      * that a NULL is needed in the output tuple.
     162             :      */
     163         632 :     cleanLength = cleanTupType->natts;
     164         632 :     if (cleanLength > 0)
     165             :     {
     166         632 :         cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
     167         632 :         t = list_head(targetList);
     168        2504 :         for (i = 0; i < cleanLength; i++)
     169             :         {
     170        1872 :             if (TupleDescAttr(cleanTupType, i)->attisdropped)
     171          44 :                 continue;       /* map entry is already zero */
     172             :             for (;;)
     173           0 :             {
     174        1828 :                 TargetEntry *tle = lfirst(t);
     175             : 
     176        1828 :                 t = lnext(t);
     177        1828 :                 if (!tle->resjunk)
     178             :                 {
     179        1828 :                     cleanMap[i] = tle->resno;
     180        1828 :                     break;
     181             :                 }
     182             :             }
     183             :         }
     184             :     }
     185             :     else
     186           0 :         cleanMap = NULL;
     187             : 
     188             :     /*
     189             :      * Finally create and initialize the JunkFilter struct.
     190             :      */
     191         632 :     junkfilter = makeNode(JunkFilter);
     192             : 
     193         632 :     junkfilter->jf_targetList = targetList;
     194         632 :     junkfilter->jf_cleanTupType = cleanTupType;
     195         632 :     junkfilter->jf_cleanMap = cleanMap;
     196         632 :     junkfilter->jf_resultSlot = slot;
     197             : 
     198         632 :     return junkfilter;
     199             : }
     200             : 
     201             : /*
     202             :  * ExecFindJunkAttribute
     203             :  *
     204             :  * Locate the specified junk attribute in the junk filter's targetlist,
     205             :  * and return its resno.  Returns InvalidAttrNumber if not found.
     206             :  */
     207             : AttrNumber
     208       13494 : ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
     209             : {
     210       13494 :     return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
     211             : }
     212             : 
     213             : /*
     214             :  * ExecFindJunkAttributeInTlist
     215             :  *
     216             :  * Find a junk attribute given a subplan's targetlist (not necessarily
     217             :  * part of a JunkFilter).
     218             :  */
     219             : AttrNumber
     220       20766 : ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
     221             : {
     222             :     ListCell   *t;
     223             : 
     224      149872 :     foreach(t, targetlist)
     225             :     {
     226      149658 :         TargetEntry *tle = lfirst(t);
     227             : 
     228      173792 :         if (tle->resjunk && tle->resname &&
     229       24134 :             (strcmp(tle->resname, attrName) == 0))
     230             :         {
     231             :             /* We found it ! */
     232       20552 :             return tle->resno;
     233             :         }
     234             :     }
     235             : 
     236         214 :     return InvalidAttrNumber;
     237             : }
     238             : 
     239             : /*
     240             :  * ExecGetJunkAttribute
     241             :  *
     242             :  * Given a junk filter's input tuple (slot) and a junk attribute's number
     243             :  * previously found by ExecFindJunkAttribute, extract & return the value and
     244             :  * isNull flag of the attribute.
     245             :  */
     246             : Datum
     247      954058 : ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
     248             :                      bool *isNull)
     249             : {
     250             :     Assert(attno > 0);
     251             : 
     252      954058 :     return slot_getattr(slot, attno, isNull);
     253             : }
     254             : 
     255             : /*
     256             :  * ExecFilterJunk
     257             :  *
     258             :  * Construct and return a slot with all the junk attributes removed.
     259             :  */
     260             : TupleTableSlot *
     261      356206 : ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
     262             : {
     263             :     TupleTableSlot *resultSlot;
     264             :     AttrNumber *cleanMap;
     265             :     TupleDesc   cleanTupType;
     266             :     int         cleanLength;
     267             :     int         i;
     268             :     Datum      *values;
     269             :     bool       *isnull;
     270             :     Datum      *old_values;
     271             :     bool       *old_isnull;
     272             : 
     273             :     /*
     274             :      * Extract all the values of the old tuple.
     275             :      */
     276      356206 :     slot_getallattrs(slot);
     277      356206 :     old_values = slot->tts_values;
     278      356206 :     old_isnull = slot->tts_isnull;
     279             : 
     280             :     /*
     281             :      * get info from the junk filter
     282             :      */
     283      356206 :     cleanTupType = junkfilter->jf_cleanTupType;
     284      356206 :     cleanLength = cleanTupType->natts;
     285      356206 :     cleanMap = junkfilter->jf_cleanMap;
     286      356206 :     resultSlot = junkfilter->jf_resultSlot;
     287             : 
     288             :     /*
     289             :      * Prepare to build a virtual result tuple.
     290             :      */
     291      356206 :     ExecClearTuple(resultSlot);
     292      356206 :     values = resultSlot->tts_values;
     293      356206 :     isnull = resultSlot->tts_isnull;
     294             : 
     295             :     /*
     296             :      * Transpose data into proper fields of the new tuple.
     297             :      */
     298     2361874 :     for (i = 0; i < cleanLength; i++)
     299             :     {
     300     2005668 :         int         j = cleanMap[i];
     301             : 
     302     2005668 :         if (j == 0)
     303             :         {
     304          80 :             values[i] = (Datum) 0;
     305          80 :             isnull[i] = true;
     306             :         }
     307             :         else
     308             :         {
     309     2005588 :             values[i] = old_values[j - 1];
     310     2005588 :             isnull[i] = old_isnull[j - 1];
     311             :         }
     312             :     }
     313             : 
     314             :     /*
     315             :      * And return the virtual tuple.
     316             :      */
     317      356206 :     return ExecStoreVirtualTuple(resultSlot);
     318             : }

Generated by: LCOV version 1.13