home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / ex_flatten.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-10  |  5.4 KB  |  220 lines

  1. /*
  2.  * $Header: /private/postgres/src/executor/RCS/ex_flatten.c,v 1.7 1992/07/13 10:19:46 hong Exp $
  3.  *
  4.  * This file handles the nodes associated with flattening sets in the
  5.  * target list of queries containing functions returning sets.
  6.  *
  7.  * ExecEvalIter() -
  8.  *   Iterate through the all return tuples/base types from a function one
  9.  *   at time (i.e. one per ExecEvalIter call).  Not really needed for
  10.  *   postquel functions, but for reasons of orthogonality, these nodes
  11.  *   exist above pq functions as well as c functions.
  12.  *
  13.  * ExecEvalFjoin() -
  14.  *   Given N Iter nodes return a vector of all combinations of results
  15.  *   one at a time (i.e. one result vector per ExecEvalFjoin call).  This
  16.  *   node does the actual flattening work.
  17.  */
  18.  
  19. #include "tmp/postgres.h"
  20. #include "nodes/primnodes.h"
  21. #include "nodes/relation.h"
  22. #include "nodes/execnodes.h"
  23. #include "parser/parsetree.h"
  24. #include "executor/flatten.h"
  25.  
  26. Datum
  27. ExecEvalIter(iterNode, econtext, resultIsNull, iterIsDone)
  28.     Iter        iterNode;
  29.     ExprContext         econtext;
  30.     bool        *iterIsDone;
  31.     bool        *resultIsNull;
  32. {
  33.     List expression;
  34.  
  35.     expression = get_iterexpr(iterNode);
  36.  
  37.     /*
  38.      * Really Iter nodes are only needed for C functions, postquel function
  39.      * by their nature return 1 result at a time.  For now we are only worrying
  40.      * about postquel functions, c functions will come later.
  41.      */
  42.     return ExecEvalExpr((Node)expression, econtext, resultIsNull, iterIsDone);
  43. }
  44.  
  45. void
  46. ExecEvalFjoin(tlist, econtext, isNullVect, fj_isDone)
  47.     List        tlist;
  48.     ExprContext         econtext;
  49.     bool        *isNullVect;
  50.     bool        *fj_isDone;
  51. {
  52.     bool     isDone;
  53.     int      curNode;
  54.     List     tlistP;
  55.     Fjoin    fjNode     = (Fjoin)CAR(tlist);
  56.     DatumPtr resVect    = get_fj_results(fjNode);
  57.     BoolPtr  alwaysDone = get_fj_alwaysDone(fjNode);
  58.  
  59.     if (fj_isDone) *fj_isDone = false;
  60.     /*
  61.      * For the next tuple produced by the plan, we need to re-initialize
  62.      * the Fjoin node.
  63.      */
  64.     if (!get_fj_initialized(fjNode))
  65.     {
  66.     /*
  67.      * Initialize all of the Outer nodes
  68.      */
  69.     curNode = 1;
  70.     foreach(tlistP, CDR(tlist))
  71.     {
  72.         List tle = CAR(tlistP);
  73.  
  74.         resVect[curNode] = ExecEvalIter((Iter)tl_expr(tle),
  75.                         econtext,
  76.                         &isNullVect[curNode],
  77.                         &isDone);
  78.         if (isDone)
  79.         isNullVect[curNode] = alwaysDone[curNode] = true;
  80.         else
  81.         alwaysDone[curNode] = false;
  82.  
  83.         curNode++;
  84.     }
  85.  
  86.     /*
  87.      * Initialize the inner node
  88.      */
  89.     resVect[0] = ExecEvalIter((Iter)tl_expr(get_fj_innerNode(fjNode)),
  90.                   econtext,
  91.                   &isNullVect[0],
  92.                   &isDone);
  93.     if (isDone)
  94.         isNullVect[0] = alwaysDone[0] = true;
  95.     else
  96.         alwaysDone[0] = false;
  97.  
  98.     /*
  99.      * Mark the Fjoin as initialized now.
  100.      */
  101.     set_fj_initialized(fjNode, true);
  102.  
  103.     /*
  104.      * If the inner node is always done, then we are done for now
  105.      */
  106.     if (isDone)
  107.         return;
  108.     }
  109.     else
  110.     {
  111.     /*
  112.      * If we're already initialized, all we need to do is get the
  113.      * next inner result and pair it up with the existing outer node
  114.      * result vector.  Watch out for the degenerate case, where the
  115.      * inner node never returns results.
  116.      */
  117.  
  118.     /*
  119.      * Fill in nulls for every function that is always done.
  120.      */
  121.     for (curNode=get_fj_nNodes(fjNode)-1; curNode >= 0; curNode--)
  122.         isNullVect[curNode] = alwaysDone[curNode];
  123.  
  124.     if (alwaysDone[0] == true)
  125.     {
  126.         *fj_isDone = FjoinBumpOuterNodes(tlist,
  127.                          econtext,
  128.                          resVect,
  129.                          isNullVect);
  130.         return;
  131.     }
  132.     else
  133.         resVect[0] = ExecEvalIter((Iter)tl_expr(get_fj_innerNode(fjNode)),
  134.                       econtext,
  135.                       &isNullVect[0],
  136.                       &isDone);
  137.     }
  138.  
  139.     /*
  140.      * if the inner node is done
  141.      */
  142.     if (isDone)
  143.     {
  144.     *fj_isDone = FjoinBumpOuterNodes(tlist,
  145.                      econtext,
  146.                      resVect,
  147.                      isNullVect);
  148.     if (*fj_isDone)
  149.         return;
  150.  
  151.     resVect[0] = ExecEvalIter((Iter)tl_expr(get_fj_innerNode(fjNode)),
  152.                   econtext,
  153.                   &isNullVect[0],
  154.                   &isDone);
  155.  
  156.     }
  157.     return;
  158. }
  159.  
  160. bool
  161. FjoinBumpOuterNodes(tlist, econtext, results, nulls)
  162.     List        tlist;
  163.     ExprContext         econtext;
  164.     DatumPtr        results;
  165.     String        nulls;
  166. {
  167.     bool   funcIsDone = true;
  168.     Fjoin  fjNode     = (Fjoin)CAR(tlist);
  169.     String alwaysDone = get_fj_alwaysDone(fjNode);
  170.     List   outerList  = CDR(tlist);
  171.     List   trailers   = CDR(tlist);
  172.     int    trailNode  = 1;
  173.     int    curNode    = 1;
  174.  
  175.     /*
  176.      * Run through list of functions until we get to one that isn't yet
  177.      * done returning values.  Watch out for funcs that are always done.
  178.      */
  179.     while ((funcIsDone == true) && (outerList != LispNil))
  180.     {
  181.     if (alwaysDone[curNode] == true)
  182.         nulls[curNode] = 'n';
  183.     else
  184.         results[curNode] = ExecEvalIter((Iter)tl_expr(CAR(outerList)),
  185.                         econtext,
  186.                         &nulls[curNode],
  187.                         &funcIsDone);
  188.     curNode++;
  189.     outerList = CDR(outerList);
  190.     }
  191.  
  192.     /*
  193.      * If every function is done, then we are done flattening.
  194.      * Mark the Fjoin node unitialized, it is time to get the
  195.      * next tuple from the plan and redo all of the flattening.
  196.      */
  197.     if (funcIsDone)
  198.     {
  199.     set_fj_initialized(fjNode, false);
  200.     return (true);
  201.     }
  202.  
  203.     /*
  204.      * We found a function that wasn't done.  Now re-run every function
  205.      * before it.  As usual watch out for functions that are always done.
  206.      */
  207.     trailNode = 1;
  208.     while (trailNode != curNode-1)
  209.     {
  210.     if (alwaysDone[trailNode] != true)
  211.         results[trailNode] = ExecEvalIter((Iter)tl_expr(CAR(trailers)),
  212.                         econtext,
  213.                         &nulls[trailNode],
  214.                         &funcIsDone);
  215.     trailNode++;
  216.     trailers = CDR(trailers);
  217.     }
  218.     return false;
  219. }
  220.