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

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    unique.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    Routines to handle unique'ing of queries where appropriate
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *         ExecUnique    - generate a unique'd temporary relation
  10.  *         ExecInitUnique    - initialize node and subnodes..
  11.  *         ExecEndUnique    - shutdown node and subnodes
  12.  *
  13.  *   NOTES
  14.  *    Assumes tuples returned from subplan arrive in
  15.  *    sorted order.
  16.  *
  17.  *   IDENTIFICATION
  18.  *    $Header: /private/postgres/src/executor/RCS/n_unique.c,v 1.6 1992/08/21 08:02:07 mer Exp $
  19.  * ----------------------------------------------------------------
  20.  */
  21.  
  22. #include "executor/executor.h"
  23. #include "planner/clauses.h"
  24.  
  25.  RcsId("$Header: /private/postgres/src/executor/RCS/n_unique.c,v 1.6 1992/08/21 08:02:07 mer Exp $");
  26.  
  27.  
  28. /* ----------------------------------------------------------------
  29.  *       ExecIdenticalTuples
  30.  *
  31.  *    This is a hack function used by ExecUnique to see if
  32.  *    two tuples are identical.  This should be provided
  33.  *    by the heap tuple code but isn't.  The real problem
  34.  *    is that we assume we can byte compare tuples to determine
  35.  *    if they are "equal".  In fact, if we have user defined
  36.  *    types there may be problems because it's possible that
  37.  *    an ADT may have multiple representations with the
  38.  *    same ADT value. -cim
  39.  * ----------------------------------------------------------------
  40.  */
  41. /**** xxref:
  42.  *           ExecUnique
  43.  ****/
  44. bool    /* true if tuples are identical, false otherwise */
  45. ExecIdenticalTuples(t1, t2)
  46.     List  t1;
  47.     List  t2;
  48. {
  49.     HeapTuple     h1;
  50.     HeapTuple     h2;
  51.     char     *d1;
  52.     char     *d2;
  53.     int     len;
  54.     
  55.     h1 = (HeapTuple) ExecFetchTuple((Pointer) t1);
  56.     h2 = (HeapTuple) ExecFetchTuple((Pointer) t2);
  57.     
  58.     /* ----------------
  59.      *    if tuples aren't the same length then they are 
  60.      *  obviously different (one may have null attributes).
  61.      * ----------------
  62.      */
  63.     if (h1->t_len != h2->t_len)
  64.     return false;
  65.     
  66.     /* ----------------
  67.      *  if the tuples have different header offsets then
  68.      *  they are different.  This will prevent us from returning
  69.      *  true when comparing tuples of one attribute where one of
  70.      *  two we're looking at is null (t_len - t_hoff == 0).
  71.      *  THE t_len FIELDS CAN BE THE SAME IN THIS CASE!!
  72.      * ----------------
  73.      */
  74.     if (h1->t_hoff != h2->t_hoff)
  75.     return false;
  76.  
  77.     /* ----------------
  78.      *    ok, now get the pointers to the data and the
  79.      *  size of the attribute portion of the tuple.
  80.      * ----------------
  81.      */
  82.     d1 = (char *) GETSTRUCT(h1);
  83.     d2 = (char *) GETSTRUCT(h2);
  84.     len = (int) h1->t_len - (int) h1->t_hoff;
  85.     
  86.     /* ----------------
  87.      *    byte compare the data areas and return the result.
  88.      * ----------------
  89.      */
  90.     if (bcmp(d1, d2, len) != 0)
  91.     return false;
  92.     
  93.     return true;
  94. }
  95.  
  96. /* ----------------------------------------------------------------
  97.  *       ExecUnique
  98.  *
  99.  *    This is a very simple node which filters out duplicate
  100.  *    tuples from a stream of sorted tuples from a subplan.
  101.  *
  102.  *    XXX see comments below regarding freeing tuples.
  103.  * ----------------------------------------------------------------
  104.  */
  105. /**** xxref:
  106.  *           ExecProcNode
  107.  ****/
  108. TupleTableSlot         /* return: a tuple or NULL */
  109. ExecUnique(node)
  110.     Unique node;
  111. {
  112.     UniqueState        uniquestate;
  113.     TupleTableSlot    resultTupleSlot;
  114.     TupleTableSlot    slot;
  115.     Plan           outerPlan;
  116.     bool        shouldFree;
  117.     
  118.     /* ----------------
  119.      *    get information from the node
  120.      * ----------------
  121.      */
  122.     uniquestate =       get_uniquestate(node);
  123.     outerPlan =         get_outerPlan((Plan) node);
  124.     resultTupleSlot =   get_cs_ResultTupleSlot((CommonState) uniquestate);
  125.     
  126.     /* ----------------
  127.      *    now loop, returning only non-duplicate tuples.
  128.      *  We assume that the tuples arrive in sorted order
  129.      *  so we can detect duplicates easily.
  130.      * ----------------
  131.      */
  132.     for (;;) {
  133.     /* ----------------
  134.      *   fetch a tuple from the outer subplan
  135.      * ----------------
  136.      */
  137.     slot = ExecProcNode(outerPlan);
  138.     if (TupIsNull((Pointer) slot))
  139.         return NULL;
  140.     
  141.     /* ----------------
  142.      *   we use the result tuple slot to hold our saved tuples.
  143.      *   if we haven't a saved tuple to compare our new tuple with,
  144.      *   then we exit the loop. This new tuple as the saved tuple
  145.      *   the next time we get here.  
  146.      * ----------------
  147.      */
  148.     if (TupIsNull((Pointer) resultTupleSlot))
  149.         break;
  150.     
  151.     /* ----------------
  152.      *   now test if the new tuple and the previous
  153.      *   tuple match.  If so then we loop back and fetch
  154.      *   another new tuple from the subplan.
  155.      * ----------------
  156.      */
  157.     if (! ExecIdenticalTuples((List) slot, (List) resultTupleSlot))
  158.         break;
  159.     }
  160.     
  161.     /* ----------------
  162.      *    we have a new tuple different from the previous saved tuple
  163.      *  so we save it in the saved tuple slot.  We copy the tuple
  164.      *  so we don't increment the buffer ref count.
  165.      * ----------------
  166.      */
  167.     ExecStoreTuple((Pointer)heap_copysimple(ExecFetchTuple((Pointer) slot)),
  168.            (Pointer) resultTupleSlot,
  169.            ExecSlotBuffer((Pointer) slot),
  170.            true);
  171.     
  172.     return
  173.     slot;
  174. }
  175.  
  176. /* ----------------------------------------------------------------
  177.  *       ExecInitUnique
  178.  *
  179.  *    This initializes the unique node state structures and
  180.  *    the node's subplan.
  181.  * ----------------------------------------------------------------
  182.  */
  183. /**** xxref:
  184.  *           ExecInitNode
  185.  ****/
  186. List    /* return: initialization status */
  187. ExecInitUnique(node, estate, parent)
  188.     Unique     node;
  189.     EState     estate;
  190.     Plan    parent;
  191. {
  192.     UniqueState        uniquestate;
  193.     Plan           outerPlan;
  194.     
  195.     /* ----------------
  196.      *    assign execution state to node
  197.      * ----------------
  198.      */
  199.     set_state((Plan) node,  (EStatePtr)estate);
  200.     
  201.     /* ----------------
  202.      *    create new UniqueState for node
  203.      * ----------------
  204.      */
  205.     uniquestate = MakeUniqueState(0);
  206.     set_uniquestate(node, uniquestate);
  207.     
  208.     /* ----------------
  209.      *  Miscellanious initialization
  210.      *
  211.      *         +    assign node's base_id
  212.      *       +    assign debugging hooks and
  213.      *
  214.      *  Unique nodes have no ExprContext initialization because
  215.      *  they never call ExecQual or ExecTargetList.
  216.      * ----------------
  217.      */
  218.     ExecAssignNodeBaseInfo(estate, (BaseNode) uniquestate, parent);
  219.     ExecAssignDebugHooks((Plan) node, (BaseNode) uniquestate);
  220.  
  221. #define UNIQUE_NSLOTS 1
  222.     /* ------------
  223.      * Tuple table initialization
  224.      * ------------
  225.      */
  226.     ExecInitResultTupleSlot(estate, (CommonState) uniquestate);
  227.     
  228.     /* ----------------
  229.      *    then initialize outer plan
  230.      * ----------------
  231.      */
  232.     outerPlan = get_outerPlan((Plan) node);
  233.     ExecInitNode(outerPlan, estate, (Plan) node);
  234.     
  235.     /* ----------------
  236.      *    unique nodes do no projections, so initialize
  237.      *  projection info for this node appropriately
  238.      * ----------------
  239.      */
  240.     ExecAssignResultTypeFromOuterPlan((Plan) node, (CommonState) uniquestate);
  241.     set_cs_ProjInfo((CommonState) uniquestate, NULL);
  242.        
  243.     /* ----------------
  244.      *    all done.
  245.      * ----------------
  246.      */
  247.     return
  248.     LispTrue;
  249. }
  250.  
  251. int
  252. ExecCountSlotsUnique(node)
  253.     Plan node;
  254. {
  255.     return ExecCountSlotsNode(get_outerPlan(node)) +
  256.        ExecCountSlotsNode(get_innerPlan(node)) +
  257.        UNIQUE_NSLOTS;
  258. }
  259.  
  260. /* ----------------------------------------------------------------
  261.  *       ExecEndUnique
  262.  *
  263.  *    This shuts down the subplan and frees resources allocated
  264.  *    to this node.
  265.  * ----------------------------------------------------------------
  266.  */
  267. /**** xxref:
  268.  *           ExecEndNode
  269.  ****/
  270. void
  271. ExecEndUnique(node)
  272.     Unique node;
  273. {
  274.     UniqueState        uniquestate;
  275.     
  276.     uniquestate = get_uniquestate(node);
  277.     ExecEndNode((Plan) get_outerPlan((Plan) node));
  278.     ExecClearTuple((Pointer)
  279.            get_cs_ResultTupleSlot((CommonState) uniquestate));
  280.