LCOV - code coverage report
Current view: top level - src/backend/executor - execJunk.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 72 76 94.7 %
Date: 2017-09-29 15:12:54 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-2017, 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, plus the passed specification
      57             :  * of whether to include room for an OID or not.
      58             :  * An optional resultSlot can be passed as well.
      59             :  */
      60             : JunkFilter *
      61        4755 : ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
      62             : {
      63             :     JunkFilter *junkfilter;
      64             :     TupleDesc   cleanTupType;
      65             :     int         cleanLength;
      66             :     AttrNumber *cleanMap;
      67             :     ListCell   *t;
      68             :     AttrNumber  cleanResno;
      69             : 
      70             :     /*
      71             :      * Compute the tuple descriptor for the cleaned tuple.
      72             :      */
      73        4755 :     cleanTupType = ExecCleanTypeFromTL(targetList, hasoid);
      74             : 
      75             :     /*
      76             :      * Use the given slot, or make a new slot if we weren't given one.
      77             :      */
      78        4755 :     if (slot)
      79        2036 :         ExecSetSlotDescriptor(slot, cleanTupType);
      80             :     else
      81        2719 :         slot = MakeSingleTupleTableSlot(cleanTupType);
      82             : 
      83             :     /*
      84             :      * Now calculate the mapping between the original tuple's attributes and
      85             :      * the "clean" tuple's attributes.
      86             :      *
      87             :      * The "map" is an array of "cleanLength" attribute numbers, i.e. one
      88             :      * entry for every attribute of the "clean" tuple. The value of this entry
      89             :      * is the attribute number of the corresponding attribute of the
      90             :      * "original" tuple.  (Zero indicates a NULL output attribute, but we do
      91             :      * not use that feature in this routine.)
      92             :      */
      93        4755 :     cleanLength = cleanTupType->natts;
      94        4755 :     if (cleanLength > 0)
      95             :     {
      96        4422 :         cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
      97        4422 :         cleanResno = 1;
      98       12860 :         foreach(t, targetList)
      99             :         {
     100        8438 :             TargetEntry *tle = lfirst(t);
     101             : 
     102        8438 :             if (!tle->resjunk)
     103             :             {
     104        6436 :                 cleanMap[cleanResno - 1] = tle->resno;
     105        6436 :                 cleanResno++;
     106             :             }
     107             :         }
     108             :     }
     109             :     else
     110         333 :         cleanMap = NULL;
     111             : 
     112             :     /*
     113             :      * Finally create and initialize the JunkFilter struct.
     114             :      */
     115        4755 :     junkfilter = makeNode(JunkFilter);
     116             : 
     117        4755 :     junkfilter->jf_targetList = targetList;
     118        4755 :     junkfilter->jf_cleanTupType = cleanTupType;
     119        4755 :     junkfilter->jf_cleanMap = cleanMap;
     120        4755 :     junkfilter->jf_resultSlot = slot;
     121             : 
     122        4755 :     return junkfilter;
     123             : }
     124             : 
     125             : /*
     126             :  * ExecInitJunkFilterConversion
     127             :  *
     128             :  * Initialize a JunkFilter for rowtype conversions.
     129             :  *
     130             :  * Here, we are given the target "clean" tuple descriptor rather than
     131             :  * inferring it from the targetlist.  The target descriptor can contain
     132             :  * deleted columns.  It is assumed that the caller has checked that the
     133             :  * non-deleted columns match up with the non-junk columns of the targetlist.
     134             :  */
     135             : JunkFilter *
     136         156 : ExecInitJunkFilterConversion(List *targetList,
     137             :                              TupleDesc cleanTupType,
     138             :                              TupleTableSlot *slot)
     139             : {
     140             :     JunkFilter *junkfilter;
     141             :     int         cleanLength;
     142             :     AttrNumber *cleanMap;
     143             :     ListCell   *t;
     144             :     int         i;
     145             : 
     146             :     /*
     147             :      * Use the given slot, or make a new slot if we weren't given one.
     148             :      */
     149         156 :     if (slot)
     150           0 :         ExecSetSlotDescriptor(slot, cleanTupType);
     151             :     else
     152         156 :         slot = MakeSingleTupleTableSlot(cleanTupType);
     153             : 
     154             :     /*
     155             :      * Calculate the mapping between the original tuple's attributes and the
     156             :      * "clean" tuple's attributes.
     157             :      *
     158             :      * The "map" is an array of "cleanLength" attribute numbers, i.e. one
     159             :      * entry for every attribute of the "clean" tuple. The value of this entry
     160             :      * is the attribute number of the corresponding attribute of the
     161             :      * "original" tuple.  We store zero for any deleted attributes, marking
     162             :      * that a NULL is needed in the output tuple.
     163             :      */
     164         156 :     cleanLength = cleanTupType->natts;
     165         156 :     if (cleanLength > 0)
     166             :     {
     167         156 :         cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
     168         156 :         t = list_head(targetList);
     169         616 :         for (i = 0; i < cleanLength; i++)
     170             :         {
     171         460 :             if (TupleDescAttr(cleanTupType, i)->attisdropped)
     172          11 :                 continue;       /* map entry is already zero */
     173             :             for (;;)
     174             :             {
     175         449 :                 TargetEntry *tle = lfirst(t);
     176             : 
     177         449 :                 t = lnext(t);
     178         449 :                 if (!tle->resjunk)
     179             :                 {
     180         449 :                     cleanMap[i] = tle->resno;
     181         449 :                     break;
     182             :                 }
     183           0 :             }
     184             :         }
     185             :     }
     186             :     else
     187           0 :         cleanMap = NULL;
     188             : 
     189             :     /*
     190             :      * Finally create and initialize the JunkFilter struct.
     191             :      */
     192         156 :     junkfilter = makeNode(JunkFilter);
     193             : 
     194         156 :     junkfilter->jf_targetList = targetList;
     195         156 :     junkfilter->jf_cleanTupType = cleanTupType;
     196         156 :     junkfilter->jf_cleanMap = cleanMap;
     197         156 :     junkfilter->jf_resultSlot = slot;
     198             : 
     199         156 :     return junkfilter;
     200             : }
     201             : 
     202             : /*
     203             :  * ExecFindJunkAttribute
     204             :  *
     205             :  * Locate the specified junk attribute in the junk filter's targetlist,
     206             :  * and return its resno.  Returns InvalidAttrNumber if not found.
     207             :  */
     208             : AttrNumber
     209        1043 : ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
     210             : {
     211        1043 :     return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
     212             : }
     213             : 
     214             : /*
     215             :  * ExecFindJunkAttributeInTlist
     216             :  *
     217             :  * Find a junk attribute given a subplan's targetlist (not necessarily
     218             :  * part of a JunkFilter).
     219             :  */
     220             : AttrNumber
     221        1699 : ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
     222             : {
     223             :     ListCell   *t;
     224             : 
     225        5361 :     foreach(t, targetlist)
     226             :     {
     227        5361 :         TargetEntry *tle = lfirst(t);
     228             : 
     229        7465 :         if (tle->resjunk && tle->resname &&
     230        2104 :             (strcmp(tle->resname, attrName) == 0))
     231             :         {
     232             :             /* We found it ! */
     233        1699 :             return tle->resno;
     234             :         }
     235             :     }
     236             : 
     237           0 :     return InvalidAttrNumber;
     238             : }
     239             : 
     240             : /*
     241             :  * ExecGetJunkAttribute
     242             :  *
     243             :  * Given a junk filter's input tuple (slot) and a junk attribute's number
     244             :  * previously found by ExecFindJunkAttribute, extract & return the value and
     245             :  * isNull flag of the attribute.
     246             :  */
     247             : Datum
     248       69533 : ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
     249             :                      bool *isNull)
     250             : {
     251       69533 :     Assert(attno > 0);
     252             : 
     253       69533 :     return slot_getattr(slot, attno, isNull);
     254             : }
     255             : 
     256             : /*
     257             :  * ExecFilterJunk
     258             :  *
     259             :  * Construct and return a slot with all the junk attributes removed.
     260             :  */
     261             : TupleTableSlot *
     262       28682 : ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
     263             : {
     264             :     TupleTableSlot *resultSlot;
     265             :     AttrNumber *cleanMap;
     266             :     TupleDesc   cleanTupType;
     267             :     int         cleanLength;
     268             :     int         i;
     269             :     Datum      *values;
     270             :     bool       *isnull;
     271             :     Datum      *old_values;
     272             :     bool       *old_isnull;
     273             : 
     274             :     /*
     275             :      * Extract all the values of the old tuple.
     276             :      */
     277       28682 :     slot_getallattrs(slot);
     278       28682 :     old_values = slot->tts_values;
     279       28682 :     old_isnull = slot->tts_isnull;
     280             : 
     281             :     /*
     282             :      * get info from the junk filter
     283             :      */
     284       28682 :     cleanTupType = junkfilter->jf_cleanTupType;
     285       28682 :     cleanLength = cleanTupType->natts;
     286       28682 :     cleanMap = junkfilter->jf_cleanMap;
     287       28682 :     resultSlot = junkfilter->jf_resultSlot;
     288             : 
     289             :     /*
     290             :      * Prepare to build a virtual result tuple.
     291             :      */
     292       28682 :     ExecClearTuple(resultSlot);
     293       28682 :     values = resultSlot->tts_values;
     294       28682 :     isnull = resultSlot->tts_isnull;
     295             : 
     296             :     /*
     297             :      * Transpose data into proper fields of the new tuple.
     298             :      */
     299      124619 :     for (i = 0; i < cleanLength; i++)
     300             :     {
     301       95937 :         int         j = cleanMap[i];
     302             : 
     303       95937 :         if (j == 0)
     304             :         {
     305          20 :             values[i] = (Datum) 0;
     306          20 :             isnull[i] = true;
     307             :         }
     308             :         else
     309             :         {
     310       95917 :             values[i] = old_values[j - 1];
     311       95917 :             isnull[i] = old_isnull[j - 1];
     312             :         }
     313             :     }
     314             : 
     315             :     /*
     316             :      * And return the virtual tuple.
     317             :      */
     318       28682 :     return ExecStoreVirtualTuple(resultSlot);
     319             : }

Generated by: LCOV version 1.11