From a9998cf54fe3e4277ef7431213179d1b811132a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=80=E6=8C=83?= <yizhi.fzh@alibaba-inc.com>
Date: Fri, 24 Apr 2020 10:48:24 +0800
Subject: [PATCH v1] Add a Material Path for subplan and reused the previous
 result if the inputed params is not changed. PoC only

---
 src/backend/executor/nodeMaterial.c    | 10 +++++++++-
 src/backend/executor/nodeSubplan.c     |  2 +-
 src/backend/optimizer/plan/subselect.c |  4 ++++
 src/backend/optimizer/util/pathnode.c  |  2 +-
 src/backend/utils/sort/tuplestore.c    |  2 +-
 5 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index dd077f4323..67066686b8 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -59,7 +59,7 @@ ExecMaterial(PlanState *pstate)
 	/*
 	 * If first time through, and we need a tuplestore, initialize it.
 	 */
-	if (tuplestorestate == NULL && node->eflags != 0)
+	if (tuplestorestate == NULL)
 	{
 		tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
 		tuplestore_set_eflags(tuplestorestate, node->eflags);
@@ -321,6 +321,14 @@ ExecReScanMaterial(MaterialState *node)
 
 	ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
 
+	/* Param is not changed, and all the underlying rows is fetched,
+	 * We reuses current data */
+	if (outerPlan->chgParam == NULL && node->eof_underlying)
+	{
+		tuplestore_rescan(node->tuplestorestate);
+		return;
+	}
+
 	if (node->eflags != 0)
 	{
 		/*
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 298b7757f5..35b9a3b2ce 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -288,7 +288,7 @@ ExecScanSubPlan(SubPlanState *node,
 		prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
 											   econtext,
 											   &(prm->isnull));
-		planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
+		// planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
 	}
 
 	/*
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index b02fcb9bfe..0b00de175e 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -23,6 +23,7 @@
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
+#include "nodes/bitmapset.h"
 #include "optimizer/clauses.h"
 #include "optimizer/cost.h"
 #include "optimizer/optimizer.h"
@@ -232,6 +233,9 @@ make_subplan(PlannerInfo *root, Query *orig_subquery,
 	final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
 	best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
 
+	if (linitial_node(RangeTblEntry, root->parse->rtable)->relid == 25634)
+		best_path = (Path *) create_material_path(final_rel, best_path);
+
 	plan = create_plan(subroot, best_path);
 
 	/* And convert to SubPlan or InitPlan format. */
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index e991385059..8d4946c45c 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -1496,7 +1496,7 @@ create_material_path(RelOptInfo *rel, Path *subpath)
 {
 	MaterialPath *pathnode = makeNode(MaterialPath);
 
-	Assert(subpath->parent == rel);
+	// Assert(subpath->parent == rel);
 
 	pathnode->path.pathtype = T_Material;
 	pathnode->path.parent = rel;
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index ebb1da0746..df00b15aee 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -1234,7 +1234,7 @@ tuplestore_rescan(Tuplestorestate *state)
 {
 	TSReadPointer *readptr = &state->readptrs[state->activeptr];
 
-	Assert(readptr->eflags & EXEC_FLAG_REWIND);
+	// Assert(readptr->eflags & EXEC_FLAG_REWIND);
 	Assert(!state->truncated);
 
 	switch (state->status)
-- 
2.21.0

