From 14bb38e179ffd497a3303e730bbe2674bd5d4d45 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Sun, 30 Aug 2015 01:28:47 -0300
Subject: [PATCH 20/24] Add FormColumnStoreDatum and FilterHeapTuple

These are temporary hacks only -- don't look at them too much.

FilterHeapTuple: this code is intended to take a full HeapTuple, and
create a new version of it stripped of columns that are not stored in
the heap.  The resulting tuple can be inserted into the heap.  This also
returns a TupleDescriptor useful for the raw heap.

FormColumnStoreDatum: this creates values/isnulls arrays that can be
passed to a column store for insert.

The definitive version of these routines probably ought to use
TupleTableSlots.

Implementation notes:

This commit includes necessary fields in struct ResultRelInfo, just so
that the functions compile.  These fields are not filled yet with this
commit.
---
 src/backend/catalog/colstore.c | 92 ++++++++++++++++++++++++++++++++++++++++++
 src/include/catalog/colstore.h |  8 ++++
 src/include/nodes/execnodes.h  |  6 +++
 3 files changed, 106 insertions(+)

diff --git a/src/backend/catalog/colstore.c b/src/backend/catalog/colstore.c
index 3954e1d..15cb8d4 100644
--- a/src/backend/catalog/colstore.c
+++ b/src/backend/catalog/colstore.c
@@ -579,6 +579,98 @@ BuildColumnStoreInfo(Relation cstore)
 	return csi;
 }
 
+/* ----------------
+ *		FormColumnStoreDatum
+ *			Construct values[] and isnull[] arrays for a new column store tuple.
+ *
+ *	columnStoreInfo	Info about the column store
+ *	slot			Heap tuple for which we must prepare a column store entry
+ *	values			Array of column store Datums (output area)
+ *	isnull			Array of is-null indicators (output area)
+ * ----------------
+ */
+void
+FormColumnStoreDatum(ColumnStoreInfo *columnStoreInfo,
+					 HeapTuple tuple,
+					 TupleDesc tupdesc,
+					 Datum *values,
+					 bool *isnull)
+{
+	int i;
+
+	for (i = 0; i < columnStoreInfo->csi_NumColumnStoreAttrs; i++)
+		values[i] = heap_getattr(tuple,
+								 columnStoreInfo->csi_KeyAttrNumbers[i],
+								 tupdesc,
+								 &isnull[i]);
+}
+
+/*
+ * Builds a descriptor for the heap part of the relation, and a tuple with only
+ * the relevant attributes.
+ */
+HeapTuple
+FilterHeapTuple(ResultRelInfo *resultRelInfo, HeapTuple tuple, TupleDesc *heapdesc)
+{
+	int			i, j, attnum;
+	Bitmapset  *cstoreatts = NULL;	/* attributes mentioned in colstore */
+
+	TupleDesc	origdesc = resultRelInfo->ri_RelationDesc->rd_att;
+	HeapTuple	newtup;
+
+	/* used to build the new descriptor / tuple */
+	int		natts;
+	Datum  *values;
+	bool   *nulls;
+
+	/* should not be called with no column stores */
+	Assert(resultRelInfo->ri_NumColumnStores > 0);
+
+	for (i = 0; i < resultRelInfo->ri_NumColumnStores; i++)
+	{
+		ColumnStoreInfo *cstinfo = resultRelInfo->ri_ColumnStoreRelationInfo[i];
+
+		for (j = 0; j < cstinfo->csi_NumColumnStoreAttrs; j++)
+			cstoreatts = bms_add_member(cstoreatts,
+										cstinfo->csi_KeyAttrNumbers[j]);
+	}
+
+	/* we should get some columns from column stores */
+	Assert(bms_num_members(cstoreatts) > 0);
+
+	/* the new descriptor contains only the remaining attributes */
+	natts = origdesc->natts - bms_num_members(cstoreatts);
+
+	*heapdesc = CreateTemplateTupleDesc(natts, false);
+
+	values = (Datum *) palloc0(sizeof(Datum) * natts);
+	nulls  = (bool *) palloc0(sizeof(bool) * natts);
+
+	attnum = 1;
+	for (i = 0; i < origdesc->natts; i++)
+	{
+		/* if part of a column store, skip the attribute */
+		if (bms_is_member(origdesc->attrs[i]->attnum, cstoreatts))
+			continue;
+
+		values[attnum - 1] = heap_getattr(tuple, i + 1, origdesc,
+										  &nulls[attnum - 1]);
+
+		TupleDescCopyEntry(*heapdesc, attnum++, origdesc, i + 1);
+	}
+
+	newtup = heap_form_tuple(*heapdesc, values, nulls);
+
+	/* copy important header fields */
+	newtup->t_self = tuple->t_self;
+	newtup->t_data->t_ctid = tuple->t_data->t_ctid;
+
+	pfree(values);
+	pfree(nulls);
+
+	return newtup;
+}
+
 /*
  * GetColumnStoreRoutine - call the specified column store handler routine
  * to get its ColumnStoreRoutine struct.
diff --git a/src/include/catalog/colstore.h b/src/include/catalog/colstore.h
index 638c0e5..20be191 100644
--- a/src/include/catalog/colstore.h
+++ b/src/include/catalog/colstore.h
@@ -41,4 +41,12 @@ extern Oid GetColumnStoreAMByName(char *cstamname, bool missing_ok);
 
 extern ColumnStoreInfo *BuildColumnStoreInfo(Relation cstore);
 
+/* XXX these are temporary hacks */
+extern void FormColumnStoreDatum(ColumnStoreInfo *columnStoreInfo,
+					 HeapTuple tuple, TupleDesc tupdesc,
+					 Datum *values, bool *isnull);
+extern HeapTuple FilterHeapTuple(ResultRelInfo *resultRelInfo, HeapTuple tuple,
+				TupleDesc *heapdesc);
+
+
 #endif		/* COLSTORE_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index c0a9862..574b904 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -324,6 +324,9 @@ typedef struct JunkFilter
  *		NumIndices				# of indices existing on result relation
  *		IndexRelationDescs		array of relation descriptors for indices
  *		IndexRelationInfo		array of key/attr info for indices
+ *		NumColumnStores			# of column stores existing on result relation
+ *		ColumnStoreRelationDescs	array of rel. descriptors for column stores
+ *		ColumnStoreRelationInfo		array of key/attr info for column stores
  *		TrigDesc				triggers to be fired, if any
  *		TrigFunctions			cached lookup info for trigger functions
  *		TrigWhenExprs			array of trigger WHEN expr states
@@ -347,6 +350,9 @@ typedef struct ResultRelInfo
 	int			ri_NumIndices;
 	RelationPtr ri_IndexRelationDescs;
 	IndexInfo **ri_IndexRelationInfo;
+	int			ri_NumColumnStores;
+	RelationPtr ri_ColumnStoreRelationDescs;
+	ColumnStoreInfo **ri_ColumnStoreRelationInfo;
 	TriggerDesc *ri_TrigDesc;
 	FmgrInfo   *ri_TrigFunctions;
 	List	  **ri_TrigWhenExprs;
-- 
2.1.4

