diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index b019bc1..ab95fcc 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -299,6 +299,7 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock)
 	ItemPointerSetInvalid(&scan->rs_ctup.t_self);
 	scan->rs_cbuf = InvalidBuffer;
 	scan->rs_cblock = InvalidBlockNumber;
+	scan->rs_scanslot = NULL;
 
 	/* page-at-a-time fields are always invalid when not rs_inited */
 
@@ -660,7 +661,8 @@ heapgettup(HeapScanDesc scan,
 
 				if (valid && key != NULL)
 					HeapKeyTest(tuple, RelationGetDescr(scan->rs_rd),
-								nkeys, key, valid);
+							NULL, 0, NULL,
+							nkeys, key, valid);
 
 				if (valid)
 				{
@@ -955,7 +957,9 @@ heapgettup_pagemode(HeapScanDesc scan,
 				bool		valid;
 
 				HeapKeyTest(tuple, RelationGetDescr(scan->rs_rd),
-							nkeys, key, valid);
+						scan->rs_scanslot, scan->rs_cbuf,
+						scan->per_tuple_context,
+						nkeys, key, valid);
 				if (valid)
 				{
 					scan->rs_cindex = lineindex;
@@ -1649,7 +1653,8 @@ heap_parallelscan_initialize(ParallelHeapScanDesc target, Relation relation,
  * ----------------
  */
 HeapScanDesc
-heap_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan)
+heap_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan,
+						int nkeys, ScanKey key)
 {
 	Snapshot	snapshot;
 
@@ -1657,7 +1662,7 @@ heap_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan)
 	snapshot = RestoreSnapshot(parallel_scan->phs_snapshot_data);
 	RegisterSnapshot(snapshot);
 
-	return heap_beginscan_internal(relation, snapshot, 0, NULL, parallel_scan,
+	return heap_beginscan_internal(relation, snapshot, nkeys, key, parallel_scan,
 								   true, true, true, false, false, true);
 }
 
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index fb0013d..3a12ec4 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -205,7 +205,7 @@ ExecScan(ScanState *node,
 		 * when the qual is nil ... saves only a few cycles, but they add up
 		 * ...
 		 */
-		if (!qual || ExecQual(qual, econtext, false))
+		if (!node->ps.qual || ExecQual(node->ps.qual, econtext, false))
 		{
 			/*
 			 * Found a satisfactory scan tuple.
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 00bf3a5..695958f 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -30,9 +30,14 @@
 #include "executor/execdebug.h"
 #include "executor/nodeSeqscan.h"
 #include "utils/rel.h"
+#include "optimizer/clauses.h"
+#include "executor/executor.h"
+#include "access/valid.h"
 
 static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
 static TupleTableSlot *SeqNext(SeqScanState *node);
+static void get_scankey_from_qual(TupleDesc tupDesc, List *qual, PlanState *ps,
+							int *nkeys, ScanKey *rs_keys);
 
 /* ----------------------------------------------------------------
  *						Scan Support
@@ -53,6 +58,9 @@ SeqNext(SeqScanState *node)
 	EState	   *estate;
 	ScanDirection direction;
 	TupleTableSlot *slot;
+	int 		 nkeys = 0;
+	ScanKey		 keys = NULL;
+	bool		valid = false;
 
 	/*
 	 * get information from the estate and scan state
@@ -65,36 +73,76 @@ SeqNext(SeqScanState *node)
 	if (scandesc == NULL)
 	{
 		/*
+		 * Pull out scan key from qual list
+		 */
+		get_scankey_from_qual(RelationGetDescr(node->ss.ss_currentRelation),
+							 node->ss.ps.plan->qual, &node->ss.ps,
+							 &nkeys, &keys);
+
+		/*
 		 * We reach here if the scan is not parallel, or if we're executing a
 		 * scan that was intended to be parallel serially.
 		 */
 		scandesc = heap_beginscan(node->ss.ss_currentRelation,
 								  estate->es_snapshot,
 								  0, NULL);
+
+		node->ss.nkey = nkeys;
+		node->ss.keys = keys;
+
+
 		node->ss.ss_currentScanDesc = scandesc;
 	}
 
-	/*
-	 * get the next tuple from the table
-	 */
-	tuple = heap_getnext(scandesc, direction);
+	for (;;)
+	{
+		/*
+		 * get the next tuple from the table
+		 */
+		tuple = heap_getnext(scandesc, direction);
 
-	/*
-	 * save the tuple and the buffer returned to us by the access methods in
-	 * our scan tuple slot and return the slot.  Note: we pass 'false' because
-	 * tuples returned by heap_getnext() are pointers onto disk pages and were
-	 * not created with palloc() and so should not be pfree()'d.  Note also
-	 * that ExecStoreTuple will increment the refcount of the buffer; the
-	 * refcount will not be dropped until the tuple table slot is cleared.
-	 */
-	if (tuple)
-		ExecStoreTuple(tuple,	/* tuple to store */
-					   slot,	/* slot to store in */
-					   scandesc->rs_cbuf,		/* buffer associated with this
-												 * tuple */
-					   false);	/* don't pfree this pointer */
-	else
-		ExecClearTuple(slot);
+		/*
+		 * save the tuple and the buffer returned to us by the access methods in
+		 * our scan tuple slot and return the slot.  Note: we pass 'false' because
+		 * tuples returned by heap_getnext() are pointers onto disk pages and were
+		 * not created with palloc() and so should not be pfree()'d.  Note also
+		 * that ExecStoreTuple will increment the refcount of the buffer; the
+		 * refcount will not be dropped until the tuple table slot is cleared.
+		 *
+		 * If scandesc have valid scanslot means we would have already stored
+		 * tuple in slot, so no need to do it again.
+		 */
+		if (tuple)
+			ExecStoreTuple(tuple,	/* tuple to store */
+						   slot,	/* slot to store in */
+						   scandesc->rs_cbuf,		/* buffer associated with this
+													 * tuple */
+						   false);	/* don't pfree this pointer */
+		else
+			ExecClearTuple(slot);
+
+		if (tuple)
+		{
+			MemoryContext oldctx;
+
+			oldctx = MemoryContextSwitchTo(node->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
+			HeapKeyTest(tuple, RelationGetDescr(node->ss.ss_currentRelation),
+					slot, scandesc->rs_cbuf, NULL,
+					node->ss.nkey, node->ss.keys, valid);
+			if (valid != true)
+			{
+				MemoryContextSwitchTo(oldctx);
+				MemoryContextReset(node->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
+				continue;
+			}
+
+			MemoryContextSwitchTo(oldctx);
+
+			return slot;
+		}
+		else
+			break;
+	}
 
 	return slot;
 }
@@ -317,14 +365,24 @@ ExecSeqScanInitializeDSM(SeqScanState *node,
 {
 	EState	   *estate = node->ss.ps.state;
 	ParallelHeapScanDesc pscan;
+	int					 nkeys = 0;
+	ScanKey				 keys = NULL;
+
+	/*
+	 * Pull out scan key from qual list
+	 */
+	get_scankey_from_qual(RelationGetDescr(node->ss.ss_currentRelation),
+						 node->ss.ps.plan->qual, &node->ss.ps,
+						 &nkeys, &keys);
 
 	pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
 	heap_parallelscan_initialize(pscan,
 								 node->ss.ss_currentRelation,
 								 estate->es_snapshot);
 	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
-	node->ss.ss_currentScanDesc =
-		heap_beginscan_parallel(node->ss.ss_currentRelation, pscan);
+	node->ss.ss_currentScanDesc = heap_beginscan_parallel(
+										node->ss.ss_currentRelation, pscan,
+										nkeys, keys);
 }
 
 /* ----------------------------------------------------------------
@@ -337,8 +395,129 @@ void
 ExecSeqScanInitializeWorker(SeqScanState *node, shm_toc *toc)
 {
 	ParallelHeapScanDesc pscan;
+	int					 nkeys = 0;
+	ScanKey				 keys = NULL;
 
 	pscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
-	node->ss.ss_currentScanDesc =
-		heap_beginscan_parallel(node->ss.ss_currentRelation, pscan);
+
+	/*
+	 * Pull out scan key from qual list
+	 */
+	get_scankey_from_qual(RelationGetDescr(node->ss.ss_currentRelation),
+						 node->ss.ps.plan->qual, &node->ss.ps,
+						 &nkeys, &keys);
+
+	node->ss.ss_currentScanDesc = heap_beginscan_parallel(
+										node->ss.ss_currentRelation, pscan,
+										nkeys, keys);
+}
+
+/*
+ * get_scankey_from_qual
+ *
+ * process complete QUAL list and create scankey entry for pushable quals.
+ *
+ * quals which can be pushed down:
+ * 1. qual should be of form VAR op CONST.
+ * 2. VAR should be for datatype with fixed length.
+ */
+static void
+get_scankey_from_qual(TupleDesc tupDesc, List *qual, PlanState *ps,
+					int *nkeys, ScanKey *rs_keys)
+{
+	ListCell   		*l, *l1;
+	Expr 	   		*expr;
+	ListCell   		*prev = NULL;
+	ScanKey			 key;
+	Expr			*leftop;
+	Expr			*rightop;
+	AttrNumber	 	 varattno;
+	Datum		 	 scanvalue;
+
+	/*
+	 * Validate each qual whether this qual can be push down to heap node
+	 * or not, If this can be pushed down then create a ScanKey entry
+	 * and delete it from qual list of PlanState
+	 */
+	forboth(l, qual, l1, ps->qual)
+	{
+		expr = (Expr *) lfirst(l);
+
+		if (!IsA(expr, OpExpr))
+		{
+			prev = l1;
+			continue;
+		}
+
+
+		/* leftop should be the Var, possibly relabeled. */
+		leftop = (Expr *) get_leftop(expr);
+		if (leftop && IsA(leftop, RelabelType))
+			leftop = ((RelabelType *) leftop)->arg;
+
+		Assert(leftop != NULL);
+
+		/* If leftop is not var then continue and check next qual. */
+		if (!(IsA(leftop, Var)))
+		{
+			prev = l1;
+			continue;
+		}
+
+		varattno = ((Var *) leftop)->varattno;
+
+		/*
+		 * We don't want to push down the qual which can have variable
+		 * length data.
+		 */
+		if (varattno <= 0)
+		{
+			prev = l1;
+			continue;
+		}
+
+		rightop = (Expr *) get_rightop(expr);
+		if (rightop && IsA(rightop, RelabelType))
+			rightop = ((RelabelType *) rightop)->arg;
+
+		Assert(rightop != NULL);
+
+		/*
+		 * If right op is not constant then we can not push down this key
+		 * so move to next qual.
+		 */
+		if (!IsA(rightop, Const))
+		{
+			prev = l1;
+			continue;
+		}
+
+		scanvalue = ((Const *) rightop)->constvalue;
+
+		/* If we havn't yet allocated memory for scan keys, then do so. */
+		if (*rs_keys == NULL)
+		{
+			*rs_keys = (ScanKey) palloc(sizeof(ScanKeyData) *
+									list_length(qual));
+			key = *rs_keys;
+		}
+
+		/* Create scan key entry */
+		ScanKeyInit(key,
+				varattno,
+				InvalidStrategy,
+				((OpExpr *) expr)->opfuncid,
+				scanvalue);
+
+		key->sk_collation = ((OpExpr *) expr)->inputcollid;
+
+		key++;
+		(*nkeys)++;
+
+		/*
+		 * We have created scankey for this qual entry so remove it from
+		 * qual list.
+		 */
+		ps->qual = list_delete_cell(ps->qual, l1, prev);
+	}
 }
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 6016d19..48e50ce 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -1168,6 +1168,7 @@ SearchCatCache(CatCache *cache,
 		 */
 		HeapKeyTest(&ct->tuple,
 					cache->cc_tupdesc,
+					NULL, 0, NULL,
 					cache->cc_nkeys,
 					cur_skey,
 					res);
@@ -1459,6 +1460,7 @@ SearchCatCacheList(CatCache *cache,
 			continue;
 		HeapKeyTest(&cl->tuple,
 					cache->cc_tupdesc,
+					NULL, 0, NULL,
 					nkeys,
 					cur_skey,
 					res);
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 0d12bbb..d02f44a 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -130,7 +130,9 @@ extern HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction);
 extern Size heap_parallelscan_estimate(Snapshot snapshot);
 extern void heap_parallelscan_initialize(ParallelHeapScanDesc target,
 							 Relation relation, Snapshot snapshot);
-extern HeapScanDesc heap_beginscan_parallel(Relation, ParallelHeapScanDesc);
+extern HeapScanDesc heap_beginscan_parallel(Relation relation,
+						ParallelHeapScanDesc parallel_scan, int nkeys,
+						ScanKey key);
 
 extern bool heap_fetch(Relation relation, Snapshot snapshot,
 		   HeapTuple tuple, Buffer *userbuf, bool keep_buf,
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index de98dd6..f237ecd 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -20,7 +20,7 @@
 #include "access/itup.h"
 #include "access/tupdesc.h"
 #include "storage/spin.h"
-
+#include "executor/tuptable.h"
 /*
  * Shared state for parallel heap scan.
  *
@@ -70,6 +70,8 @@ typedef struct HeapScanDescData
 	Buffer		rs_cbuf;		/* current buffer in scan, if any */
 	/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
 	ParallelHeapScanDesc rs_parallel;	/* parallel scan information */
+	TupleTableSlot	*rs_scanslot;
+	MemoryContext	per_tuple_context;
 
 	/* these fields only used in page-at-a-time mode and for bitmap scans */
 	int			rs_cindex;		/* current tuple's index in vistuples */
diff --git a/src/include/access/valid.h b/src/include/access/valid.h
index 30af9df..bdcb390 100644
--- a/src/include/access/valid.h
+++ b/src/include/access/valid.h
@@ -21,15 +21,18 @@
  */
 #define HeapKeyTest(tuple, \
 					tupdesc, \
+					slot, \
+					buf, \
+					context, \
 					nkeys, \
 					keys, \
 					result) \
 do \
 { \
 	/* Use underscores to protect the variables passed in as parameters */ \
-	int			__cur_nkeys = (nkeys); \
-	ScanKey		__cur_keys = (keys); \
- \
+	int				__cur_nkeys = (nkeys); \
+	ScanKey			__cur_keys = (keys); \
+	\
 	(result) = true; /* may change */ \
 	for (; __cur_nkeys--; __cur_keys++) \
 	{ \
@@ -43,10 +46,13 @@ do \
 			break; \
 		} \
  \
-		__atp = heap_getattr((tuple), \
+ 	 	if (!(slot))	\
+			__atp = heap_getattr((tuple), \
 							 __cur_keys->sk_attno, \
 							 (tupdesc), \
 							 &__isnull); \
+		else \
+		    __atp = slot_getattr((slot), __cur_keys->sk_attno, &__isnull); \
  \
 		if (__isnull) \
 		{ \
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index f6f73f3..faad0a1 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1256,6 +1256,8 @@ typedef struct ScanState
 	Relation	ss_currentRelation;
 	HeapScanDesc ss_currentScanDesc;
 	TupleTableSlot *ss_ScanTupleSlot;
+	int			nkey;
+	ScanKey		keys;
 } ScanState;
 
 /* ----------------
