Header And Logo

PostgreSQL
| The world's most advanced open source database.

execJunk.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * execJunk.c
00004  *    Junk attribute support stuff....
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/executor/execJunk.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "executor/executor.h"
00018 
00019 /*-------------------------------------------------------------------------
00020  *      XXX this stuff should be rewritten to take advantage
00021  *          of ExecProject() and the ProjectionInfo node.
00022  *          -cim 6/3/91
00023  *
00024  * An attribute of a tuple living inside the executor, can be
00025  * either a normal attribute or a "junk" attribute. "junk" attributes
00026  * never make it out of the executor, i.e. they are never printed,
00027  * returned or stored on disk. Their only purpose in life is to
00028  * store some information useful only to the executor, mainly the values
00029  * of system attributes like "ctid", or sort key columns that are not to
00030  * be output.
00031  *
00032  * The general idea is the following: A target list consists of a list of
00033  * TargetEntry nodes containing expressions. Each TargetEntry has a field
00034  * called 'resjunk'. If the value of this field is true then the
00035  * corresponding attribute is a "junk" attribute.
00036  *
00037  * When we initialize a plan we call ExecInitJunkFilter to create a filter.
00038  *
00039  * We then execute the plan, treating the resjunk attributes like any others.
00040  *
00041  * Finally, when at the top level we get back a tuple, we can call
00042  * ExecFindJunkAttribute/ExecGetJunkAttribute to retrieve the values of the
00043  * junk attributes we are interested in, and ExecFilterJunk to remove all the
00044  * junk attributes from a tuple.  This new "clean" tuple is then printed,
00045  * inserted, or updated.
00046  *
00047  *-------------------------------------------------------------------------
00048  */
00049 
00050 /*
00051  * ExecInitJunkFilter
00052  *
00053  * Initialize the Junk filter.
00054  *
00055  * The source targetlist is passed in.  The output tuple descriptor is
00056  * built from the non-junk tlist entries, plus the passed specification
00057  * of whether to include room for an OID or not.
00058  * An optional resultSlot can be passed as well.
00059  */
00060 JunkFilter *
00061 ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
00062 {
00063     JunkFilter *junkfilter;
00064     TupleDesc   cleanTupType;
00065     int         cleanLength;
00066     AttrNumber *cleanMap;
00067     ListCell   *t;
00068     AttrNumber  cleanResno;
00069 
00070     /*
00071      * Compute the tuple descriptor for the cleaned tuple.
00072      */
00073     cleanTupType = ExecCleanTypeFromTL(targetList, hasoid);
00074 
00075     /*
00076      * Use the given slot, or make a new slot if we weren't given one.
00077      */
00078     if (slot)
00079         ExecSetSlotDescriptor(slot, cleanTupType);
00080     else
00081         slot = MakeSingleTupleTableSlot(cleanTupType);
00082 
00083     /*
00084      * Now calculate the mapping between the original tuple's attributes and
00085      * the "clean" tuple's attributes.
00086      *
00087      * The "map" is an array of "cleanLength" attribute numbers, i.e. one
00088      * entry for every attribute of the "clean" tuple. The value of this entry
00089      * is the attribute number of the corresponding attribute of the
00090      * "original" tuple.  (Zero indicates a NULL output attribute, but we do
00091      * not use that feature in this routine.)
00092      */
00093     cleanLength = cleanTupType->natts;
00094     if (cleanLength > 0)
00095     {
00096         cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
00097         cleanResno = 1;
00098         foreach(t, targetList)
00099         {
00100             TargetEntry *tle = lfirst(t);
00101 
00102             if (!tle->resjunk)
00103             {
00104                 cleanMap[cleanResno - 1] = tle->resno;
00105                 cleanResno++;
00106             }
00107         }
00108     }
00109     else
00110         cleanMap = NULL;
00111 
00112     /*
00113      * Finally create and initialize the JunkFilter struct.
00114      */
00115     junkfilter = makeNode(JunkFilter);
00116 
00117     junkfilter->jf_targetList = targetList;
00118     junkfilter->jf_cleanTupType = cleanTupType;
00119     junkfilter->jf_cleanMap = cleanMap;
00120     junkfilter->jf_resultSlot = slot;
00121 
00122     return junkfilter;
00123 }
00124 
00125 /*
00126  * ExecInitJunkFilterConversion
00127  *
00128  * Initialize a JunkFilter for rowtype conversions.
00129  *
00130  * Here, we are given the target "clean" tuple descriptor rather than
00131  * inferring it from the targetlist.  The target descriptor can contain
00132  * deleted columns.  It is assumed that the caller has checked that the
00133  * non-deleted columns match up with the non-junk columns of the targetlist.
00134  */
00135 JunkFilter *
00136 ExecInitJunkFilterConversion(List *targetList,
00137                              TupleDesc cleanTupType,
00138                              TupleTableSlot *slot)
00139 {
00140     JunkFilter *junkfilter;
00141     int         cleanLength;
00142     AttrNumber *cleanMap;
00143     ListCell   *t;
00144     int         i;
00145 
00146     /*
00147      * Use the given slot, or make a new slot if we weren't given one.
00148      */
00149     if (slot)
00150         ExecSetSlotDescriptor(slot, cleanTupType);
00151     else
00152         slot = MakeSingleTupleTableSlot(cleanTupType);
00153 
00154     /*
00155      * Calculate the mapping between the original tuple's attributes and the
00156      * "clean" tuple's attributes.
00157      *
00158      * The "map" is an array of "cleanLength" attribute numbers, i.e. one
00159      * entry for every attribute of the "clean" tuple. The value of this entry
00160      * is the attribute number of the corresponding attribute of the
00161      * "original" tuple.  We store zero for any deleted attributes, marking
00162      * that a NULL is needed in the output tuple.
00163      */
00164     cleanLength = cleanTupType->natts;
00165     if (cleanLength > 0)
00166     {
00167         cleanMap = (AttrNumber *) palloc0(cleanLength * sizeof(AttrNumber));
00168         t = list_head(targetList);
00169         for (i = 0; i < cleanLength; i++)
00170         {
00171             if (cleanTupType->attrs[i]->attisdropped)
00172                 continue;       /* map entry is already zero */
00173             for (;;)
00174             {
00175                 TargetEntry *tle = lfirst(t);
00176 
00177                 t = lnext(t);
00178                 if (!tle->resjunk)
00179                 {
00180                     cleanMap[i] = tle->resno;
00181                     break;
00182                 }
00183             }
00184         }
00185     }
00186     else
00187         cleanMap = NULL;
00188 
00189     /*
00190      * Finally create and initialize the JunkFilter struct.
00191      */
00192     junkfilter = makeNode(JunkFilter);
00193 
00194     junkfilter->jf_targetList = targetList;
00195     junkfilter->jf_cleanTupType = cleanTupType;
00196     junkfilter->jf_cleanMap = cleanMap;
00197     junkfilter->jf_resultSlot = slot;
00198 
00199     return junkfilter;
00200 }
00201 
00202 /*
00203  * ExecFindJunkAttribute
00204  *
00205  * Locate the specified junk attribute in the junk filter's targetlist,
00206  * and return its resno.  Returns InvalidAttrNumber if not found.
00207  */
00208 AttrNumber
00209 ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
00210 {
00211     return ExecFindJunkAttributeInTlist(junkfilter->jf_targetList, attrName);
00212 }
00213 
00214 /*
00215  * ExecFindJunkAttributeInTlist
00216  *
00217  * Find a junk attribute given a subplan's targetlist (not necessarily
00218  * part of a JunkFilter).
00219  */
00220 AttrNumber
00221 ExecFindJunkAttributeInTlist(List *targetlist, const char *attrName)
00222 {
00223     ListCell   *t;
00224 
00225     foreach(t, targetlist)
00226     {
00227         TargetEntry *tle = lfirst(t);
00228 
00229         if (tle->resjunk && tle->resname &&
00230             (strcmp(tle->resname, attrName) == 0))
00231         {
00232             /* We found it ! */
00233             return tle->resno;
00234         }
00235     }
00236 
00237     return InvalidAttrNumber;
00238 }
00239 
00240 /*
00241  * ExecGetJunkAttribute
00242  *
00243  * Given a junk filter's input tuple (slot) and a junk attribute's number
00244  * previously found by ExecFindJunkAttribute, extract & return the value and
00245  * isNull flag of the attribute.
00246  */
00247 Datum
00248 ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
00249                      bool *isNull)
00250 {
00251     Assert(attno > 0);
00252 
00253     return slot_getattr(slot, attno, isNull);
00254 }
00255 
00256 /*
00257  * ExecFilterJunk
00258  *
00259  * Construct and return a slot with all the junk attributes removed.
00260  */
00261 TupleTableSlot *
00262 ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
00263 {
00264     TupleTableSlot *resultSlot;
00265     AttrNumber *cleanMap;
00266     TupleDesc   cleanTupType;
00267     int         cleanLength;
00268     int         i;
00269     Datum      *values;
00270     bool       *isnull;
00271     Datum      *old_values;
00272     bool       *old_isnull;
00273 
00274     /*
00275      * Extract all the values of the old tuple.
00276      */
00277     slot_getallattrs(slot);
00278     old_values = slot->tts_values;
00279     old_isnull = slot->tts_isnull;
00280 
00281     /*
00282      * get info from the junk filter
00283      */
00284     cleanTupType = junkfilter->jf_cleanTupType;
00285     cleanLength = cleanTupType->natts;
00286     cleanMap = junkfilter->jf_cleanMap;
00287     resultSlot = junkfilter->jf_resultSlot;
00288 
00289     /*
00290      * Prepare to build a virtual result tuple.
00291      */
00292     ExecClearTuple(resultSlot);
00293     values = resultSlot->tts_values;
00294     isnull = resultSlot->tts_isnull;
00295 
00296     /*
00297      * Transpose data into proper fields of the new tuple.
00298      */
00299     for (i = 0; i < cleanLength; i++)
00300     {
00301         int         j = cleanMap[i];
00302 
00303         if (j == 0)
00304         {
00305             values[i] = (Datum) 0;
00306             isnull[i] = true;
00307         }
00308         else
00309         {
00310             values[i] = old_values[j - 1];
00311             isnull[i] = old_isnull[j - 1];
00312         }
00313     }
00314 
00315     /*
00316      * And return the virtual tuple.
00317      */
00318     return ExecStoreVirtualTuple(resultSlot);
00319 }