home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / ex_junk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  10.8 KB  |  377 lines

  1. /*=========================================================================
  2.  * FILE:
  3.  *    junk.c
  4.  *
  5.  * $Header: /private/postgres/src/executor/RCS/ex_junk.c,v 1.4 1992/08/21 05:00:07 mer Exp $
  6.  *
  7.  * DESCRIPTION:
  8.  *     Junk attribute support stuff....
  9.  *
  10.  *=========================================================================
  11.  */
  12.  
  13. #include "executor/executor.h"
  14.  
  15. extern Node CopyObject();
  16. extern List MakeTLE();
  17.  
  18. /*-------------------------------------------------------------------------
  19.  *     XXX this stuff should be rewritten to take advantage
  20.  *         of ExecProject() and the ProjectionInfo node.
  21.  *         -cim 6/3/91
  22.  * 
  23.  * An attribute of a tuple living inside the executor, can be
  24.  * either a normal attribute or a "junk" attribute. "junk" attributes
  25.  * never make it out of the executor, i.e. they are never printed,
  26.  * returned or stored in disk. Their only purpose in life is to
  27.  * store some information useful only to the executor, mainly the values
  28.  * of some system attributes like "ctid" or rule locks.
  29.  * 
  30.  * The general idea is the following: A target list consists of a list of
  31.  * Resdom nodes & expression pairs. Each Resdom node has an attribute
  32.  * called 'resjunk'. If the value of this attribute is 1 then the
  33.  * corresponding attribute is a "junk" attribute.
  34.  * 
  35.  * When we initialize a plan  we call 'ExecInitJunkFilter' to create
  36.  * and store the appropriate information in the 'es_junkFilter' attribute of
  37.  * EState.
  38.  * 
  39.  * We then execute the plan ignoring the "resjunk" attributes.
  40.  * 
  41.  * Finally, when at the top level we get back a tuple, we can call
  42.  * 'ExecGetJunkAttribute' to retrieve the value of the junk attributes we
  43.  * are interested in, and 'ExecRemoveJunk' to remove all the junk attributes
  44.  * from a tuple. This new "clean" tuple is then printed, replaced, deleted
  45.  * or inserted.
  46.  * 
  47.  *-------------------------------------------------------------------------
  48.  */
  49.  
  50. /*-------------------------------------------------------------------------
  51.  * ExecInitJunkFilter
  52.  *
  53.  * Initialize the Junk filter.
  54.  *-------------------------------------------------------------------------
  55.  */
  56. JunkFilter
  57. ExecInitJunkFilter(targetList)
  58.     List targetList;
  59. {
  60.     JunkFilter         junkfilter;
  61.     List         cleanTargetList;
  62.     int         len, cleanLength;
  63.     TupleDescriptor     tupType, cleanTupType;
  64.     List         t, expr, tle;
  65.     Resdom         resdom, cleanResdom;
  66.     int         resjunk;
  67.     AttributeNumber     resno, cleanResno;
  68.     AttributeNumberPtr     cleanMap;
  69.     Size         size;
  70.  
  71.     /* ---------------------
  72.      * First find the "clean" target list, i.e. all the entries
  73.      * in the original target list which have a zero 'resjunk'
  74.      * NOTE: make copy of the Resdom nodes, because we have
  75.      * to change the 'resno's...
  76.      * ---------------------
  77.      */
  78.     cleanTargetList = LispNil;
  79.     cleanResno = 1;
  80.     
  81.     foreach (t, targetList) {
  82.     if (tl_is_resdom(CAR(t))) {
  83.         resdom = (Resdom) tl_resdom(CAR(t));
  84.         expr = tl_expr(CAR(t));
  85.         resjunk = get_resjunk(resdom);
  86.         if (resjunk == 0) {
  87.         /*
  88.          * make a copy of the resdom node, changing its resno.
  89.          */
  90.         cleanResdom = (Resdom) CopyObject(resdom);
  91.         set_resno(cleanResdom, cleanResno);
  92.         cleanResno ++;
  93.         /*
  94.          * create a new target list entry
  95.          */
  96.         tle = (List) MakeTLE(cleanResdom, expr);
  97.         cleanTargetList = nappend1(cleanTargetList, tle);
  98.         }
  99.     }
  100.     else {
  101.         List fjListP;
  102.         Fjoin cleanFjoin;
  103.         List cleanFjList;
  104.         List fjList = CAR(t);
  105.         Fjoin fjNode = (Fjoin)tl_node(fjList);
  106.  
  107.         cleanFjoin = (Fjoin)CopyObject(fjNode);
  108.         cleanFjList = lispCons(cleanFjoin, LispNil);
  109.  
  110.         resdom = (Resdom) CAR(get_fj_innerNode(fjNode));
  111.         expr =   CADR(get_fj_innerNode(fjNode));
  112.         cleanResdom = (Resdom) CopyObject(resdom);
  113.         set_resno(cleanResdom, cleanResno);
  114.         cleanResno++;
  115.         tle = (List) MakeTLE(cleanResdom, expr);
  116.         set_fj_innerNode(cleanFjoin, tle);
  117.  
  118.         foreach(fjListP, CDR(fjList)) {
  119.         
  120.             resdom = (Resdom) tl_resdom(CAR(fjListP));
  121.             expr = tl_expr(CAR(fjListP));
  122.             cleanResdom = (Resdom) CopyObject(resdom);
  123.         cleanResno++;
  124.             set_resno(cleanResdom, cleanResno);
  125.             /*
  126.               * create a new target list entry
  127.               */
  128.             tle = (List) MakeTLE(cleanResdom, expr);
  129.             cleanFjList = nappend1(cleanFjList, tle);
  130.         }
  131.         nappend1(cleanTargetList, cleanFjList);
  132.     }
  133.     }
  134.  
  135.     /* ---------------------
  136.      * Now calculate the tuple types for the original and the clean tuple
  137.      *
  138.      * XXX ExecTypeFromTL should be used sparingly.  Don't we already
  139.      *       have the tupType corresponding to the targetlist we are passed?
  140.      *     -cim 5/31/91
  141.      * ---------------------
  142.      */
  143.     tupType =        (TupleDescriptor) ExecTypeFromTL(targetList);
  144.     cleanTupType = (TupleDescriptor) ExecTypeFromTL(cleanTargetList);
  145.     
  146.     len =       ExecTargetListLength(targetList);
  147.     cleanLength = ExecTargetListLength(cleanTargetList);
  148.  
  149.     /* ---------------------
  150.      * Now calculate the "map" between the original tuples attributes
  151.      * and the "clean" tuple's attributes.
  152.      *
  153.      * The "map" is an array of "cleanLength" attribute numbers, i.e.
  154.      * one entry for every attribute of the "clean" tuple.
  155.      * The value of this entry is the attribute number of the corresponding
  156.      * attribute of the "original" tuple.
  157.      * ---------------------
  158.      */
  159.     if (cleanLength > 0) {
  160.     size = cleanLength * sizeof(AttributeNumber);
  161.     cleanMap = (AttributeNumberPtr) palloc(size);
  162.     cleanResno = 1;
  163.     foreach (t, targetList) {
  164.         if (tl_is_resdom(CAR(t))) {
  165.         resdom = (Resdom) tl_resdom(CAR(t));
  166.         expr = tl_expr(CAR(t));
  167.         resjunk = get_resjunk(resdom);
  168.         if (resjunk == 0) {
  169.             cleanMap[cleanResno-1] = get_resno(resdom);
  170.             cleanResno ++;
  171.         }
  172.         }
  173.         else {
  174.         List fjListP;
  175.         List fjList = CAR(t);
  176.         Fjoin fjNode = (Fjoin)CAR(fjList);
  177.  
  178.         resdom = (Resdom) CAR(get_fj_innerNode(fjNode));
  179.         cleanMap[cleanResno-1] = get_resno(resdom);
  180.         cleanResno++;
  181.  
  182.         foreach(fjListP, CDR(fjList)) {
  183.             resdom = (Resdom) tl_resdom(CAR(fjListP));
  184.             cleanMap[cleanResno-1] = get_resno(resdom);
  185.             cleanResno++;
  186.         }
  187.         }
  188.     }
  189.     } else {
  190.     cleanMap = NULL;
  191.     }
  192.     
  193.     /* ---------------------
  194.      * Finally create and initialize the JunkFilter.
  195.      * ---------------------
  196.      */
  197.     junkfilter = (JunkFilter) RMakeJunkFilter();
  198.  
  199.     set_jf_targetList(junkfilter, targetList);
  200.     set_jf_length(junkfilter, len);
  201.     set_jf_tupType(junkfilter, tupType);
  202.     set_jf_cleanTargetList(junkfilter, cleanTargetList);
  203.     set_jf_cleanLength(junkfilter, cleanLength);
  204.     set_jf_cleanTupType(junkfilter, cleanTupType);
  205.     set_jf_cleanMap(junkfilter, cleanMap);
  206.  
  207.     return(junkfilter);
  208.     
  209. }
  210.  
  211. /*-------------------------------------------------------------------------
  212.  * ExecGetJunkAttribute
  213.  *
  214.  * Given a tuple (slot), the junk filter and a junk attribute's name,
  215.  * extract & return the value of this attribute.
  216.  *
  217.  * It returns false iff no junk attribute with such name was found.
  218.  *
  219.  * NOTE: isNull might be NULL !
  220.  *-------------------------------------------------------------------------
  221.  */
  222. bool
  223. ExecGetJunkAttribute(junkfilter, slot, attrName, value, isNull)
  224.     JunkFilter         junkfilter;
  225.     TupleTableSlot     slot;
  226.     Name         attrName;
  227.     Datum         *value;
  228.     Boolean         *isNull;
  229. {
  230.     List         targetList;
  231.     List         t;
  232.     Resdom         resdom;
  233.     AttributeNumber     resno;
  234.     Name         resname;
  235.     int         resjunk;
  236.     TupleDescriptor     tupType;
  237.     HeapTuple         tuple;
  238.  
  239.     /* ---------------------
  240.      * first look in the junkfilter's target list for
  241.      * an attribute with the given name
  242.      * ---------------------
  243.      */
  244.     resno =      InvalidAttributeNumber;
  245.     targetList = get_jf_targetList(junkfilter);
  246.     
  247.     foreach (t, targetList) {
  248.     resdom = (Resdom) tl_resdom(CAR(t));
  249.     resname = get_resname(resdom);
  250.     resjunk = get_resjunk(resdom);
  251.     if (resjunk != 0 && NameIsEqual(resname, attrName)) {
  252.         /* We found it ! */
  253.         resno = get_resno(resdom);
  254.         break;
  255.     }
  256.     }
  257.  
  258.     if (resno == InvalidAttributeNumber) {
  259.     /* Ooops! We couldn't find this attribute... */
  260.     return(false);
  261.     }
  262.  
  263.     /* ---------------------
  264.      * Now extract the attribute value from the tuple.
  265.      * ---------------------
  266.      */
  267.     tuple =     (HeapTuple) ExecFetchTuple((Pointer) slot);
  268.     tupType =     (TupleDescriptor) get_jf_tupType(junkfilter);
  269.     
  270.     *value =     (Datum)
  271.     heap_getattr(tuple, InvalidBuffer, resno, tupType, isNull);
  272.  
  273.     return true;
  274. }
  275.  
  276. /*-------------------------------------------------------------------------
  277.  * ExecRemoveJunk
  278.  *
  279.  * Construct and return a tuple with all the junk attributes removed.
  280.  *-------------------------------------------------------------------------
  281.  */
  282. HeapTuple
  283. ExecRemoveJunk(junkfilter, slot)
  284.     JunkFilter junkfilter;
  285.     TupleTableSlot slot;
  286. {
  287.     HeapTuple         tuple;
  288.     HeapTuple         cleanTuple;
  289.     AttributeNumberPtr     cleanMap;
  290.     TupleDescriptor     cleanTupType;
  291.     TupleDescriptor    tupType;
  292.     int         cleanLength;
  293.     Boolean         isNull;
  294.     int         i;
  295.     Size         size;
  296.     Datum         *values;
  297.     char        *nulls;
  298.     Datum        values_array[64];
  299.     char        nulls_array[64];
  300.  
  301.     /* ----------------
  302.      *    get info from the slot and the junk filter
  303.      * ----------------
  304.      */
  305.     tuple = (HeapTuple) ExecFetchTuple((Pointer) slot);
  306.     
  307.     tupType =         (TupleDescriptor) get_jf_tupType(junkfilter);
  308.     cleanTupType =     (TupleDescriptor) get_jf_cleanTupType(junkfilter);
  309.     cleanLength =     get_jf_cleanLength(junkfilter);
  310.     cleanMap =         get_jf_cleanMap(junkfilter);
  311.  
  312.     /* ---------------------
  313.      *  Handle the trivial case first.
  314.      * ---------------------
  315.      */
  316.     if (cleanLength == 0)
  317.     return (HeapTuple) NULL;
  318.  
  319.     /* ---------------------
  320.      * Create the arrays that will hold the attribute values
  321.      * and the null information for the new "clean" tuple.
  322.      *
  323.      * Note: we use memory on the stack to optimize things when
  324.      *       we are dealing with a small number of tuples.
  325.      *         for large tuples we just use palloc.
  326.      * ---------------------
  327.      */
  328.     if (cleanLength > 64) {
  329.     size =      cleanLength * sizeof(Datum);
  330.     values = (Datum *) palloc(size);
  331.     
  332.     size =      cleanLength * sizeof(char);
  333.     nulls =  (char *) palloc(size);
  334.     } else {
  335.     values = values_array;
  336.     nulls =  nulls_array;
  337.     }
  338.     
  339.     /* ---------------------
  340.      * Exctract one by one all the values of the "clean" tuple.
  341.      * ---------------------
  342.      */
  343.     for (i=0; i<cleanLength; i++) {
  344.     Datum d = (Datum)
  345.         heap_getattr(tuple, InvalidBuffer, cleanMap[i], tupType, &isNull);
  346.     
  347.     values[i] = d;
  348.     
  349.     if (isNull)
  350.         nulls[i] = 'n';
  351.     else
  352.         nulls[i] = ' ';
  353.     }
  354.  
  355.     /* ---------------------
  356.      * Now form the new tuple.
  357.      * ---------------------
  358.      */
  359.     cleanTuple = heap_formtuple(cleanLength,
  360.                 cleanTupType,
  361.                 values,
  362.                 nulls);
  363.     
  364.     /* ---------------------
  365.      * We are done.  Free any space allocated for 'values' and 'nulls'
  366.      * and return the new tuple.
  367.      * ---------------------
  368.      */
  369.     if (cleanLength > 64) {
  370.     pfree(values);
  371.     pfree(nulls);
  372.     }
  373.     
  374.     return(cleanTuple);
  375. }
  376.  
  377.