1 /*-------------------------------------------------------------------------
4 * support for constant nodes needing special code.
6 * Copyright (c) 1994, Regents of the University of California
11 * Example: in constant queries where no relations are scanned,
12 * the planner generates result nodes. Examples of such queries are:
16 * append emp (name = "mike", salary = 15000)
18 * Result nodes are also used to optimise queries
19 * with tautological qualifications like:
21 * retrieve (emp.all) where 2 > 1
23 * In this case, the plan generated is
25 * Result (with 2 > 1 qual)
30 * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.5 1997/09/08 21:43:16 momjian Exp $
32 *-------------------------------------------------------------------------
37 #include "executor/executor.h"
38 #include "executor/nodeResult.h"
40 /* ----------------------------------------------------------------
43 * returns the tuples from the outer plan which satisify the
44 * qualification clause. Since result nodes with right
45 * subtrees are never planned, we ignore the right subtree
46 * entirely (for now).. -cim 10/7/89
48 * The qualification containing only constant clauses are
49 * checked first before any processing is done. It always returns
50 * 'nil' if the constant qualification is not satisfied.
51 * ----------------------------------------------------------------
54 ExecResult(Result *node)
56 ResultState *resstate;
57 TupleTableSlot *outerTupleSlot;
58 TupleTableSlot *resultSlot;
60 ExprContext *econtext;
64 ProjectionInfo *projInfo;
67 * initialize the result node's state
70 resstate = node->resstate;
73 * get the expression context
76 econtext = resstate->cstate.cs_ExprContext;
79 * check tautological qualifications like (2 > 1)
82 qual = node->resconstantqual;
85 qualResult = ExecQual((List *) qual, econtext);
87 * if we failed the constant qual, then there
88 * is no need to continue processing because regardless of
89 * what happens, the constant qual will be false..
92 if (qualResult == false)
96 * our constant qualification succeeded so now we
97 * throw away the qual because we know it will always
101 node->resconstantqual = NULL;
104 if (resstate->cstate.cs_TupFromTlist)
106 ProjectionInfo *projInfo;
108 projInfo = resstate->cstate.cs_ProjInfo;
109 resultSlot = ExecProject(projInfo, &isDone);
115 * retrieve a tuple that satisfy the qual from the outer plan until
118 * if rs_done is 1 then it means that we were asked to return
119 * a constant tuple and we alread did the last time ExecResult()
120 * was called, so now we are through.
123 outerPlan = outerPlan(node);
125 while (!resstate->rs_done)
129 * get next outer tuple if necessary.
132 if (outerPlan != NULL)
134 outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
136 if (TupIsNull(outerTupleSlot))
139 resstate->cstate.cs_OuterTupleSlot = outerTupleSlot;
145 * if we don't have an outer plan, then it's probably
146 * the case that we are doing a retrieve or an append
147 * with a constant target list, so we should only return
148 * the constant tuple once or never if we fail the qual.
151 resstate->rs_done = 1;
155 * get the information to place into the expr context
158 resstate = node->resstate;
160 outerTupleSlot = resstate->cstate.cs_OuterTupleSlot;
163 * fill in the information in the expression context
164 * XXX gross hack. use outer tuple as scan tuple
167 econtext->ecxt_outertuple = outerTupleSlot;
168 econtext->ecxt_scantuple = outerTupleSlot;
171 * form the result tuple and pass it back using ExecProject()
174 projInfo = resstate->cstate.cs_ProjInfo;
175 resultSlot = ExecProject(projInfo, &isDone);
176 resstate->cstate.cs_TupFromTlist = !isDone;
183 /* ----------------------------------------------------------------
186 * Creates the run-time state information for the result node
187 * produced by the planner and initailizes outer relations
189 * ----------------------------------------------------------------
192 ExecInitResult(Result *node, EState *estate, Plan *parent)
194 ResultState *resstate;
197 * assign execution state to node
200 node->plan.state = estate;
203 * create new ResultState for node
206 resstate = makeNode(ResultState);
207 resstate->rs_done = 0;
208 node->resstate = resstate;
211 * Miscellanious initialization
213 * + assign node's base_id
214 * + assign debugging hooks and
215 * + create expression context for node
218 ExecAssignNodeBaseInfo(estate, &resstate->cstate, parent);
219 ExecAssignExprContext(estate, &resstate->cstate);
221 #define RESULT_NSLOTS 1
223 * tuple table initialization
226 ExecInitResultTupleSlot(estate, &resstate->cstate);
229 * then initialize children
232 ExecInitNode(outerPlan(node), estate, (Plan *) node);
235 * we don't use inner plan
237 Assert(innerPlan(node) == NULL);
240 * initialize tuple type and projection info
243 ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate);
244 ExecAssignProjectionInfo((Plan *) node, &resstate->cstate);
247 * set "are we done yet" to false
250 resstate->rs_done = 0;
256 ExecCountSlotsResult(Result *node)
258 return ExecCountSlotsNode(outerPlan(node)) + RESULT_NSLOTS;
261 /* ----------------------------------------------------------------
264 * fees up storage allocated through C routines
265 * ----------------------------------------------------------------
268 ExecEndResult(Result *node)
270 ResultState *resstate;
272 resstate = node->resstate;
275 * Free the projection info
277 * Note: we don't ExecFreeResultType(resstate)
278 * because the rule manager depends on the tupType
279 * returned by ExecMain(). So for now, this
280 * is freed at end-transaction time. -cim 6/2/91
283 ExecFreeProjectionInfo(&resstate->cstate);
289 ExecEndNode(outerPlan(node), (Plan *) node);
292 * clean out the tuple table
295 ExecClearTuple(resstate->cstate.cs_ResultTupleSlot);