summaryrefslogtreecommitdiff
path: root/src/backend/executor/execFlatten.c
diff options
context:
space:
mode:
authorTom Lane2002-05-12 23:43:04 +0000
committerTom Lane2002-05-12 23:43:04 +0000
commit3389a110d40a505951e7c7babdfb8681173bb2ca (patch)
tree438acebac5cfd161cf920bcda6ad168affcb96a7 /src/backend/executor/execFlatten.c
parentf9e4f611a18f64fd9106a72ec9af9e2220075780 (diff)
Get rid of long-since-vestigial Iter node type, in favor of adding a
returns-set boolean field in Func and Oper nodes. This allows cleaner, more reliable tests for expressions returning sets in the planner and parser. For example, a WHERE clause returning a set is now detected and complained of in the parser, not only at runtime.
Diffstat (limited to 'src/backend/executor/execFlatten.c')
-rw-r--r--src/backend/executor/execFlatten.c243
1 files changed, 0 insertions, 243 deletions
diff --git a/src/backend/executor/execFlatten.c b/src/backend/executor/execFlatten.c
deleted file mode 100644
index ecbe7b5d189..00000000000
--- a/src/backend/executor/execFlatten.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * execFlatten.c
- * This file handles the nodes associated with flattening sets in the
- * target list of queries containing functions returning sets.
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/Attic/execFlatten.c,v 1.16 2001/10/28 06:25:43 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-/*
- * ExecEvalIter() -
- * Iterate through the all return tuples/base types from a function one
- * at time (i.e. one per ExecEvalIter call). Not really needed for
- * postquel functions, but for reasons of orthogonality, these nodes
- * exist above pq functions as well as c functions.
- *
- * ExecEvalFjoin() -
- * Given N Iter nodes return a vector of all combinations of results
- * one at a time (i.e. one result vector per ExecEvalFjoin call). This
- * node does the actual flattening work.
- */
-#include "postgres.h"
-#include "executor/execFlatten.h"
-#include "executor/executor.h"
-
-#ifdef SETS_FIXED
-static bool FjoinBumpOuterNodes(TargetEntry *tlist, ExprContext *econtext,
- DatumPtr results, char *nulls);
-#endif
-
-
-Datum
-ExecEvalIter(Iter *iterNode,
- ExprContext *econtext,
- bool *isNull,
- ExprDoneCond *isDone)
-{
- Node *expression;
-
- expression = iterNode->iterexpr;
-
- /*
- * Really Iter nodes are only needed for C functions, postquel
- * function by their nature return 1 result at a time. For now we are
- * only worrying about postquel functions, c functions will come
- * later.
- */
- return ExecEvalExpr(expression, econtext, isNull, isDone);
-}
-
-void
-ExecEvalFjoin(TargetEntry *tlist,
- ExprContext *econtext,
- bool *isNullVect,
- ExprDoneCond *fj_isDone)
-{
-
-#ifdef SETS_FIXED
- bool isDone;
- int curNode;
- List *tlistP;
-
- Fjoin *fjNode = tlist->fjoin;
- DatumPtr resVect = fjNode->fj_results;
- BoolPtr alwaysDone = fjNode->fj_alwaysDone;
-
- if (fj_isDone)
- *fj_isDone = ExprMultipleResult;
-
- /*
- * For the next tuple produced by the plan, we need to re-initialize
- * the Fjoin node.
- */
- if (!fjNode->fj_initialized)
- {
- /*
- * Initialize all of the Outer nodes
- */
- curNode = 1;
- foreach(tlistP, lnext(tlist))
- {
- TargetEntry *tle = lfirst(tlistP);
-
- resVect[curNode] = ExecEvalIter((Iter *) tle->expr,
- econtext,
- &isNullVect[curNode],
- &isDone);
- if (isDone)
- isNullVect[curNode] = alwaysDone[curNode] = true;
- else
- alwaysDone[curNode] = false;
-
- curNode++;
- }
-
- /*
- * Initialize the inner node
- */
- resVect[0] = ExecEvalIter((Iter *) fjNode->fj_innerNode->expr,
- econtext,
- &isNullVect[0],
- &isDone);
- if (isDone)
- isNullVect[0] = alwaysDone[0] = true;
- else
- alwaysDone[0] = false;
-
- /*
- * Mark the Fjoin as initialized now.
- */
- fjNode->fj_initialized = TRUE;
-
- /*
- * If the inner node is always done, then we are done for now
- */
- if (isDone)
- return;
- }
- else
- {
- /*
- * If we're already initialized, all we need to do is get the next
- * inner result and pair it up with the existing outer node result
- * vector. Watch out for the degenerate case, where the inner
- * node never returns results.
- */
-
- /*
- * Fill in nulls for every function that is always done.
- */
- for (curNode = fjNode->fj_nNodes - 1; curNode >= 0; curNode--)
- isNullVect[curNode] = alwaysDone[curNode];
-
- if (alwaysDone[0] == true)
- {
- *fj_isDone = FjoinBumpOuterNodes(tlist,
- econtext,
- resVect,
- isNullVect);
- return;
- }
- else
- resVect[0] = ExecEvalIter((Iter *) fjNode->fj_innerNode->expr,
- econtext,
- &isNullVect[0],
- &isDone);
- }
-
- /*
- * if the inner node is done
- */
- if (isDone)
- {
- *fj_isDone = FjoinBumpOuterNodes(tlist,
- econtext,
- resVect,
- isNullVect);
- if (*fj_isDone)
- return;
-
- resVect[0] = ExecEvalIter((Iter *) fjNode->fj_innerNode->expr,
- econtext,
- &isNullVect[0],
- &isDone);
-
- }
-#endif
- return;
-}
-
-#ifdef SETS_FIXED
-static bool
-FjoinBumpOuterNodes(TargetEntry *tlist,
- ExprContext *econtext,
- DatumPtr results,
- char *nulls)
-{
- bool funcIsDone = true;
- Fjoin *fjNode = tlist->fjoin;
- char *alwaysDone = fjNode->fj_alwaysDone;
- List *outerList = lnext(tlist);
- List *trailers = lnext(tlist);
- int trailNode = 1;
- int curNode = 1;
-
- /*
- * Run through list of functions until we get to one that isn't yet
- * done returning values. Watch out for funcs that are always done.
- */
- while ((funcIsDone == true) && (outerList != NIL))
- {
- TargetEntry *tle = lfirst(outerList);
-
- if (alwaysDone[curNode] == true)
- nulls[curNode] = 'n';
- else
- results[curNode] = ExecEvalIter((Iter) tle->expr,
- econtext,
- &nulls[curNode],
- &funcIsDone);
- curNode++;
- outerList = lnext(outerList);
- }
-
- /*
- * If every function is done, then we are done flattening. Mark the
- * Fjoin node uninitialized, it is time to get the next tuple from the
- * plan and redo all of the flattening.
- */
- if (funcIsDone)
- {
- set_fj_initialized(fjNode, false);
- return true;
- }
-
- /*
- * We found a function that wasn't done. Now re-run every function
- * before it. As usual watch out for functions that are always done.
- */
- trailNode = 1;
- while (trailNode != curNode - 1)
- {
- TargetEntry *tle = lfirst(trailers);
-
- if (alwaysDone[trailNode] != true)
- results[trailNode] = ExecEvalIter((Iter) tle->expr,
- econtext,
- &nulls[trailNode],
- &funcIsDone);
- trailNode++;
- trailers = lnext(trailers);
- }
- return false;
-}
-
-#endif