execFlatten.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:6k
源码类别:

数据库系统

开发平台:

Unix_Linux

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