From ea0cfca172713d6d1284380b01dc51938b726e05 Mon Sep 17 00:00:00 2001
From: Hari <haribabuk@fast.au.fujitsu.com>
Date: Tue, 20 Dec 2016 17:23:01 +1100
Subject: [PATCH 2/3] Server minimal changes

Hooks and minimal structure changes that are required for
VCI to work properly
---
 src/backend/access/heap/heapam.c       | 15 +++++++++++++++
 src/backend/catalog/dependency.c       |  6 ++++++
 src/backend/catalog/index.c            | 20 ++++++++++++++++++++
 src/backend/commands/tablecmds.c       | 15 +++++++++++++++
 src/backend/executor/execQual.c        |  6 ++++++
 src/backend/executor/nodeModifyTable.c | 12 ++++++++++++
 src/backend/nodes/params.c             |  1 +
 src/backend/utils/cache/relcache.c     | 16 ++++++++++++++++
 src/include/access/heapam.h            |  8 ++++++++
 src/include/catalog/dependency.h       |  4 ++++
 src/include/catalog/index.h            |  4 ++++
 src/include/catalog/pg_class.h         |  1 +
 src/include/commands/tablecmds.h       | 13 +++++++++++++
 src/include/executor/nodeModifyTable.h |  3 +++
 src/include/nodes/extensible.h         |  3 +++
 src/include/nodes/params.h             |  9 ++++++++-
 src/include/nodes/plannodes.h          |  2 ++
 src/include/utils/relcache.h           |  3 +++
 18 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index ea579a0..7226ac4 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -77,6 +77,8 @@
 /* GUC variable */
 bool		synchronize_seqscans = true;
 
+add_index_delete_hook_type add_index_delete_hook = NULL;
+add_heap_rescan_skip_recounting_nblocks_hook_type add_heap_rescan_skip_recounting_nblocks_hook = NULL;
 
 static HeapScanDesc heap_beginscan_internal(Relation relation,
 						Snapshot snapshot,
@@ -229,10 +231,15 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	 * results for a non-MVCC snapshot, the caller must hold some higher-level
 	 * lock that ensures the interesting tuple(s) won't change.)
 	 */
+	if (keep_startblock)
+		if (add_heap_rescan_skip_recounting_nblocks_hook)
+			if (add_heap_rescan_skip_recounting_nblocks_hook(scan, key))
+				goto skip_get_number_of_blocks;
 	if (scan->rs_parallel != NULL)
 		scan->rs_nblocks = scan->rs_parallel->phs_nblocks;
 	else
 		scan->rs_nblocks = RelationGetNumberOfBlocks(scan->rs_rd);
+skip_get_number_of_blocks:
 
 	/*
 	 * If the table is large relative to NBuffers, use a bulk-read access
@@ -3003,6 +3010,7 @@ heap_delete(Relation relation, ItemPointer tid,
 	bool		all_visible_cleared = false;
 	HeapTuple	old_key_tuple = NULL;	/* replica identity of the tuple */
 	bool		old_key_copied = false;
+	TransactionId old_xmin;
 
 	Assert(ItemPointerIsValid(tid));
 
@@ -3223,6 +3231,7 @@ l1:
 							  xid, LockTupleExclusive, true,
 							  &new_xmax, &new_infomask, &new_infomask2);
 
+	old_xmin = HeapTupleHeaderGetXmin(tp.t_data);
 	START_CRIT_SECTION();
 
 	/*
@@ -3358,6 +3367,8 @@ l1:
 	if (old_key_tuple != NULL && old_key_copied)
 		heap_freetuple(old_key_tuple);
 
+	if (add_index_delete_hook)
+		add_index_delete_hook(relation, tid, old_xmin);
 	return HeapTupleMayBeUpdated;
 }
 
@@ -3475,6 +3486,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
 				infomask2_old_tuple,
 				infomask_new_tuple,
 				infomask2_new_tuple;
+	TransactionId old_xmin;
 
 	Assert(ItemPointerIsValid(otid));
 
@@ -3836,6 +3848,7 @@ l2:
 							  &xmax_old_tuple, &infomask_old_tuple,
 							  &infomask2_old_tuple);
 
+	old_xmin = HeapTupleHeaderGetRawXmin(oldtup.t_data);
 	/*
 	 * And also prepare an Xmax value for the new copy of the tuple.  If there
 	 * was no xmax previously, or there was one but all lockers are now gone,
@@ -4271,6 +4284,8 @@ l2:
 	bms_free(key_attrs);
 	bms_free(id_attrs);
 
+	if (add_index_delete_hook)
+		add_index_delete_hook(relation, otid, old_xmin);
 	return HeapTupleMayBeUpdated;
 }
 
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 18a14bf..d576809 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -79,6 +79,7 @@
 #include "utils/syscache.h"
 #include "utils/tqual.h"
 
+add_drop_relation_hook_type add_drop_relation_hook = NULL;
 
 /*
  * Deletion processing requires additional state for each ObjectAddress that
@@ -1100,6 +1101,11 @@ doDeletion(const ObjectAddress *object, int flags)
 			{
 				char		relKind = get_rel_relkind(object->objectId);
 
+				if (add_drop_relation_hook && object->objectSubId == 0)
+				{
+					if (add_drop_relation_hook(object->objectId, flags))
+						break;
+				}
 				if (relKind == RELKIND_INDEX)
 				{
 					bool		concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 08b0989..445d0b0 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -127,6 +127,13 @@ static void SetReindexPending(List *indexes);
 static void RemoveReindexPending(Oid indexOid);
 static void ResetReindexPending(void);
 
+add_reindex_index_hook_type add_reindex_index_hook = NULL;
+
+/*
+ * Itempointer points to the actual heaptuple
+ * not to the root tuple used for index build callback
+ */
+ItemPointerData IndexingHeapTupleTid;
 
 /*
  * relationHasPrimaryKey
@@ -2576,6 +2583,7 @@ IndexBuildHeapRangeScan(Relation heapRelation,
 		 * some index AMs want to do further processing on the data first.  So
 		 * pass the values[] and isnull[] arrays, instead.
 		 */
+		IndexingHeapTupleTid = heapTuple->t_self;
 
 		if (HeapTupleIsHeapOnly(heapTuple))
 		{
@@ -3329,6 +3337,18 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
 	 */
 	iRel = index_open(indexId, AccessExclusiveLock);
 
+	if(add_reindex_index_hook)
+	{
+		if (!add_reindex_index_hook(iRel))
+		{
+			RemoveReindexPending(RelationGetRelid(iRel));
+
+			/* Close rels, but keep locks */
+			index_close(iRel, NoLock);
+			heap_close(heapRelation, NoLock);
+			return;
+		}
+	}
 	/*
 	 * Don't allow reindex on temp tables of other backends ... their local
 	 * buffer manager is not going to cope.
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index b0e3f28..94db866 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -100,6 +100,9 @@
 #include "utils/tqual.h"
 #include "utils/typcache.h"
 
+add_alter_tablespace_hook_type add_alter_tablespace_hook = NULL;
+add_alter_table_change_owner_hook_type add_alter_table_change_owner_hook = NULL;
+add_alter_table_change_schema_hook_type add_alter_table_change_schema_hook = NULL;
 
 /*
  * ON COMMIT action list
@@ -9672,6 +9675,8 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
 			/* If it has dependent sequences, recurse to change them too */
 			change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
 		}
+		if (add_alter_table_change_owner_hook)
+			add_alter_table_change_owner_hook(relationOid, tuple_class->relkind, newOwnerId);
 	}
 
 	InvokeObjectPostAlterHook(RelationRelationId, relationOid, 0);
@@ -10116,6 +10121,14 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
 	 * Need lock here in case we are recursing to toast table or index
 	 */
 	rel = relation_open(tableOid, lockmode);
+	if (add_alter_tablespace_hook)
+	{
+		if (add_alter_tablespace_hook(rel))
+		{
+			relation_close(rel, NoLock);
+			return;
+		}
+	}
 
 	/*
 	 * No work if no change in tablespace.
@@ -12191,6 +12204,8 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
 	{
 		add_exact_object_address(&thisobj, objsMoved);
 
+		if (add_alter_table_change_schema_hook)
+			add_alter_table_change_schema_hook(relOid, classForm->relkind, newNspOid);
 		InvokeObjectPostAlterHook(RelationRelationId, relOid, 0);
 	}
 
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index ec1ca01..c8923af 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -4603,6 +4603,12 @@ ExecInitExpr(Expr *node, PlanState *parent)
 			state->evalfunc = ExecEvalConst;
 			break;
 		case T_Param:
+			if (ExecInitParam_hook)
+			{
+				state = ExecInitParam_hook((Param *) node, parent);
+				if (state)
+					break;
+			}
 			state = makeNode(ExprState);
 			switch (((Param *) node)->paramkind)
 			{
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 0d85b15..e89dfa2 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -52,6 +52,7 @@
 #include "utils/rel.h"
 #include "utils/tqual.h"
 
+add_should_index_insert_hook_type add_should_index_insert_hook = NULL;
 
 static bool ExecOnConflictUpdate(ModifyTableState *mtstate,
 					 ResultRelInfo *resultRelInfo,
@@ -1103,6 +1104,17 @@ lreplace:;
 		if (resultRelInfo->ri_NumIndices > 0 && !HeapTupleIsHeapOnly(tuple))
 			recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
 												   estate, false, NULL, NIL);
+		else if( resultRelInfo->ri_NumIndices > 0 && HeapTupleIsHeapOnly(tuple) )
+		{
+			/*
+			 * But for VCI index, the newtuple needs to be inserted into VCI,
+			 * Because of this reason, the HOT tuple gets inserted through the
+			 * hook function
+			 */
+			if(add_should_index_insert_hook)
+				recheckIndexes = add_should_index_insert_hook(slot,&(tuple->t_self),
+															  estate);
+		}
 	}
 
 	if (canSetTag)
diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c
index f2e26b8..e88394a 100644
--- a/src/backend/nodes/params.c
+++ b/src/backend/nodes/params.c
@@ -21,6 +21,7 @@
 #include "utils/datum.h"
 #include "utils/lsyscache.h"
 
+ExecInitParam_hook_type ExecInitParam_hook;
 
 /*
  * Copy a ParamListInfo structure.
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 2a68359..6d7de3d 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -83,6 +83,7 @@
 #include "utils/syscache.h"
 #include "utils/tqual.h"
 
+add_skip_vci_index_hook_type add_skip_vci_index_hook = NULL;
 
 /*
  *		name of relcache init file(s), used to speed up backend startup
@@ -4790,6 +4791,21 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
 
 		indexDesc = index_open(indexOid, AccessShareLock);
 
+		/*
+		 * Check Whether the index is of type VCI or not?
+		 *
+		 * If it is VCI type Skip adding to the relation index list.
+		 * VCI index's are not like normal indexes, so don't add them.
+		 */
+		if (add_skip_vci_index_hook)
+		{
+			if (add_skip_vci_index_hook(indexDesc))
+			{
+				/* Skip if Index is VCI index */
+				index_close(indexDesc, AccessShareLock);
+				continue;
+			}
+		}
 		/* Extract index key information from the index's pg_index row */
 		indexInfo = BuildIndexInfo(indexDesc);
 
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 0d12bbb..b4daf68 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -196,4 +196,12 @@ extern BlockNumber ss_get_location(Relation rel, BlockNumber relnblocks);
 extern void SyncScanShmemInit(void);
 extern Size SyncScanShmemSize(void);
 
+/* Hook for plugins to get control for heap delete operation */
+typedef void (*add_index_delete_hook_type)(Relation indexRelation, ItemPointer heap_tid, TransactionId xmin);
+extern PGDLLIMPORT add_index_delete_hook_type add_index_delete_hook;
+
+/* Hook for plugins to get control in heap rescan */
+typedef bool (*add_heap_rescan_skip_recounting_nblocks_hook_type)(HeapScanDesc scan, ScanKey key);
+extern PGDLLIMPORT add_heap_rescan_skip_recounting_nblocks_hook_type add_heap_rescan_skip_recounting_nblocks_hook;
+
 #endif   /* HEAPAM_H */
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index e8a302f..f5ba30a 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -276,4 +276,8 @@ extern void shdepDropOwned(List *relids, DropBehavior behavior);
 
 extern void shdepReassignOwned(List *relids, Oid newrole);
 
+/* Hook for plugins to get control for drop index operation */
+typedef bool (*add_drop_relation_hook_type)(Oid relOid, int flags);
+extern PGDLLIMPORT add_drop_relation_hook_type add_drop_relation_hook;
+
 #endif   /* DEPENDENCY_H */
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 37e6ef3..c784428 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -131,4 +131,8 @@ extern bool ReindexIsProcessingHeap(Oid heapOid);
 extern bool ReindexIsProcessingIndex(Oid indexOid);
 extern Oid	IndexGetRelation(Oid indexId, bool missing_ok);
 
+/* Hook for plugins to get control for reindex operation */
+typedef bool (*add_reindex_index_hook_type)(Relation);
+extern PGDLLIMPORT add_reindex_index_hook_type add_reindex_index_hook;
+extern PGDLLIMPORT ItemPointerData IndexingHeapTupleTid;
 #endif   /* INDEX_H */
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index a61b7a2..f6f7dd4 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -166,6 +166,7 @@ DESCR("");
 #define		  RELKIND_FOREIGN_TABLE   'f'		/* foreign table */
 #define		  RELKIND_MATVIEW		  'm'		/* materialized view */
 #define		  RELKIND_PARTITIONED_TABLE 'P'		/* partitioned table */
+#define           RELKIND_CSTORE                  'C'           /* columnar store rel */
 
 #define		  RELPERSISTENCE_PERMANENT	'p'		/* regular table */
 #define		  RELPERSISTENCE_UNLOGGED	'u'		/* unlogged permanent table */
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index fa48f2e..8020a98 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -87,4 +87,17 @@ extern void RangeVarCallbackOwnsTable(const RangeVar *relation,
 
 extern void RangeVarCallbackOwnsRelation(const RangeVar *relation,
 							 Oid relId, Oid oldRelId, void *noCatalogs);
+
+/* Hook for plugins to get control for alter tablespace operation */
+typedef bool (*add_alter_tablespace_hook_type)(Relation rel);
+extern PGDLLIMPORT add_alter_tablespace_hook_type add_alter_tablespace_hook;
+
+/* Hook for plugins to get control for alter table change owner operation */
+typedef void (*add_alter_table_change_owner_hook_type)(Oid relOid, char relKind, Oid newOwnerId);
+extern PGDLLIMPORT add_alter_table_change_owner_hook_type add_alter_table_change_owner_hook;
+
+/* Hook for plugins to get control for alter table change schema operation */
+typedef void (*add_alter_table_change_schema_hook_type)(Oid relOid, char relKind, Oid newNspOid);
+extern PGDLLIMPORT add_alter_table_change_schema_hook_type add_alter_table_change_schema_hook;
+
 #endif   /* TABLECMDS_H */
diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h
index 6b66353..8ef9167 100644
--- a/src/include/executor/nodeModifyTable.h
+++ b/src/include/executor/nodeModifyTable.h
@@ -20,4 +20,7 @@ extern TupleTableSlot *ExecModifyTable(ModifyTableState *node);
 extern void ExecEndModifyTable(ModifyTableState *node);
 extern void ExecReScanModifyTable(ModifyTableState *node);
 
+/* Hook for plugins to get control for HOT update operation */
+typedef List* (*add_should_index_insert_hook_type)(TupleTableSlot*, ItemPointer, EState* );
+extern PGDLLIMPORT add_should_index_insert_hook_type add_should_index_insert_hook;
 #endif   /* NODEMODIFYTABLE_H */
diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h
index 17afe58..f2a85de 100644
--- a/src/include/nodes/extensible.h
+++ b/src/include/nodes/extensible.h
@@ -144,6 +144,9 @@ typedef struct CustomExecMethods
 	void		(*ExplainCustomScan) (CustomScanState *node,
 												  List *ancestors,
 												  ExplainState *es);
+	/* added for vci */
+	void		(*SetBoundCustomScan)(const struct LimitState *limit,struct CustomScanState *cps);
+	void		(*ExplainCustomPlanTargetRel) (struct CustomScanState *node, struct ExplainState *es);
 } CustomExecMethods;
 
 extern void RegisterCustomScanMethods(const CustomScanMethods *methods);
diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h
index a8aa530..f215981 100644
--- a/src/include/nodes/params.h
+++ b/src/include/nodes/params.h
@@ -17,7 +17,9 @@
 /* Forward declarations, to avoid including other headers */
 struct Bitmapset;
 struct ParseState;
-
+struct Param;
+struct ExprState;
+struct PlanState;
 
 /* ----------------
  *	  ParamListInfo
@@ -99,6 +101,8 @@ typedef struct ParamExecData
 	void	   *execPlan;		/* should be "SubPlanState *" */
 	Datum		value;
 	bool		isnull;
+	bool		noNeedLoadFromMain;
+	bool		loadedFromMain;
 } ParamExecData;
 
 
@@ -108,4 +112,7 @@ extern Size EstimateParamListSpace(ParamListInfo paramLI);
 extern void SerializeParamList(ParamListInfo paramLI, char **start_address);
 extern ParamListInfo RestoreParamList(char **start_address);
 
+/* Hook for plugins to get control Parameters in expressions */
+typedef struct ExprState *(*ExecInitParam_hook_type)(struct Param *param, struct PlanState *parent);
+extern PGDLLIMPORT ExecInitParam_hook_type ExecInitParam_hook;
 #endif   /* PARAMS_H */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index e2fbc7d..279b9d5 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -112,6 +112,8 @@ typedef struct Plan
 	 * information needed for parallel query
 	 */
 	bool		parallel_aware; /* engage parallel-aware logic? */
+	/* added for vci */
+	AttrNumber	plan_no;		/* plan number (1-origin) in the Query */
 
 	/*
 	 * Common structural data for all Plan types.
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 6ea7dd2..b08ec93 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -128,4 +128,7 @@ extern bool criticalRelcachesBuilt;
 /* should be used only by relcache.c and postinit.c */
 extern bool criticalSharedRelcachesBuilt;
 
+/* Hook for plugins to get control for Relation build */
+typedef bool (*add_skip_vci_index_hook_type)(Relation rel);
+extern PGDLLIMPORT bool (*add_skip_vci_index_hook)(Relation rel);
 #endif   /* RELCACHE_H */
-- 
2.7.4.windows.1

