You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by in...@apache.org on 2018/04/19 10:28:40 UTC

[3/3] incubator-hawq git commit: HAWQ-1603. Add new hook API

HAWQ-1603. Add new hook API


Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/80eaf448
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/80eaf448
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/80eaf448

Branch: refs/heads/master
Commit: 80eaf448f01c9422f1d7631527026804f954b252
Parents: f68cac7
Author: Shujie Zhang <sh...@Shujie-Zhangs-MacBook-Pro.local>
Authored: Wed Apr 4 16:10:07 2018 +0800
Committer: interma <in...@outlook.com>
Committed: Thu Apr 19 18:27:54 2018 +0800

----------------------------------------------------------------------
 contrib/vexecutor/execVQual.c                  |   574 +-
 contrib/vexecutor/execVQual.h                  |     7 +-
 contrib/vexecutor/execVScan.c                  |    43 +-
 contrib/vexecutor/vadt.c                       |    66 +-
 contrib/vexecutor/vexecutor.c                  |    83 +-
 contrib/vexecutor/vexecutor.h                  |     1 +
 src/backend/executor/execMain.c                |     5 +
 src/backend/executor/execProcnode.c            |    20 +-
 src/backend/executor/execQual.c                |    10 +
 src/include/executor/executor.h                |     4 +-
 src/test/feature/vexecutor/ans/.DS_Store       |   Bin 0 -> 6148 bytes
 src/test/feature/vexecutor/ans/projandqual.ans |    40 +
 src/test/feature/vexecutor/ans/scan1.ans       | 19743 +++++++++---------
 src/test/feature/vexecutor/sql/projandqual.sql |     4 +
 src/test/feature/vexecutor/sql/scan1.sql       |     2 +-
 src/test/feature/vexecutor/test_vexecutor.cpp  |    19 +
 16 files changed, 10657 insertions(+), 9964 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/contrib/vexecutor/execVQual.c
----------------------------------------------------------------------
diff --git a/contrib/vexecutor/execVQual.c b/contrib/vexecutor/execVQual.c
index c4ccf9e..83e298a 100644
--- a/contrib/vexecutor/execVQual.c
+++ b/contrib/vexecutor/execVQual.c
@@ -16,8 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+#include "postgres.h"
+#include "utils/builtins.h"
 #include "execVQual.h"
-
+static bool
+ExecVTargetList(List *targetlist,
+			   ExprContext *econtext,
+			   TupleTableSlot *slot,
+			   ExprDoneCond *itemIsDone,
+			   ExprDoneCond *isDone);
 /*
  * ExecVariableList
  *		Evaluates a simple-Variable-list projection.
@@ -26,12 +33,12 @@
  */
 static void
 ExecVecVariableList(ProjectionInfo *projInfo,
-                 Datum *values)
+                 Datum values)
 {
     ExprContext *econtext = projInfo->pi_exprContext;
     int		   *varSlotOffsets = projInfo->pi_varSlotOffsets;
     int		   *varNumbers = projInfo->pi_varNumbers;
-    TupleBatch  tb = (TupleBatch) values;
+    TupleBatch  tb = (TupleBatch) DatumGetPointer(values);
     int			i;
     tb->ncols = list_length(projInfo->pi_targetlist);
 
@@ -81,14 +88,12 @@ ExecVProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
     }
     else
     {
-        elog(FATAL,"does not support expression in projection stmt");
-       // if (ExecTargetList(projInfo->pi_targetlist,
-       //                    projInfo->pi_exprContext,
-       //                    slot_get_values(slot),
-       //                    slot_get_isnull(slot),
-       //                    (ExprDoneCond *) projInfo->pi_itemIsDone,
-       //                    isDone))
-       //     ExecStoreVirtualTuple(slot);
+       if (ExecVTargetList(projInfo->pi_targetlist,
+                           projInfo->pi_exprContext,
+                           slot,
+                           (ExprDoneCond *) projInfo->pi_itemIsDone,
+                           isDone))
+            ExecStoreVirtualTuple(slot);
     }
 
     return slot;
@@ -104,7 +109,7 @@ VirtualNodeProc(ScanState* state,TupleTableSlot *slot){
     if(TupIsNull(slot) )
         return false;
 
-    TupleBatch tb = slot->PRIVATE_tb;
+    TupleBatch tb = (TupleBatch)DatumGetPointer(slot->PRIVATE_tb);
     ExecClearTuple(slot);
 
     while (tb->skip[tb->iter] && tb->iter < tb->nrows)
@@ -123,3 +128,548 @@ VirtualNodeProc(ScanState* state,TupleTableSlot *slot){
     ExecStoreVirtualTuple(slot);
     return true;
 }
+
+/*
+ * get values from vectorized tuple slot
+ * copy from src/backend/executor/execQual.c
+ */
+static Datum
+VExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
+			bool *isNull, ExprDoneCond *isDone)
+{
+	Var		   *variable = (Var *) exprstate->expr;
+	TupleTableSlot *slot;
+	AttrNumber	attnum;
+	TupleBatch tb;
+
+	if (isDone)
+		*isDone = ExprSingleResult;
+
+	Assert(econtext->ecxt_scantuple != NULL || econtext->ecxt_innertuple != NULL || econtext->ecxt_outertuple != NULL);
+	/*
+	 * Get the input slot and attribute number we want
+	 *
+	 * The asserts check that references to system attributes only appear at
+	 * the level of a relation scan; at higher levels, system attributes must
+	 * be treated as ordinary variables (since we no longer have access to the
+	 * original tuple).
+	 */
+	attnum = variable->varattno;
+
+	switch (variable->varno)
+	{
+		case INNER:				/* get the tuple from the inner node */
+			slot = econtext->ecxt_innertuple;
+			Assert(attnum > 0);
+			break;
+
+		case OUTER:				/* get the tuple from the outer node */
+			slot = econtext->ecxt_outertuple;
+			Assert(attnum > 0);
+			break;
+
+		default:				/* get the tuple from the relation being
+								 * scanned */
+			slot = econtext->ecxt_scantuple;
+			break;
+	}
+
+	/* isNull is a single value, it can not be used when data is vectorized */
+	*isNull = false;
+
+	/* Fetch the value from the slot */
+	Assert(NULL != slot);
+	tb = (TupleBatch )slot->PRIVATE_tb;
+
+	Assert(NULL != tb);
+
+	return PointerGetDatum(tb->datagroup[attnum - 1]);
+}
+
+
+/*
+ * get values from vectorized tuple slot
+ * copy from src/backend/executor/execQual.c
+ */
+static Datum
+VExecEvalVar(ExprState *exprstate, ExprContext *econtext,
+			bool *isNull, ExprDoneCond *isDone)
+{
+	Var		   *variable = (Var *) exprstate->expr;
+	TupleTableSlot *slot;
+	AttrNumber	attnum;
+
+	if (isDone)
+		*isDone = ExprSingleResult;
+
+	Assert(econtext->ecxt_scantuple != NULL || econtext->ecxt_innertuple != NULL || econtext->ecxt_outertuple != NULL);
+	/*
+	 * Get the input slot and attribute number we want
+	 *
+	 * The asserts check that references to system attributes only appear at
+	 * the level of a relation scan; at higher levels, system attributes must
+	 * be treated as ordinary variables (since we no longer have access to the
+	 * original tuple).
+	 */
+	attnum = variable->varattno;
+
+	switch (variable->varno)
+	{
+		case INNER:				/* get the tuple from the inner node */
+			slot = econtext->ecxt_innertuple;
+			Assert(attnum > 0);
+			break;
+
+		case OUTER:				/* get the tuple from the outer node */
+			slot = econtext->ecxt_outertuple;
+			Assert(attnum > 0);
+			break;
+
+		default:				/* get the tuple from the relation being
+								 * scanned */
+			slot = econtext->ecxt_scantuple;
+			break;
+	}
+
+	Assert(NULL != slot);
+
+	if (attnum != InvalidAttrNumber)
+	{
+		TupleBatch tb;
+		/*
+		 * Scalar variable case.
+		 *
+		 * If it's a user attribute, check validity (bogus system attnums will
+		 * be caught inside slot_getattr).  What we have to check for here
+		 * is the possibility of an attribute having been changed in type
+		 * since the plan tree was created.  Ideally the plan would get
+		 * invalidated and not re-used, but until that day arrives, we need
+		 * defenses.  Fortunately it's sufficient to check once on the first
+		 * time through.
+		 *
+		 * Note: we allow a reference to a dropped attribute.  slot_getattr
+		 * will force a NULL result in such cases.
+		 *
+		 * Note: ideally we'd check typmod as well as typid, but that seems
+		 * impractical at the moment: in many cases the tupdesc will have
+		 * been generated by ExecTypeFromTL(), and that can't guarantee to
+		 * generate an accurate typmod in all cases, because some expression
+		 * node types don't carry typmod.
+		 */
+		if (attnum > 0)
+		{
+			TupleDesc	slot_tupdesc = slot->tts_tupleDescriptor;
+			Form_pg_attribute attr;
+
+			if (attnum > slot_tupdesc->natts)	/* should never happen */
+				elog(ERROR, "attribute number %d exceeds number of columns %d",
+					 attnum, slot_tupdesc->natts);
+
+			attr = slot_tupdesc->attrs[attnum - 1];
+
+			/* can't check type if dropped, since atttypid is probably 0 */
+			if (!attr->attisdropped)
+			{
+				if (variable->vartype != attr->atttypid &&
+					GetNType(variable->vartype) != attr->atttypid)
+					ereport(ERROR,
+							(errmsg("attribute %d has wrong type", attnum),
+							 errdetail("Table has type %s, but query expects %s.",
+									   format_type_be(attr->atttypid),
+									   format_type_be(variable->vartype))));
+			}
+		}
+
+		/* Skip the checking on future executions of node */
+		exprstate->evalfunc = VExecEvalScalarVar;
+
+		/* isNull is a single value, it can not be used when data is vectorized */
+		*isNull = false;
+
+		/* Fetch the value from the slot */
+		tb = (TupleBatch )slot->PRIVATE_tb;
+
+		Assert(NULL != tb);
+		return PointerGetDatum(tb->datagroup[attnum - 1]);
+	}
+	else
+	{
+		/* NOT support so far */
+		Assert(false);
+	}
+
+	return PointerGetDatum(NULL);
+}
+
+
+/* ----------------------------------------------------------------
+ *		VExecEvalNot
+ *		VExecEvalOr
+ *		VExecEvalAnd
+ *
+ * copy from src/backend/executor/execQual.c
+ *
+ *		Evaluate boolean expressions, with appropriate short-circuiting.
+ *
+ *		The query planner reformulates clause expressions in the
+ *		qualification to conjunctive normal form.  If we ever get
+ *		an AND to evaluate, we can be sure that it's not a top-level
+ *		clause in the qualification, but appears lower (as a function
+ *		argument, for example), or in the target list.	Not that you
+ *		need to know this, mind you...
+ * ----------------------------------------------------------------
+ */
+static Datum
+VExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
+			bool *isNull, ExprDoneCond *isDone)
+{
+	ExprState  *clause = linitial(notclause->args);
+	Datum		expr_value;
+	vbool		*ret;
+	int			i;
+
+	if (isDone)
+		*isDone = ExprSingleResult;
+
+	expr_value = ExecEvalExpr(clause, econtext, isNull, NULL);
+
+	ret = (vbool*)DatumGetPointer(expr_value);
+	for(i = 0; i < ret->header.dim; i++)
+	{
+		if(!ret->header.isnull[i])
+			ret->values[i] = !ret->values[i];
+	}
+
+	/*
+	 * evaluation of 'not' is simple.. expr is false, then return 'true' and
+	 * vice versa.
+	 */
+	return PointerGetDatum(ret);
+}
+
+/* ----------------------------------------------------------------
+ *		ExecEvalOr
+ * ----------------------------------------------------------------
+ */
+static Datum
+VExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
+		   bool *isNull, ExprDoneCond *isDone)
+{
+	List	   *clauses = orExpr->args;
+	ListCell   *clause;
+	vbool	*res = NULL;
+	vbool	*next = 	NULL;
+	bool		skip = true;
+	int 		i = 0;
+
+	if (isDone)
+		*isDone = ExprSingleResult;
+
+	/*
+	 * If any of the clauses is TRUE, the OR result is TRUE regardless of the
+	 * states of the rest of the clauses, so we can stop evaluating and return
+	 * TRUE immediately.  If none are TRUE and one or more is NULL, we return
+	 * NULL; otherwise we return FALSE.  This makes sense when you interpret
+	 * NULL as "don't know": if we have a TRUE then the OR is TRUE even if we
+	 * aren't sure about some of the other inputs. If all the known inputs are
+	 * FALSE, but we have one or more "don't knows", then we have to report
+	 * that we "don't know" what the OR's result should be --- perhaps one of
+	 * the "don't knows" would have been TRUE if we'd known its value.  Only
+	 * when all the inputs are known to be FALSE can we state confidently that
+	 * the OR's result is FALSE.
+	 */
+	foreach(clause, clauses)
+	{
+		ExprState  *clausestate = (ExprState *) lfirst(clause);
+		Datum		clause_value;
+
+		/*
+		 * to check if all the values is true, then skip to evaluate some
+		 * expressions
+		 */
+		skip = true;
+
+		clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
+
+		if(NULL == res)
+		{
+			res = DatumGetPointer(clause_value);
+			Assert(NULL != res->header.isnull);
+			for(i = 0; i < res->header.dim; i++)
+			{
+				if(res->header.isnull[i] ||
+					!res->values[i])
+				{
+					skip = false;
+					break;
+				}
+			}
+		}
+		else
+		{
+			next = DatumGetPointer(clause_value);
+			Assert(NULL != res->header.isnull && NULL != next->header.isnull);
+			for(i = 0; i < res->header.dim; i++)
+			{
+				res->header.isnull[i] =
+						(res->header.isnull[i] || next->header.isnull[i]);
+				res->values[i] = (res->values[i] || next->values[i]);
+				if(skip && (res->header.isnull[i] || !res->values[i]))
+					skip = false;
+			}
+		}
+
+		if(skip)
+		{
+			*isNull = false;
+			return PointerGetDatum(res);
+		}
+	}
+
+	*isNull = false;
+	return PointerGetDatum(res);
+}
+
+static Datum
+VExecEvalAndInternal(List* clauses, ExprContext *econtext,
+			bool *isNull, ExprDoneCond *isDone)
+{
+	ListCell   *clause;
+	vbool	*res = NULL;
+	vbool	*next = 	NULL;
+	bool		skip = true;
+	int 		i = 0;
+
+	if (isDone)
+		*isDone = ExprSingleResult;
+
+	/*
+	 * If any of the clauses is FALSE, the AND result is FALSE regardless of
+	 * the states of the rest of the clauses, so we can stop evaluating and
+	 * return FALSE immediately.  If none are FALSE and one or more is NULL,
+	 * we return NULL; otherwise we return TRUE.  This makes sense when you
+	 * interpret NULL as "don't know", using the same sort of reasoning as for
+	 * OR, above.
+	 */
+
+	foreach(clause, clauses)
+	{
+		ExprState  *clausestate = (ExprState *) lfirst(clause);
+		Datum		clause_value;
+
+		/*
+		 * to check if all the values is false, then skip to evaluate some
+		 * expressions
+		 */
+		skip = true;
+
+		clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL);
+
+		if(NULL == res)
+		{
+			res = DatumGetPointer(clause_value);
+			Assert(NULL != res->header.isnull);
+			for(i = 0; i < res->header.dim; i++)
+			{
+				if(res->header.isnull[i] || res->values[i])
+				{
+					skip = false;
+					break;
+				}
+			}
+		}
+		else
+		{
+			next = DatumGetPointer(clause_value);
+			Assert(NULL != res->header.isnull && NULL != next->header.isnull);
+			for(i = 0; i < res->header.dim; i++)
+			{
+				res->header.isnull[i] =
+						(res->header.isnull[i] || next->header.isnull[i]);
+				res->values[i] = (res->values[i] && next->values[i]);
+				if(skip && (res->header.isnull[i] || res->values[i]))
+					skip = false;
+			}
+		}
+
+		if(skip)
+		{
+			*isNull = false;
+			return PointerGetDatum(res);
+		}
+	}
+
+	*isNull = false;
+	return PointerGetDatum(res);
+}
+
+/* ----------------------------------------------------------------
+ *		ExecEvalAnd
+ * ----------------------------------------------------------------
+ */
+static Datum
+VExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
+			bool *isNull, ExprDoneCond *isDone)
+{
+	return VExecEvalAndInternal(andExpr->args, econtext, isNull, isDone);
+}
+
+/*
+ * Init the vectorized expressions
+ */
+ExprState *
+VExecInitExpr(Expr *node, PlanState *parent)
+{
+	ExprState *state = NULL;
+
+	/*
+	 * Because Var is the leaf node of the expression tree, it have to be
+	 * refactored first, otherwise the all call stack should be refactored.
+	 */
+	switch (nodeTag(node))
+	{
+		case T_Var:
+			state = (ExprState *) makeNode(ExprState);
+			state->evalfunc = VExecEvalVar;
+			break;
+		case T_BoolExpr:
+			{
+				BoolExpr   *boolexpr = (BoolExpr *) node;
+				BoolExprState *bstate = makeNode(BoolExprState);
+
+				switch (boolexpr->boolop)
+				{
+					case AND_EXPR:
+						bstate->xprstate.evalfunc = (ExprStateEvalFunc) VExecEvalAnd;
+						break;
+					case OR_EXPR:
+						bstate->xprstate.evalfunc = (ExprStateEvalFunc) VExecEvalOr;
+						break;
+					case NOT_EXPR:
+						bstate->xprstate.evalfunc = (ExprStateEvalFunc) VExecEvalNot;
+						break;
+					default:
+						elog(ERROR, "unrecognized boolop: %d",
+							 (int) boolexpr->boolop);
+						break;
+				}
+				bstate->args = (List *)
+					ExecInitExpr((Expr *) boolexpr->args, parent);
+				state = (ExprState *) bstate;
+			}
+			break;
+
+		/*TODO: More and more expressions should be vectorized */
+		default:
+			break;
+	}
+
+	/* Common code for all state-node types */
+	if(NULL != state)
+		state->expr = node;
+
+	return state;
+}
+
+/* ----------------------------------------------------------------
+ *	copy from src/backend/executor/execQual.c
+ *
+ * NOTE:resultForNull do not used now, we can process it when call the
+ * ExecVQual.
+ * ----------------------------------------------------------------
+ */
+vbool*
+ExecVQual(List *qual, ExprContext *econtext, bool resultForNull)
+{
+	vbool *result;
+	MemoryContext oldContext;
+	bool	 isNull;
+
+	/*
+	 * debugging stuff
+	 */
+	EV_printf("ExecQual: qual is ");
+	EV_nodeDisplay(qual);
+	EV_printf("\n");
+
+	/*
+	 * Run in short-lived per-tuple context while computing expressions.
+	 */
+	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+
+	result = (vbool*)DatumGetPointer(VExecEvalAndInternal(qual, econtext, &isNull, NULL));
+
+	MemoryContextSwitchTo(oldContext);
+
+	return result;
+}
+
+/*
+ * copy from src/backend/executor/ExecQual.c
+ * ExecTargetList
+ *		Evaluates a targetlist with respect to the given
+ *		expression context.  Returns TRUE if we were able to create
+ *		a result, FALSE if we have exhausted a set-valued expression.
+ *
+ * Results are stored into the passed values and isnull arrays.
+ * The caller must provide an itemIsDone array that persists across calls.
+ *
+ * As with ExecEvalExpr, the caller should pass isDone = NULL if not
+ * prepared to deal with sets of result tuples.  Otherwise, a return
+ * of *isDone = ExprMultipleResult signifies a set element, and a return
+ * of *isDone = ExprEndResult signifies end of the set of tuple.
+ */
+static bool
+ExecVTargetList(List *targetlist,
+			   ExprContext *econtext,
+			   TupleTableSlot *slot,
+			   ExprDoneCond *itemIsDone,
+			   ExprDoneCond *isDone)
+{
+	MemoryContext oldContext;
+	ListCell   *tl;
+	TupleBatch tb;
+	bool isnull;
+
+	Assert(NULL != slot);
+
+	tb = (TupleBatch)DatumGetPointer(slot->PRIVATE_tb);
+
+	Assert(NULL != tb);
+
+	tb->ncols = list_length(targetlist);
+
+	/*
+	 * Run in short-lived per-tuple context while computing expressions.
+	 */
+	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+
+	/*
+	 * evaluate all the expressions in the target list
+	 */
+	if (isDone)
+		*isDone = ExprSingleResult;		/* until proven otherwise */
+
+	foreach(tl, targetlist)
+	{
+		GenericExprState *gstate = (GenericExprState *) lfirst(tl);
+		TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
+		AttrNumber	resind = tle->resno - 1;
+
+		tb->datagroup[resind] = ExecEvalExpr(gstate->arg,
+									  econtext,
+									  &isnull,
+									  &itemIsDone[resind]);
+
+		if (itemIsDone[resind] != ExprSingleResult)
+		{
+			/*TODO: DO NOT SUPPORT SO FAR*/
+			elog(ERROR, "Only support single result so far.");
+		}
+	}
+
+	/* Report success */
+	MemoryContextSwitchTo(oldContext);
+
+	return true;
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/contrib/vexecutor/execVQual.h
----------------------------------------------------------------------
diff --git a/contrib/vexecutor/execVQual.h b/contrib/vexecutor/execVQual.h
index fb35789..01113dc 100644
--- a/contrib/vexecutor/execVQual.h
+++ b/contrib/vexecutor/execVQual.h
@@ -31,10 +31,13 @@
 extern TupleTableSlot *
 ExecVProject(ProjectionInfo *projInfo, ExprDoneCond *isDone);
 
-extern bool
-ExecVQual(List *qual, ExprContext *econtext);
+extern vbool*
+ExecVQual(List *qual, ExprContext *econtext, bool resultForNull);
 
 extern bool
 VirtualNodeProc(ScanState* state,TupleTableSlot *slot);
 
+extern ExprState *
+VExecInitExpr(Expr *node, PlanState *parent);
+
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/contrib/vexecutor/execVScan.c
----------------------------------------------------------------------
diff --git a/contrib/vexecutor/execVScan.c b/contrib/vexecutor/execVScan.c
index 8779e14..deb2724 100644
--- a/contrib/vexecutor/execVScan.c
+++ b/contrib/vexecutor/execVScan.c
@@ -69,16 +69,24 @@ TupleTableSlot *ExecTableVScanVirtualLayer(ScanState *scanState)
     VectorizedState* pvs = vs->parent->vectorized;
 
     if(pvs->vectorized)
-        return ExecVScan(scanState,getVScanMethod(scanState->tableType)->accessMethod);
+        return ExecTableVScan(scanState);
     else
     {
         TupleTableSlot* slot = scanState->ps.ps_ProjInfo ? scanState->ps.ps_ResultTupleSlot : scanState->ss_ScanTupleSlot;
-        bool succ = VirtualNodeProc(scanState,slot);
-
-        if(!succ)
+        while(1)
         {
-            slot = ExecTableVScan(scanState);
-            VirtualNodeProc(scanState,slot);
+            bool succ = VirtualNodeProc(scanState,slot);
+
+            if(!succ)
+            {
+                slot = ExecTableVScan(scanState);
+                if(TupIsNull(slot))
+                    break;
+                else
+                    continue;
+            }
+
+            break;
         }
 
         return slot;
@@ -112,6 +120,7 @@ ExecVScan(ScanState *node, ExecScanAccessMtd accessMtd)
     ExprContext *econtext;
     List	   *qual;
     ProjectionInfo *projInfo;
+    vbool *skip = NULL;
 
     /*
      * Fetch data from node
@@ -172,19 +181,35 @@ ExecVScan(ScanState *node, ExecScanAccessMtd accessMtd)
          * when the qual is nil ... saves only a few cycles, but they add up
          * ...
          */
-        if (!qual || ExecQual(qual, econtext, false))
+        if (!qual || (NULL != (skip = ExecVQual(qual, econtext, false))))
         {
             /*
              * Found a satisfactory scan tuple.
              */
             if (projInfo)
             {
+                int i;
+
+                /* first construct the skip array */
+                if(NULL != skip)
+                {
+                    for(i = 0; i < skip->header.dim; i++)
+                    {
+                        skip->values[i] = ((!(skip->values[i])) ||
+                                          (skip->header.isnull[i]) ||
+                                          ((TupleBatch)slot->PRIVATE_tb)->skip[i]);
+                    }
+                }
+
                 /*
                  * Form a projection tuple, store it in the result tuple slot
                  * and return it.
                  */
                 ((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->nrows = ((TupleBatch)slot->PRIVATE_tb)->nrows;
-                ((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->skip = ((TupleBatch)slot->PRIVATE_tb)->skip;
+                if(NULL != skip)
+                    ((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->skip = skip->values;
+                else
+                    ((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->skip = ((TupleBatch)slot->PRIVATE_tb)->skip;
                 return ExecVProject(projInfo, NULL);
             }
             else
@@ -203,4 +228,4 @@ ExecVScan(ScanState *node, ExecScanAccessMtd accessMtd)
         tbReset(node->ss_ScanTupleSlot->PRIVATE_tb);
         tbReset(node->ps.ps_ResultTupleSlot->PRIVATE_tb);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/contrib/vexecutor/vadt.c
----------------------------------------------------------------------
diff --git a/contrib/vexecutor/vadt.c b/contrib/vexecutor/vadt.c
index 4e5b766..1aa486e 100644
--- a/contrib/vexecutor/vadt.c
+++ b/contrib/vexecutor/vadt.c
@@ -138,6 +138,7 @@ v##type##in(PG_FUNCTION_ARGS) \
     SET_VARSIZE(res, (offsetof(v##type, values) + n * sizeof(type))); \
     res->header.elemtype = typeoid; \
     res->header.dim = n; \
+    res->header.isnull = palloc0(sizeof(bool) * n); \
     PG_RETURN_POINTER(res); \
 }
 
@@ -181,29 +182,36 @@ v##type1##v##type2##opstr(PG_FUNCTION_ARGS) \
     int i = 0; \
     v##type1 *arg1 = PG_GETARG_POINTER(0); \
     v##type2 *arg2 = PG_GETARG_POINTER(1); \
-    v##type1 *res = NULL; \
     Assert((arg1)->header.dim == (arg2)->header.dim); \
     size = (arg1)->header.dim; \
     if(sizeof(type1) > sizeof(type2)) \
     { \
-        res = palloc0(offsetof(v##type1, values) + (size) * sizeof(type1)); \
-        SET_VARSIZE(res, (offsetof(v##type1, values) + (size) * sizeof(type1))); \
-        res->header.dim = size;  \
-        res->header.elemtype = arg1->header.elemtype; \
+        v##type1 *res = NULL; \
+        res = (v##type1 *)buildv##type1(size); \
+        while(i < size) \
+        { \
+            res->header.isnull[i] = \
+                arg1->header.isnull[i] || arg2->header.isnull[i]; \
+            if(!res->header.isnull[i]) \
+                res->values[i] = arg1->values[i] opsym arg2->values[i]; \
+            i++; \
+        } \
+        PG_RETURN_POINTER(res); \
     } \
     else \
     { \
-        res = palloc0(offsetof(v##type2, values) + (size) * sizeof(type2)); \
-        SET_VARSIZE(res, (offsetof(v##type2, values) + (size) * sizeof(type2))); \
-        res->header.dim = size;  \
-        res->header.elemtype = arg2->header.elemtype; \
+        v##type2 *res = NULL; \
+        res = (v##type2 *)buildv##type2(size); \
+        while(i < size) \
+        { \
+            res->header.isnull[i] = \
+                arg1->header.isnull[i] || arg2->header.isnull[i]; \
+            if(!res->header.isnull[i]) \
+                res->values[i] = arg1->values[i] opsym arg2->values[i]; \
+            i++; \
+        } \
+        PG_RETURN_POINTER(res); \
     } \
-    while(i < size) \
-    { \
-        res->values[i] = arg1->values[i] opsym arg2->values[i]; \
-        i++; \
-    } \
-    PG_RETURN_POINTER(res); \
 }
 
 /*
@@ -222,13 +230,12 @@ v##type##const_type##opstr(PG_FUNCTION_ARGS) \
     const_type arg2 = CONST_ARG_MACRO(1); \
     v##type *res = NULL; \
     size = (arg1)->header.dim; \
-    res = palloc0(offsetof(v##type, values) + (size) * sizeof(type)); \
-    SET_VARSIZE(res, (offsetof(v##type, values) + (size) * sizeof(type)));  \
-    res->header.elemtype = arg1->header.elemtype; \
-    res->header.dim = arg1->header.dim; \
+    res = (v##type *)buildv##type(size); \
     while(i < size) \
     { \
-        res->values[i] = arg1->values[i] opsym arg2; \
+        res->header.isnull[i] = (arg1)->header.isnull[i]; \
+        if(!res->header.isnull[i]) \
+            res->values[i] = arg1->values[i] opsym arg2; \
         i ++ ;\
     } \
     PG_RETURN_POINTER(res); \
@@ -250,13 +257,13 @@ v##type1##v##type2##cmpstr(PG_FUNCTION_ARGS) \
     v##type2 *arg2 = PG_GETARG_POINTER(1); \
     vbool *res = NULL; \
     size = (arg1)->header.dim; \
-    res = palloc0(offsetof(vbool, values) + (size) * sizeof(bool)); \
-    SET_VARSIZE(res, (offsetof(vbool, values) + (size) * sizeof(bool)));  \
-    res->header.elemtype = BOOLOID; \
-    res->header.dim = arg1->header.dim; \
+    res = (vbool*)buildvbool(size); \
     while(i < size) \
     { \
-        res->values[i] = arg1->values[i] cmpsym arg2->values[i]; \
+         res->header.isnull[i] =  \
+            arg1->header.isnull[i] || arg2->header.isnull[i]; \
+        if(!res->header.isnull[i]) \
+            res->values[i] = arg1->values[i] cmpsym arg2->values[i]; \
         i++; \
     } \
     PG_RETURN_POINTER(res); \
@@ -278,13 +285,12 @@ v##type##const_type##cmpstr(PG_FUNCTION_ARGS) \
     const_type arg2 = CONST_ARG_MACRO(1); \
     vbool *res = NULL; \
     size = (arg1)->header.dim; \
-    res = palloc0(offsetof(vbool, values) + (size) * sizeof(bool)); \
-    SET_VARSIZE(res, (offsetof(vbool, values) + (size) * sizeof(bool)));  \
-    res->header.elemtype = BOOLOID; \
-    res->header.dim = size; \
+    res = (vbool*)buildvbool(size); \
     while(i < size) \
     { \
-        res->values[i] = arg1->values[i] cmpsym arg2; \
+        res->header.isnull[i] = (arg1)->header.isnull[i]; \
+        if(!res->header.isnull[i]) \
+            res->values[i] = arg1->values[i] cmpsym arg2; \
         i++; \
     } \
     PG_RETURN_POINTER(res); \

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/contrib/vexecutor/vexecutor.c
----------------------------------------------------------------------
diff --git a/contrib/vexecutor/vexecutor.c b/contrib/vexecutor/vexecutor.c
index 4533fdd..9f5506f 100644
--- a/contrib/vexecutor/vexecutor.c
+++ b/contrib/vexecutor/vexecutor.c
@@ -26,7 +26,10 @@
 #include "executor/nodeTableScan.h"
 #include "catalog/catquery.h"
 #include "cdb/cdbvars.h"
+#include "utils/memaccounting.h"
 #include "execVScan.h"
+#include "execVQual.h"
+#include "vexecutor.h"
 
 PG_MODULE_MAGIC;
 int BATCHSIZE = 1024;
@@ -35,10 +38,10 @@ static int MAXBATCHSIZE = 4096;
 /*
  * hook function
  */
-static PlanState* VExecInitNode(PlanState *node,EState *eState,int eflags,MemoryAccount* ptr);
+static PlanState* VExecInitNode(Plan *node,EState *eState,int eflags);
+static PlanState* VExecVecNode(PlanState *Node, PlanState *parentNode, EState *eState,int eflags);
 static TupleTableSlot* VExecProcNode(PlanState *node);
 static bool VExecEndNode(PlanState *node);
-static Oid GetNType(Oid vtype);
 extern int currentSliceId;
 
 /*
@@ -51,7 +54,9 @@ _PG_init(void)
 {
 	elog(DEBUG3, "PG INIT VEXECTOR");
 	vmthd.CheckPlanVectorized_Hook = CheckAndReplacePlanVectorized;
+	vmthd.ExecInitExpr_Hook = VExecInitExpr;
 	vmthd.ExecInitNode_Hook = VExecInitNode;
+	vmthd.ExecVecNode_Hook = VExecVecNode;
 	vmthd.ExecProcNode_Hook = VExecProcNode;
 	vmthd.ExecEndNode_Hook = VExecEndNode;
 	vmthd.GetNType = GetNType;
@@ -80,7 +85,9 @@ _PG_fini(void)
 {
 	elog(DEBUG3, "PG FINI VEXECTOR");
 	vmthd.CheckPlanVectorized_Hook = NULL;
+	vmthd.ExecInitExpr_Hook = NULL;
 	vmthd.ExecInitNode_Hook = NULL;
+	vmthd.ExecVecNode_Hook = NULL;
 	vmthd.ExecProcNode_Hook = NULL;
 	vmthd.ExecEndNode_Hook = NULL;
 }
@@ -124,10 +131,24 @@ static void backportTupleDescriptor(PlanState* ps,TupleDesc td)
 	ExecAssignResultType(ps,td);
 }
 
-static PlanState* VExecInitNode(PlanState *node,EState *eState,int eflags,MemoryAccount* curMemoryAccount)
+static PlanState* VExecInitNode(Plan *node,EState *eState,int eflags)
+{
+	elog(DEBUG3, "PG VEXECINIT NODE");
+
+	return NULL;
+}
+
+#define HAS_EXECUTOR_MEMORY_ACCOUNT(planNode, NodeType) \
+	(NULL != planNode->memoryAccount && \
+	MEMORY_OWNER_TYPE_Exec_##NodeType == planNode->memoryAccount->ownerType)
+
+/*
+ * when vectorized_executor_enable is ON, we have to process the plan.
+ */
+static PlanState*
+VExecVecNode(PlanState *node, PlanState *parentNode, EState *eState,int eflags)
 {
 	Plan *plan = node->plan;
-	PlanState *subState = NULL;
 	VectorizedState *vstate = (VectorizedState*)palloc0(sizeof(VectorizedState));
 
 	elog(DEBUG3, "PG VEXECINIT NODE");
@@ -139,22 +160,7 @@ static PlanState* VExecInitNode(PlanState *node,EState *eState,int eflags,Memory
 	node->vectorized = (void*)vstate;
 
 	vstate->vectorized = plan->vectorized;
-
-	/* set the parent state of son */
-	if(innerPlanState(node))
-	{
-		subState = innerPlanState(node);
-		Assert(NULL != subState);
-
-		((VectorizedState*)(subState->vectorized))->parent = node;
-	}
-	if(outerPlanState(node))
-	{
-		subState = outerPlanState(node);
-		Assert(NULL != subState);
-
-		((VectorizedState*)(subState->vectorized))->parent = node;
-	}
+	vstate->parent = parentNode;
 
 	if(Gp_role != GP_ROLE_DISPATCH)
 	{
@@ -163,15 +169,21 @@ static PlanState* VExecInitNode(PlanState *node,EState *eState,int eflags,Memory
 			case T_AppendOnlyScan:
 			case T_ParquetScan:
 			case T_TableScanState:
-				START_MEMORY_ACCOUNT(curMemoryAccount);
-					{
-						TupleDesc td = ((TableScanState *)node)->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
-						((TableScanState *)node)->ss.ss_ScanTupleSlot->PRIVATE_tb = PointerGetDatum(tbGenerate(td->natts,BATCHSIZE));
-						node->ps_ResultTupleSlot->PRIVATE_tb = PointerGetDatum(tbGenerate(td->natts,BATCHSIZE));
-						/* if V->N */
-						backportTupleDescriptor(node,node->ps_ResultTupleSlot->tts_tupleDescriptor);
-					}
-						END_MEMORY_ACCOUNT();
+				if(HAS_EXECUTOR_MEMORY_ACCOUNT(plan, TableScan))
+					START_MEMORY_ACCOUNT(plan->memoryAccount);
+
+				TupleDesc td = ((TableScanState *)node)->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+				((TableScanState *)node)->ss.ss_ScanTupleSlot->PRIVATE_tb = PointerGetDatum(tbGenerate(td->natts,BATCHSIZE));
+				node->ps_ResultTupleSlot->PRIVATE_tb = PointerGetDatum(tbGenerate(td->natts,BATCHSIZE));
+
+				/* if V->N */
+				if( NULL == parentNode ||
+					NULL == parentNode->vectorized ||
+					!((VectorizedState *)parentNode->vectorized)->vectorized)
+					backportTupleDescriptor(node,node->ps_ResultTupleSlot->tts_tupleDescriptor);
+
+				if(HAS_EXECUTOR_MEMORY_ACCOUNT(plan, TableScan))
+					END_MEMORY_ACCOUNT();
 				break;
 			default:
 				((VectorizedState *)node->vectorized)->vectorized = false;
@@ -179,8 +191,15 @@ static PlanState* VExecInitNode(PlanState *node,EState *eState,int eflags,Memory
 		}
 	}
 
+	/* recursively */
+	if(NULL != node->lefttree)
+		VExecVecNode(node->lefttree, node, eState, eflags);
+	if(NULL != node->righttree)
+		VExecVecNode(node->righttree, node, eState, eflags);
+
 	return node;
 }
+
 static TupleTableSlot* VExecProcNode(PlanState *node)
 {
     TupleTableSlot* result = NULL;
@@ -189,7 +208,7 @@ static TupleTableSlot* VExecProcNode(PlanState *node)
         case T_ParquetScanState:
         case T_AppendOnlyScanState:
         case T_TableScanState:
-			result = ExecTableVScanVirtualLayer((TableScanState*)node);
+            result = ExecTableVScanVirtualLayer((TableScanState*)node);
             break;
         default:
             break;
@@ -238,8 +257,8 @@ HasVecExecOprator(NodeTag tag)
 	return result;
 }
 
-static Oid GetNType(Oid vtype)
+Oid GetNType(Oid vtype)
 {
 	const vFuncMap* vf = GetVFunc(vtype);
 	return vf == NULL ? InvalidOid : vf->ntype;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/contrib/vexecutor/vexecutor.h
----------------------------------------------------------------------
diff --git a/contrib/vexecutor/vexecutor.h b/contrib/vexecutor/vexecutor.h
index 490f784..fdc3219 100644
--- a/contrib/vexecutor/vexecutor.h
+++ b/contrib/vexecutor/vexecutor.h
@@ -30,5 +30,6 @@ extern void _PG_init(void);
 extern void _PG_fini(void);
 
 extern bool HasVecExecOprator(NodeTag tag);
+Oid GetNType(Oid vtype);
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/src/backend/executor/execMain.c
----------------------------------------------------------------------
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 6b692a7..81f68f2 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -2047,6 +2047,11 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 	 */
 	planstate = ExecInitNode(plannedstmt->planTree, estate, eflags);
 
+	/* to process the planstate */
+	if(vmthd.vectorized_executor_enable &&
+		NULL != vmthd.ExecVecNode_Hook)
+		planstate = vmthd.ExecVecNode_Hook(planstate, NULL, estate, eflags);
+
 	queryDesc->planstate = planstate;
 
 	Assert(queryDesc->planstate);

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/src/backend/executor/execProcnode.c
----------------------------------------------------------------------
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index 7ee99c6..fa6f657 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -271,6 +271,18 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
 		}
 	}
 
+
+	/*
+    * If the plan node can be vectorized and vectorized is enable, enter the
+    * vectorized execution operators.
+    */
+	if(vmthd.vectorized_executor_enable
+	   && vmthd.ExecInitNode_Hook
+	   && node->vectorized
+	   && (result = vmthd.ExecInitNode_Hook(node,estate,eflags)))
+		return result;
+
+
 	switch (nodeTag(node))
 	{
 			/*
@@ -753,14 +765,6 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
 
 	if (result != NULL)
 	{
-		/*
-        * If the plan node can be vectorized and vectorized is enable, enter the
-        * vectorized execution operators.
-        */
-		if(vmthd.vectorized_executor_enable
-		   && vmthd.ExecInitNode_Hook)
-			result = vmthd.ExecInitNode_Hook(result,estate,eflags,curMemoryAccount);
-
 		SAVE_EXECUTOR_MEMORY_ACCOUNT(result, curMemoryAccount);
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/src/backend/executor/execQual.c
----------------------------------------------------------------------
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index b49b7ec..451e498 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -4516,6 +4516,16 @@ ExecInitExpr(Expr *node, PlanState *parent)
 	/* Guard against stack overflow due to overly complex expressions */
 	check_stack_depth();
 
+	/* Initialize the vectorzied expressions */
+	if( vmthd.vectorized_executor_enable
+		&& vmthd.ExecInitExpr_Hook
+		&& parent->plan->vectorized)
+	{
+		state = vmthd.ExecInitExpr_Hook(node, parent);
+		if(NULL != state)
+			return state;
+	}
+
 	switch (nodeTag(node))
 	{
 		case T_Var:

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/src/include/executor/executor.h
----------------------------------------------------------------------
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 8484d66..b71904f 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -44,7 +44,9 @@
 typedef struct vectorexe_t {
 	bool vectorized_executor_enable;
 	Plan* (*CheckPlanVectorized_Hook)(PlannerInfo *node, Plan *plan);
-	PlanState* (*ExecInitNode_Hook)(PlanState *node,EState *eState,int eflags,MemoryAccount* ptr);
+	ExprState* (*ExecInitExpr_Hook)(Expr *node, PlanState *parent);
+	PlanState* (*ExecInitNode_Hook)(Plan *node, EState *eState,int eflags);
+	PlanState* (*ExecVecNode_Hook)(PlanState *Node, PlanState *parentNode, EState *eState,int eflags);
 	TupleTableSlot* (*ExecProcNode_Hook)(PlanState *node);
 	bool (*ExecEndNode_Hook)(PlanState *node);
 	Oid (*GetNType)(Oid vtype);

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/src/test/feature/vexecutor/ans/.DS_Store
----------------------------------------------------------------------
diff --git a/src/test/feature/vexecutor/ans/.DS_Store b/src/test/feature/vexecutor/ans/.DS_Store
new file mode 100644
index 0000000..2d9613b
Binary files /dev/null and b/src/test/feature/vexecutor/ans/.DS_Store differ

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80eaf448/src/test/feature/vexecutor/ans/projandqual.ans
----------------------------------------------------------------------
diff --git a/src/test/feature/vexecutor/ans/projandqual.ans b/src/test/feature/vexecutor/ans/projandqual.ans
new file mode 100644
index 0000000..52084d5
--- /dev/null
+++ b/src/test/feature/vexecutor/ans/projandqual.ans
@@ -0,0 +1,40 @@
+-- start_ignore
+SET SEARCH_PATH=TestVexecutor_ProjAndQual;
+SET
+-- end_ignore
+select a + b from test1 where a + b > 1020 and b + c > 1;
+ ?column? 
+----------
+     1021
+     1022
+     1023
+     1024
+     1025
+(5 rows)
+
+select a - b from test1 where a - b > 1020 and b - c >= 0;
+ ?column? 
+----------
+     1021
+     1022
+     1023
+(3 rows)
+
+select a * b from test1 where a * b > 1020 and b * c < 10;
+ ?column? 
+----------
+     1021
+     1022
+     1023
+     1024
+(4 rows)
+
+select a / b from test1 where a / b > 1020 and b * c = 1;
+ ?column? 
+----------
+     1021
+     1022
+     1023
+     1024
+(4 rows)
+