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..0f28443 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -30,9 +30,12 @@
 #include "executor/execdebug.h"
 #include "executor/nodeSeqscan.h"
 #include "utils/rel.h"
+#include "optimizer/clauses.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
@@ -64,17 +67,39 @@ SeqNext(SeqScanState *node)
 
 	if (scandesc == NULL)
 	{
+		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);
+
 		/*
 		 * 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);
+								  nkeys, keys);
+
 		node->ss.ss_currentScanDesc = scandesc;
 	}
 
 	/*
+	 *  If we have pushed down the scan keys to heap and scan slot is not
+	 *  yet stored in heap scan descriptor then do it.
+	 */
+	if (scandesc->rs_nkeys && !scandesc->rs_scanslot)
+	{
+		scandesc->rs_scanslot = slot;
+		scandesc->per_tuple_context =
+				node->ss.ps.ps_ExprContext->ecxt_per_tuple_memory;
+	}
+
+	/*
 	 * get the next tuple from the table
 	 */
 	tuple = heap_getnext(scandesc, direction);
@@ -86,16 +111,18 @@ SeqNext(SeqScanState *node)
 	 * 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)
+	if (!tuple)
+		ExecClearTuple(slot);
+	else if (!scandesc->rs_scanslot)
 		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);
-
 	return slot;
 }
 
@@ -317,14 +344,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 +374,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..b1d9bbb 100644
--- a/src/include/access/valid.h
+++ b/src/include/access/valid.h
@@ -21,14 +21,25 @@
  */
 #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); \
+	MemoryContext	__oldcontext;	\
+	\
+	if ((slot))	\
+			ExecStoreTuple(tuple,	/* tuple to store */	\
+					   (slot),	/* slot to store in */      \
+					   (buf),		/* buffer associated with this \
+												 * tuple */ \
+					   false);	/* don't pfree this pointer */ \
  \
 	(result) = true; /* may change */ \
 	for (; __cur_nkeys--; __cur_keys++) \
@@ -43,10 +54,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) \
 		{ \
@@ -54,9 +68,11 @@ do \
 			break; \
 		} \
  \
+ 	 	__oldcontext = MemoryContextSwitchTo(context);	\
 		__test = FunctionCall2Coll(&__cur_keys->sk_func, \
 								   __cur_keys->sk_collation, \
 								   __atp, __cur_keys->sk_argument); \
+		MemoryContextSwitchTo(__oldcontext);	\
  \
 		if (!DatumGetBool(__test)) \
 		{ \
