88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.30.2.1 2000/09/08 02:11:32 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.30.2.2 2000/10/06 01:28:47 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
3939 *calls to ExecMaterial return successive tuples from the temp
4040 *relation.
4141 *
42- *Initial State:
43- *
44- *ExecMaterial assumes the temporary relation has been
45- *created and opened by ExecInitMaterial during the prior
46- *InitPlan() phase.
47- *
4842 * ----------------------------------------------------------------
4943 */
5044TupleTableSlot * /* result tuple from subplan */
@@ -78,25 +72,54 @@ ExecMaterial(Material *node)
7872
7973if (matstate -> mat_Flag == false)
8074{
75+ TupleDesc tupType ;
76+
8177/* ----------------
82- *set all relations to be scanned in the forward direction
83- *while creating the temporary relation.
78+ *get type information needed for ExecCreatR
8479 * ----------------
8580 */
86- estate -> es_direction = ForwardScanDirection ;
81+ tupType = ExecGetScanType (& matstate -> csstate );
82+
83+ /* ----------------
84+ *ExecCreatR wants its second argument to be an object id of
85+ *a relation in the range table or a _NONAME_RELATION_ID
86+ *indicating that the relation is not in the range table.
87+ *
88+ *In the second case ExecCreatR creates a temp relation.
89+ *(currently this is the only case we support -cim 10/16/89)
90+ * ----------------
91+ */
92+ /* ----------------
93+ *create the temporary relation
94+ * ----------------
95+ */
96+ tempRelation = ExecCreatR (tupType ,_NONAME_RELATION_ID_ );
8797
8898/* ----------------
8999 * if we couldn't create the temp relation then
90100 * we print a warning and return NULL.
91101 * ----------------
92102 */
93- tempRelation = matstate -> mat_TempRelation ;
94103if (tempRelation == NULL )
95104{
96105elog (DEBUG ,"ExecMaterial: temp relation is NULL! aborting..." );
97106return NULL ;
98107}
99108
109+ /* ----------------
110+ *save the relation descriptor in the sortstate
111+ * ----------------
112+ */
113+ matstate -> mat_TempRelation = tempRelation ;
114+ matstate -> csstate .css_currentRelation = NULL ;
115+
116+ /* ----------------
117+ *set all relations to be scanned in the forward direction
118+ *while creating the temporary relation.
119+ * ----------------
120+ */
121+ estate -> es_direction = ForwardScanDirection ;
122+
100123/* ----------------
101124 * retrieve tuples from the subplan and
102125 * insert them in the temporary relation
@@ -135,9 +158,6 @@ ExecMaterial(Material *node)
135158matstate -> csstate .css_currentRelation = currentRelation ;
136159matstate -> csstate .css_currentScanDesc = currentScanDesc ;
137160
138- ExecAssignScanType (& matstate -> csstate ,
139- RelationGetDescr (currentRelation ));
140-
141161/* ----------------
142162 *finally set the sorted flag to true
143163 * ----------------
@@ -178,10 +198,6 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
178198{
179199MaterialState * matstate ;
180200Plan * outerPlan ;
181- TupleDesc tupType ;
182- Relation tempDesc ;
183-
184- /* intlen; */
185201
186202/* ----------------
187203 *assign the node's execution state
@@ -225,12 +241,6 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
225241outerPlan = outerPlan ((Plan * )node );
226242ExecInitNode (outerPlan ,estate , (Plan * )node );
227243
228- /* ----------------
229- *initialize matstate information
230- * ----------------
231- */
232- matstate -> mat_Flag = false;
233-
234244/* ----------------
235245 *initialize tuple type.no need to initialize projection
236246 *info because this node doesn't do projections.
@@ -239,39 +249,6 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
239249ExecAssignScanTypeFromOuterPlan ((Plan * )node ,& matstate -> csstate );
240250matstate -> csstate .cstate .cs_ProjInfo = NULL ;
241251
242- /* ----------------
243- *get type information needed for ExecCreatR
244- * ----------------
245- */
246- tupType = ExecGetScanType (& matstate -> csstate );
247-
248- /* ----------------
249- *ExecCreatR wants its second argument to be an object id of
250- *a relation in the range table or a _NONAME_RELATION_ID
251- *indicating that the relation is not in the range table.
252- *
253- *In the second case ExecCreatR creates a temp relation.
254- *(currently this is the only case we support -cim 10/16/89)
255- * ----------------
256- */
257- /* ----------------
258- *create the temporary relation
259- * ----------------
260- */
261- tempDesc = ExecCreatR (tupType ,_NONAME_RELATION_ID_ );
262-
263- /* ----------------
264- *save the relation descriptor in the sortstate
265- * ----------------
266- */
267- matstate -> mat_TempRelation = tempDesc ;
268- matstate -> csstate .css_currentRelation = NULL ;
269-
270- /* ----------------
271- *return relation oid of temporary relation in a list
272- *(someday -- for now we return LispTrue... cim 10/12/89)
273- * ----------------
274- */
275252return TRUE;
276253}
277254
@@ -343,13 +320,39 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
343320{
344321MaterialState * matstate = node -> matstate ;
345322
323+ /*
324+ * If we haven't materialized yet, just return. If outerplan' chgParam is
325+ * not NULL then it will be re-scanned by ExecProcNode, else - no
326+ * reason to re-scan it at all.
327+ */
346328if (matstate -> mat_Flag == false)
347329return ;
348330
349- matstate -> csstate .css_currentScanDesc = ExecReScanR (matstate -> csstate .css_currentRelation ,
350- matstate -> csstate .css_currentScanDesc ,
351- node -> plan .state -> es_direction ,0 ,NULL );
352-
331+ /*
332+ * If subnode is to be rescanned then we forget previous stored results;
333+ * we have to re-read the subplan and re-store.
334+ *
335+ * Otherwise we can just rewind and rescan the stored output.
336+ */
337+ if (((Plan * )node )-> lefttree -> chgParam != NULL )
338+ {
339+ Relation tempRelation = matstate -> mat_TempRelation ;
340+
341+ matstate -> csstate .css_currentRelation = NULL ;
342+ ExecCloseR ((Plan * )node );
343+ ExecClearTuple (matstate -> csstate .css_ScanTupleSlot );
344+ if (tempRelation != NULL )
345+ heap_drop (tempRelation );
346+ matstate -> mat_TempRelation = NULL ;
347+ matstate -> mat_Flag = false;
348+ }
349+ else
350+ {
351+ matstate -> csstate .css_currentScanDesc =
352+ ExecReScanR (matstate -> csstate .css_currentRelation ,
353+ matstate -> csstate .css_currentScanDesc ,
354+ node -> plan .state -> es_direction ,0 ,NULL );
355+ }
353356}
354357
355358/* ----------------------------------------------------------------