From b32c890caf6625983ddcd17cafd8b6b445a1d6c5 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@pgaddict.com>
Date: Tue, 14 Jul 2015 23:33:29 +0200
Subject: [PATCH 19/24] Some stub executor code

This provides a new file, nodeColumStoreMaterial, implementing the
ColumnStoreMaterialize node.

- dummy implementation of the executor methods (doing nothing)

- we might probably avoid using the term 'Materialize' as that means
  something different in PostgreSQL (stuff the tuples into tuple store)
---
 src/backend/executor/Makefile                  |   6 +-
 src/backend/executor/execAmi.c                 |  15 +++
 src/backend/executor/execProcnode.c            |  14 +-
 src/backend/executor/nodeColumnStoreMaterial.c | 179 +++++++++++++++++++++++++
 src/backend/nodes/outfuncs.c                   |  13 ++
 src/backend/optimizer/plan/subselect.c         |   1 +
 src/include/executor/nodeColumnStoreMaterial.h |  26 ++++
 7 files changed, 249 insertions(+), 5 deletions(-)
 create mode 100644 src/backend/executor/nodeColumnStoreMaterial.c
 create mode 100644 src/include/executor/nodeColumnStoreMaterial.h

diff --git a/src/backend/executor/Makefile b/src/backend/executor/Makefile
index 08cba6f..703a9c8 100644
--- a/src/backend/executor/Makefile
+++ b/src/backend/executor/Makefile
@@ -16,9 +16,9 @@ OBJS = execAmi.o execCurrent.o execGrouping.o execIndexing.o execJunk.o \
        execMain.o execProcnode.o execQual.o execScan.o execTuples.o \
        execUtils.o functions.o instrument.o nodeAppend.o nodeAgg.o \
        nodeBitmapAnd.o nodeBitmapOr.o \
-       nodeBitmapHeapscan.o nodeBitmapIndexscan.o nodeCustom.o nodeHash.o \
-       nodeHashjoin.o nodeIndexscan.o nodeIndexonlyscan.o \
-       nodeLimit.o nodeLockRows.o \
+       nodeBitmapHeapscan.o nodeBitmapIndexscan.o nodeColumnStoreMaterial.o \
+       nodeCustom.o nodeHash.o nodeHashjoin.o \
+       nodeIndexscan.o nodeIndexonlyscan.o nodeLimit.o nodeLockRows.o \
        nodeMaterial.o nodeMergeAppend.o nodeMergejoin.o nodeModifyTable.o \
        nodeNestloop.o nodeFunctionscan.o nodeRecursiveunion.o nodeResult.o \
        nodeSamplescan.o nodeSeqscan.o nodeSetOp.o nodeSort.o nodeUnique.o \
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c
index 93e1e9a..1ca905b 100644
--- a/src/backend/executor/execAmi.c
+++ b/src/backend/executor/execAmi.c
@@ -20,6 +20,7 @@
 #include "executor/nodeBitmapHeapscan.h"
 #include "executor/nodeBitmapIndexscan.h"
 #include "executor/nodeBitmapOr.h"
+#include "executor/nodeColumnStoreMaterial.h"
 #include "executor/nodeCtescan.h"
 #include "executor/nodeCustom.h"
 #include "executor/nodeForeignscan.h"
@@ -224,6 +225,10 @@ ExecReScan(PlanState *node)
 			ExecReScanMaterial((MaterialState *) node);
 			break;
 
+		case T_ColumnStoreMaterialState:
+			ExecReScanColumnStoreMaterial((ColumnStoreMaterialState *) node);
+			break;
+
 		case T_SortState:
 			ExecReScanSort((SortState *) node);
 			break;
@@ -306,6 +311,10 @@ ExecMarkPos(PlanState *node)
 			ExecMaterialMarkPos((MaterialState *) node);
 			break;
 
+		case T_ColumnStoreMaterialState:
+			ExecColumnStoreMaterialMarkPos((ColumnStoreMaterialState *) node);
+			break;
+
 		case T_SortState:
 			ExecSortMarkPos((SortState *) node);
 			break;
@@ -355,6 +364,10 @@ ExecRestrPos(PlanState *node)
 			ExecMaterialRestrPos((MaterialState *) node);
 			break;
 
+		case T_ColumnStoreMaterialState:
+			ExecColumnStoreMaterialRestrPos((ColumnStoreMaterialState *) node);
+			break;
+
 		case T_SortState:
 			ExecSortRestrPos((SortState *) node);
 			break;
@@ -389,6 +402,7 @@ ExecSupportsMarkRestore(Path *pathnode)
 		case T_IndexScan:
 		case T_IndexOnlyScan:
 		case T_Material:
+		case T_ColumnStoreMaterial:
 		case T_Sort:
 			return true;
 
@@ -490,6 +504,7 @@ ExecSupportsBackwardScan(Plan *node)
 			return false;
 
 		case T_Material:
+		case T_ColumnStoreMaterial:
 		case T_Sort:
 			/* these don't evaluate tlist */
 			return true;
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index 5d68b3e..5931049 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -84,6 +84,7 @@
 #include "executor/nodeBitmapHeapscan.h"
 #include "executor/nodeBitmapIndexscan.h"
 #include "executor/nodeBitmapOr.h"
+#include "executor/nodeColumnStoreMaterial.h"
 #include "executor/nodeCtescan.h"
 #include "executor/nodeCustom.h"
 #include "executor/nodeForeignscan.h"
@@ -282,8 +283,9 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
 													estate, eflags);
 			break;
 
-		case T_ColumnStoreMaterial:	/* FIXME this is wrong (no exec implementation yet!!!) */
-			result = (PlanState *) ExecInitMaterial((Material *) node,
+		case T_ColumnStoreMaterial:
+			result = (PlanState *) ExecInitColumnStoreMaterial(
+													(ColumnStoreMaterial *) node,
 													estate, eflags);
 			break;
 
@@ -489,6 +491,10 @@ ExecProcNode(PlanState *node)
 			result = ExecMaterial((MaterialState *) node);
 			break;
 
+		case T_ColumnStoreMaterialState:
+			result = ExecColumnStoreMaterial((ColumnStoreMaterialState *) node);
+			break;
+
 		case T_SortState:
 			result = ExecSort((SortState *) node);
 			break;
@@ -733,6 +739,10 @@ ExecEndNode(PlanState *node)
 			ExecEndMaterial((MaterialState *) node);
 			break;
 
+		case T_ColumnStoreMaterialState:
+			ExecEndColumnStoreMaterial((ColumnStoreMaterialState *) node);
+			break;
+
 		case T_SortState:
 			ExecEndSort((SortState *) node);
 			break;
diff --git a/src/backend/executor/nodeColumnStoreMaterial.c b/src/backend/executor/nodeColumnStoreMaterial.c
new file mode 100644
index 0000000..0ee1444
--- /dev/null
+++ b/src/backend/executor/nodeColumnStoreMaterial.c
@@ -0,0 +1,179 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeColumnStoreMaterial.c
+ *	  Routines to handle column store materialization nodes.
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/executor/nodeColumnStoreMaterial.c
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ * INTERFACE ROUTINES
+ *		ExecColumnStoreMaterial		- materialize the result of a subplan
+ *		ExecInitColumnStoreMaterial	- initialize node and subnodes
+ *		ExecEndColumnStoreMaterial	- shutdown node and subnodes
+ *
+ */
+#include "postgres.h"
+
+#include "executor/executor.h"
+#include "executor/nodeColumnStoreMaterial.h"
+#include "miscadmin.h"
+
+/* ----------------------------------------------------------------
+ *		ExecColumnStoreMaterial
+ *
+ *		As long as we are at the end of the data collected in the tuplestore,
+ *		we collect one new row from the subplan on each call, and stash it
+ *		aside in the tuplestore before returning it.  The tuplestore is
+ *		only read if we are asked to scan backwards, rescan, or mark/restore.
+ *
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *				/* result tuple from subplan */
+ExecColumnStoreMaterial(ColumnStoreMaterialState *node)
+{
+//	EState	   *estate;
+//	ScanDirection dir;
+//	bool		forward;
+
+	PlanState  *outerNode;
+	TupleTableSlot *outerslot;
+
+	/*
+	 * get state info from node
+	 */
+//	estate = node->ss.ps.state;
+//	dir = estate->es_direction;
+//	forward = ScanDirectionIsForward(dir);
+
+	/* simply read tuple from the outer node (left subtree) */
+	outerNode = outerPlanState(node);
+	outerslot = ExecProcNode(outerNode);
+
+	if (TupIsNull(outerslot))
+		return NULL;
+
+	return outerslot;
+}
+
+/* ----------------------------------------------------------------
+ *		ExecInitMaterial
+ * ----------------------------------------------------------------
+ */
+ColumnStoreMaterialState *
+ExecInitColumnStoreMaterial(ColumnStoreMaterial *node, EState *estate, int eflags)
+{
+	ColumnStoreMaterialState *colmatstate;
+	Plan	   *outerPlan;
+
+	/*
+	 * create state structure
+	 */
+	colmatstate = makeNode(ColumnStoreMaterialState);
+	colmatstate->ss.ps.plan = (Plan *) node;
+	colmatstate->ss.ps.state = estate;
+
+	colmatstate->eflags = (eflags & (EXEC_FLAG_REWIND |
+									 EXEC_FLAG_BACKWARD |
+									 EXEC_FLAG_MARK));
+
+	/*
+	 * Miscellaneous initialization
+	 *
+	 * Materialization nodes don't need ExprContexts because they never call
+	 * ExecQual or ExecProject.
+	 */
+
+	/*
+	 * tuple table initialization
+	 *
+	 * material nodes only return tuples from their materialized relation.
+	 */
+	ExecInitResultTupleSlot(estate, &colmatstate->ss.ps);
+	ExecInitScanTupleSlot(estate, &colmatstate->ss);
+
+	/*
+	 * initialize child nodes
+	 *
+	 * We shield the child node from the need to support REWIND, BACKWARD, or
+	 * MARK/RESTORE.
+	 */
+	eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
+
+	outerPlan = outerPlan(node);
+	outerPlanState(colmatstate) = ExecInitNode(outerPlan, estate, eflags);
+
+	/*
+	 * initialize tuple type.  no need to initialize projection info because
+	 * this node doesn't do projections.
+	 */
+	ExecAssignResultTypeFromTL(&colmatstate->ss.ps);
+	ExecAssignScanTypeFromOuterPlan(&colmatstate->ss);
+	colmatstate->ss.ps.ps_ProjInfo = NULL;
+
+	return colmatstate;
+}
+
+/* ----------------------------------------------------------------
+ *		ExecColumnStoreEndMaterial
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndColumnStoreMaterial(ColumnStoreMaterialState *node)
+{
+	/*
+	 * clean out the tuple table
+	 */
+	ExecClearTuple(node->ss.ss_ScanTupleSlot);
+
+	/*
+	 * shut down the subplan
+	 */
+	ExecEndNode(outerPlanState(node));
+}
+
+/* ----------------------------------------------------------------
+ *		ExecColumnStoreMaterialMarkPos
+ * ----------------------------------------------------------------
+ */
+void
+ExecColumnStoreMaterialMarkPos(ColumnStoreMaterialState *node)
+{
+	Assert(node->eflags & EXEC_FLAG_MARK);
+
+	// FIXME
+}
+
+/* ----------------------------------------------------------------
+ *		ExecColumnStoreMaterialRestrPos
+ * ----------------------------------------------------------------
+ */
+void
+ExecColumnStoreMaterialRestrPos(ColumnStoreMaterialState *node)
+{
+	Assert(node->eflags & EXEC_FLAG_MARK);
+
+	// FIXME
+}
+
+/* ----------------------------------------------------------------
+ *		ExecColumnStoreReScanMaterial
+ *
+ *		Rescans the materialized relation.
+ * ----------------------------------------------------------------
+ */
+void
+ExecReScanColumnStoreMaterial(ColumnStoreMaterialState *node)
+{
+	ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+
+	if (node->ss.ps.lefttree->chgParam == NULL)
+		ExecReScan(node->ss.ps.lefttree);
+
+}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 92a14fe..2e550d2 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1733,6 +1733,16 @@ _outMaterialPath(StringInfo str, const MaterialPath *node)
 }
 
 static void
+_outColumnStoreMaterialPath(StringInfo str, const ColumnStoreMaterialPath *node)
+{
+	WRITE_NODE_TYPE("COLUMNSTOREMATERIALPATH");
+
+	_outPathInfo(str, (const Path *) node);
+
+	WRITE_NODE_FIELD(subpath);
+}
+
+static void
 _outUniquePath(StringInfo str, const UniquePath *node)
 {
 	WRITE_NODE_TYPE("UNIQUEPATH");
@@ -3311,6 +3321,9 @@ _outNode(StringInfo str, const void *obj)
 			case T_MaterialPath:
 				_outMaterialPath(str, obj);
 				break;
+			case T_ColumnStoreMaterialPath:
+				_outColumnStoreMaterialPath(str, obj);
+				break;
 			case T_UniquePath:
 				_outUniquePath(str, obj);
 				break;
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index d0bc412..3105df6 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -2582,6 +2582,7 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
 		case T_Hash:
 		case T_Agg:
 		case T_Material:
+		case T_ColumnStoreMaterial:
 		case T_Sort:
 		case T_Unique:
 		case T_SetOp:
diff --git a/src/include/executor/nodeColumnStoreMaterial.h b/src/include/executor/nodeColumnStoreMaterial.h
new file mode 100644
index 0000000..cd588d2
--- /dev/null
+++ b/src/include/executor/nodeColumnStoreMaterial.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeColumnStoreMaterial.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeColumnStoreMaterial.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODECOLSTOREMATERIAL_H
+#define NODECOLSTOREMATERIAL_H
+
+#include "nodes/execnodes.h"
+
+extern ColumnStoreMaterialState *ExecInitColumnStoreMaterial(ColumnStoreMaterial *node, EState *estate, int eflags);
+extern TupleTableSlot *ExecColumnStoreMaterial(ColumnStoreMaterialState *node);
+extern void ExecEndColumnStoreMaterial(ColumnStoreMaterialState *node);
+extern void ExecColumnStoreMaterialMarkPos(ColumnStoreMaterialState *node);
+extern void ExecColumnStoreMaterialRestrPos(ColumnStoreMaterialState *node);
+extern void ExecReScanColumnStoreMaterial(ColumnStoreMaterialState *node);
+
+#endif   /* NODECOLSTOREMATERIAL_H */
-- 
2.1.4

