Back-patch nodeMaterial to honor chgParam by recomputing its output.
authorTom Lane <[email protected]>
Fri, 6 Oct 2000 01:28:47 +0000 (01:28 +0000)
committerTom Lane <[email protected]>
Fri, 6 Oct 2000 01:28:47 +0000 (01:28 +0000)
src/backend/executor/nodeMaterial.c

index 4f67892682b6b8d166951563c0762744b6e446f7..bbe4fad4e5079a93e357c74b0f72c45b91caae65 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.30.2.1 2000/09/08 02:11:32 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.30.2.2 2000/10/06 01:28:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  *     calls to ExecMaterial return successive tuples from the temp
  *     relation.
  *
- *     Initial State:
- *
- *     ExecMaterial assumes the temporary relation has been
- *     created and opened by ExecInitMaterial during the prior
- *     InitPlan() phase.
- *
  * ----------------------------------------------------------------
  */
 TupleTableSlot *               /* result tuple from subplan */
@@ -78,25 +72,54 @@ ExecMaterial(Material *node)
 
    if (matstate->mat_Flag == false)
    {
+       TupleDesc   tupType;
+
        /* ----------------
-        *  set all relations to be scanned in the forward direction
-        *  while creating the temporary relation.
+        *  get type information needed for ExecCreatR
         * ----------------
         */
-       estate->es_direction = ForwardScanDirection;
+       tupType = ExecGetScanType(&matstate->csstate);
+
+       /* ----------------
+        *  ExecCreatR wants its second argument to be an object id of
+        *  a relation in the range table or a _NONAME_RELATION_ID
+        *  indicating that the relation is not in the range table.
+        *
+        *  In the second case ExecCreatR creates a temp relation.
+        *  (currently this is the only case we support -cim 10/16/89)
+        * ----------------
+        */
+       /* ----------------
+        *  create the temporary relation
+        * ----------------
+        */
+       tempRelation = ExecCreatR(tupType, _NONAME_RELATION_ID_);
 
        /* ----------------
         *   if we couldn't create the temp relation then
         *   we print a warning and return NULL.
         * ----------------
         */
-       tempRelation = matstate->mat_TempRelation;
        if (tempRelation == NULL)
        {
            elog(DEBUG, "ExecMaterial: temp relation is NULL! aborting...");
            return NULL;
        }
 
+       /* ----------------
+        *  save the relation descriptor in the sortstate
+        * ----------------
+        */
+       matstate->mat_TempRelation = tempRelation;
+       matstate->csstate.css_currentRelation = NULL;
+
+       /* ----------------
+        *  set all relations to be scanned in the forward direction
+        *  while creating the temporary relation.
+        * ----------------
+        */
+       estate->es_direction = ForwardScanDirection;
+
        /* ----------------
         *   retrieve tuples from the subplan and
         *   insert them in the temporary relation
@@ -135,9 +158,6 @@ ExecMaterial(Material *node)
        matstate->csstate.css_currentRelation = currentRelation;
        matstate->csstate.css_currentScanDesc = currentScanDesc;
 
-       ExecAssignScanType(&matstate->csstate,
-                          RelationGetDescr(currentRelation));
-
        /* ----------------
         *  finally set the sorted flag to true
         * ----------------
@@ -178,10 +198,6 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
 {
    MaterialState *matstate;
    Plan       *outerPlan;
-   TupleDesc   tupType;
-   Relation    tempDesc;
-
-   /* int                      len; */
 
    /* ----------------
     *  assign the node's execution state
@@ -225,12 +241,6 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
    outerPlan = outerPlan((Plan *) node);
    ExecInitNode(outerPlan, estate, (Plan *) node);
 
-   /* ----------------
-    *  initialize matstate information
-    * ----------------
-    */
-   matstate->mat_Flag = false;
-
    /* ----------------
     *  initialize tuple type.  no need to initialize projection
     *  info because this node doesn't do projections.
@@ -239,39 +249,6 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
    ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate);
    matstate->csstate.cstate.cs_ProjInfo = NULL;
 
-   /* ----------------
-    *  get type information needed for ExecCreatR
-    * ----------------
-    */
-   tupType = ExecGetScanType(&matstate->csstate);
-
-   /* ----------------
-    *  ExecCreatR wants its second argument to be an object id of
-    *  a relation in the range table or a _NONAME_RELATION_ID
-    *  indicating that the relation is not in the range table.
-    *
-    *  In the second case ExecCreatR creates a temp relation.
-    *  (currently this is the only case we support -cim 10/16/89)
-    * ----------------
-    */
-   /* ----------------
-    *  create the temporary relation
-    * ----------------
-    */
-   tempDesc = ExecCreatR(tupType, _NONAME_RELATION_ID_);
-
-   /* ----------------
-    *  save the relation descriptor in the sortstate
-    * ----------------
-    */
-   matstate->mat_TempRelation = tempDesc;
-   matstate->csstate.css_currentRelation = NULL;
-
-   /* ----------------
-    *  return relation oid of temporary relation in a list
-    *  (someday -- for now we return LispTrue... cim 10/12/89)
-    * ----------------
-    */
    return TRUE;
 }
 
@@ -343,13 +320,39 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
 {
    MaterialState *matstate = node->matstate;
 
+   /*
+    * If we haven't materialized yet, just return. If outerplan' chgParam is
+    * not NULL then it will be re-scanned by ExecProcNode, else - no
+    * reason to re-scan it at all.
+    */
    if (matstate->mat_Flag == false)
        return;
 
-   matstate->csstate.css_currentScanDesc = ExecReScanR(matstate->csstate.css_currentRelation,
-                                  matstate->csstate.css_currentScanDesc,
-                               node->plan.state->es_direction, 0, NULL);
-
+   /*
+    * If subnode is to be rescanned then we forget previous stored results;
+    * we have to re-read the subplan and re-store.
+    *
+    * Otherwise we can just rewind and rescan the stored output.
+    */
+   if (((Plan *) node)->lefttree->chgParam != NULL)
+   {
+       Relation    tempRelation = matstate->mat_TempRelation;
+
+       matstate->csstate.css_currentRelation = NULL;
+       ExecCloseR((Plan *) node);
+       ExecClearTuple(matstate->csstate.css_ScanTupleSlot);
+       if (tempRelation != NULL)
+           heap_drop(tempRelation);
+       matstate->mat_TempRelation = NULL;
+       matstate->mat_Flag = false;
+   }
+   else
+   {
+       matstate->csstate.css_currentScanDesc =
+           ExecReScanR(matstate->csstate.css_currentRelation,
+                       matstate->csstate.css_currentScanDesc,
+                       node->plan.state->es_direction, 0, NULL);
+   }
 }
 
 /* ----------------------------------------------------------------