hawq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From odiache...@apache.org
Subject [1/2] incubator-hawq git commit: HAWQ-1114. Implement filter-push down for IN on HAWQ bridge side.
Date Wed, 23 Nov 2016 23:11:01 GMT
Repository: incubator-hawq
Updated Branches:
  refs/heads/HAWQ-1114_ [created] 6763adbf3


HAWQ-1114. Implement filter-push down for IN on HAWQ bridge side.


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

Branch: refs/heads/HAWQ-1114_
Commit: ed3376ae30bea8d1c9df45ccd10334356259005d
Parents: 3354de0
Author: Oleksandr Diachenko <odiachenko@pivotal.io>
Authored: Wed Nov 23 15:10:09 2016 -0800
Committer: Oleksandr Diachenko <odiachenko@pivotal.io>
Committed: Wed Nov 23 15:10:09 2016 -0800

----------------------------------------------------------------------
 src/backend/access/external/pxffilters.c        | 533 +++++++++++++++++--
 .../access/external/test/pxffilters_test.c      | 351 ++++++++++--
 src/include/access/pxffilters.h                 |  37 +-
 src/include/catalog/pg_type.h                   |   1 +
 4 files changed, 823 insertions(+), 99 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/ed3376ae/src/backend/access/external/pxffilters.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/pxffilters.c b/src/backend/access/external/pxffilters.c
index 6699b84..f502e4e 100644
--- a/src/backend/access/external/pxffilters.c
+++ b/src/backend/access/external/pxffilters.c
@@ -35,8 +35,13 @@ static List* pxf_make_expression_items_list(List *quals, Node *parent,
int *logi
 static void pxf_free_filter(PxfFilterDesc* filter);
 static char* pxf_serialize_filter_list(List *filters);
 static bool opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter);
+static bool scalar_array_op_expr_to_pxffilter(ScalarArrayOpExpr *expr, PxfFilterDesc *filter);
+static bool var_to_pxffilter(Var *var, PxfFilterDesc *filter);
 static bool supported_filter_type(Oid type);
-static void const_to_str(Const *constval, StringInfo buf);
+static bool supported_operator_type_op_expr(Oid type, PxfFilterDesc *filter);
+static bool supported_operator_type_scalar_array_op_expr(Oid type, PxfFilterDesc *filter,
bool useOr);
+static void scalar_const_to_str(Const *constval, StringInfo buf);
+static void list_const_to_str(Const *constval, StringInfo buf);
 static List* append_attr_from_var(Var* var, List* attrs);
 static void enrich_trivial_expression(List *expressionItems);
 
@@ -46,7 +51,7 @@ static void enrich_trivial_expression(List *expressionItems);
  * down system catalog operators.
  * see pg_operator.h
  */
-dbop_pxfop_map pxf_supported_opr[] =
+dbop_pxfop_map pxf_supported_opr_op_expr[] =
 {
 	/* int2 */
 	{Int2EqualOperator  /* int2eq */, PXFOP_EQ},
@@ -130,7 +135,7 @@ dbop_pxfop_map pxf_supported_opr[] =
 	{1869 /* int82ne */, PXFOP_NE},
 
 	/* date */
-	{DateEqualOperator  /* eq */, PXFOP_EQ},
+	{DateEqualOperator  /* date_eq */, PXFOP_EQ},
 	{1095  /* date_lt */, PXFOP_LT},
 	{1097 /* date_gt */, PXFOP_GT},
 	{1096 /* date_le */, PXFOP_LE},
@@ -159,7 +164,16 @@ dbop_pxfop_map pxf_supported_opr[] =
 	{1060 /* bpchargt */, PXFOP_GT},
 	{1059 /* bpcharle */, PXFOP_LE},
 	{1061 /* bpcharge */, PXFOP_GE},
-	{1057 /* bpcharne */, PXFOP_NE}
+	{1057 /* bpcharne */, PXFOP_NE},
+
+	/* boolean */
+	{BooleanEqualOperator  /* booleq */, PXFOP_EQ},
+	{58  /* boollt */, PXFOP_LT},
+	{59 /* boolgt */, PXFOP_GT},
+	{1694 /* boolle */, PXFOP_LE},
+	{1695 /* boolge */, PXFOP_GE},
+	{85 /* boolne */, PXFOP_NE}
+
 
 	/* bytea */
 	// TODO: uncomment once HAWQ-1085 is done
@@ -172,6 +186,59 @@ dbop_pxfop_map pxf_supported_opr[] =
 
 };
 
+
+dbop_pxfop_array_map pxf_supported_opr_scalar_array_op_expr[] =
+{
+	/* int2 */
+	{Int2EqualOperator  /* int2eq */, PXFOP_IN, true},
+
+	/* int4 */
+	{Int4EqualOperator  /* int4eq */, PXFOP_IN, true},
+
+	/* int8 */
+	{Int8EqualOperator /* int8eq */, PXFOP_IN, true},
+
+	/* text */
+	{TextEqualOperator  /* texteq  */, PXFOP_IN, true},
+
+	/* int2 to int4 */
+	{Int24EqualOperator /* int24eq */, PXFOP_IN, true},
+
+	/* int4 to int2 */
+	{Int42EqualOperator /* int42eq */, PXFOP_IN, true},
+
+	/* int8 to int4 */
+	{Int84EqualOperator /* int84eq */, PXFOP_IN, true},
+
+	/* int4 to int8 */
+	{Int48EqualOperator /* int48eq */, PXFOP_IN, true},
+
+	/* int2 to int8 */
+	{Int28EqualOperator /* int28eq */, PXFOP_IN, true},
+
+	/* int8 to int2 */
+	{Int82EqualOperator /* int82eq */, PXFOP_IN, true},
+
+	/* date */
+	{DateEqualOperator  /* date_eq */, PXFOP_IN, true},
+
+	/* float8 */
+	{Float8EqualOperator  /* float8eq */, PXFOP_IN, true},
+
+	/* float48 */
+	{1120 /* float48eq */, PXFOP_IN, true},
+
+	/* bpchar */
+	{BPCharEqualOperator  /* bpchareq */, PXFOP_IN, true},
+
+	/* boolean */
+	{BooleanEqualOperator  /* booleq */, PXFOP_IN, true},
+
+	/* bytea */
+	// TODO: uncomment once HAWQ-1085 is done
+	//,{ByteaEqualOperator  /* byteaeq */, PXFOP_IN, true},
+};
+
 Oid pxf_supported_types[] =
 {
 	INT2OID,
@@ -186,7 +253,13 @@ Oid pxf_supported_types[] =
 	CHAROID,
 	BOOLOID,
 	DATEOID,
-	TIMESTAMPOID
+	TIMESTAMPOID,
+	/* complex datatypes*/
+	INT2ARRAYOID,
+	INT4ARRAYOID,
+	INT8ARRAYOID,
+	BOOLARRAYOID,
+	TEXTARRAYOID
 };
 
 static void
@@ -247,7 +320,9 @@ pxf_make_expression_items_list(List *quals, Node *parent, int *logicalOpsNum)
 
 		switch (tag)
 		{
+			case T_Var: // IN(single_value)
 			case T_OpExpr:
+			case T_ScalarArrayOpExpr:
 			case T_NullTest:
 			{
 				result = lappend(result, expressionItem);
@@ -273,10 +348,27 @@ pxf_make_expression_items_list(List *quals, Node *parent, int *logicalOpsNum)
 					}
 				}
 
-				for (int i = 0; i < childNodesNum - 1; i++)
+				if (expr->boolop == NOT_EXPR)
 				{
-					result = lappend(result, expressionItem);
+					for (int i = 0; i < childNodesNum; i++)
+					{
+						result = lappend(result, expressionItem);
+					}
+				} else if (expr->boolop == AND_EXPR || expr->boolop == OR_EXPR)
+				{
+					for (int i = 0; i < childNodesNum - 1; i++)
+					{
+						result = lappend(result, expressionItem);
+					}
+				} else
+				{
+					ereport(ERROR,
+						(errcode(ERRCODE_INTERNAL_ERROR),
+						 errmsg("internal error in pxffilters.c:pxf_make_expression_items_list. "
+								 "Found unknown boolean expression type")));
 				}
+
+
 				break;
 			}
 			default:
@@ -363,7 +455,6 @@ pxf_serialize_filter_list(List *expressionItems)
 		return NULL;
 
 	resbuf = makeStringInfo();
-	initStringInfo(resbuf);
 
 	/*
 	 * Iterate through the expression items in the list and serialize them one after the other.
@@ -376,6 +467,46 @@ pxf_serialize_filter_list(List *expressionItems)
 
 		switch (tag)
 		{
+			case T_Var:
+			{
+				elog(DEBUG1, "pxf_serialize_filter_list: node tag %d (T_Var)", tag);
+				PxfFilterDesc *filter = (PxfFilterDesc *) palloc0(sizeof(PxfFilterDesc));
+				Var *var = (Var *) node;
+				if (var_to_pxffilter(var, filter))
+				{
+					PxfOperand l = filter->l;
+					PxfOperand r = filter->r;
+					PxfOperatorCode o = filter->op;
+					if (pxfoperand_is_attr(l) && pxfoperand_is_scalar_const(r))
+					{
+						appendStringInfo(resbuf, "%c%d%c%d%c%lu%c%s",
+												 PXF_ATTR_CODE, l.attnum - 1, /* Java attrs are 0-based */
+												 PXF_SCALAR_CONST_CODE, r.consttype,
+												 PXF_SIZE_BYTES, strlen(r.conststr->data),
+												 PXF_CONST_DATA, (r.conststr)->data);
+					}
+					else
+					{
+						/* var_to_pxffilter() should have never let this happen */
+						ereport(ERROR,
+								(errcode(ERRCODE_INTERNAL_ERROR),
+								 errmsg("internal error in pxffilters.c:pxf_serialize_"
+										 "filter_list. Found a non const+attr filter")));
+					}
+					appendStringInfo(resbuf, "%c%d", PXF_OPERATOR_CODE, o);
+					pxf_free_filter(filter);
+
+				}
+				else
+				{
+					/* if at least one expression item is not supported, whole filter doesn't make sense*/
+					elog(DEBUG1, "Query will not be optimized to use filter push-down.");
+					pfree(filter);
+					pfree(resbuf->data);
+					return NULL;
+				}
+				break;
+			}
 			case T_OpExpr:
 			{
 				elog(DEBUG1, "pxf_serialize_filter_list: node tag %d (T_OpExpr)", tag);
@@ -386,18 +517,18 @@ pxf_serialize_filter_list(List *expressionItems)
 					PxfOperand l = filter->l;
 					PxfOperand r = filter->r;
 					PxfOperatorCode o = filter->op;
-					if (pxfoperand_is_attr(l) && pxfoperand_is_const(r))
+					if (pxfoperand_is_attr(l) && pxfoperand_is_scalar_const(r))
 					{
 						appendStringInfo(resbuf, "%c%d%c%d%c%lu%c%s",
 												 PXF_ATTR_CODE, l.attnum - 1, /* Java attrs are 0-based */
-												 PXF_CONST_CODE, r.consttype,
+												 PXF_SCALAR_CONST_CODE, r.consttype,
 												 PXF_SIZE_BYTES, strlen(r.conststr->data),
 												 PXF_CONST_DATA, (r.conststr)->data);
 					}
-					else if (pxfoperand_is_const(l) && pxfoperand_is_attr(r))
+					else if (pxfoperand_is_scalar_const(l) && pxfoperand_is_attr(r))
 					{
 						appendStringInfo(resbuf, "%c%d%c%lu%c%s%c%d",
-												 PXF_CONST_CODE, l.consttype,
+												 PXF_SCALAR_CONST_CODE, l.consttype,
 												 PXF_SIZE_BYTES, strlen(l.conststr->data),
 												 PXF_CONST_DATA, (l.conststr)->data,
 												 PXF_ATTR_CODE, r.attnum - 1); /* Java attrs are 0-based */
@@ -421,6 +552,49 @@ pxf_serialize_filter_list(List *expressionItems)
 				}
 				break;
 			}
+			case T_ScalarArrayOpExpr:
+			{
+				elog(DEBUG1, "pxf_serialize_filter_list: node tag %d (T_ScalarArrayOpExpr)", tag);
+				ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
+				PxfFilterDesc *filter = (PxfFilterDesc *) palloc0(sizeof(PxfFilterDesc));
+				if (scalar_array_op_expr_to_pxffilter(expr, filter))
+				{
+					PxfOperand l = filter->l;
+					PxfOperand r = filter->r;
+					PxfOperatorCode o = filter->op;
+					if (pxfoperand_is_attr(l) && pxfoperand_is_list_const(r))
+					{
+						appendStringInfo(resbuf, "%c%d%c%d%s",
+												 PXF_ATTR_CODE, l.attnum - 1, /* Java attrs are 0-based */
+												 PXF_LIST_CONST_CODE, r.consttype,
+												 r.conststr->data);
+					}
+					else if (pxfoperand_is_list_const(l) && pxfoperand_is_attr(r))
+					{
+						appendStringInfo(resbuf, "%c%d%s%c%d",
+												 PXF_SCALAR_CONST_CODE, l.consttype,
+												 l.conststr->data,
+												 PXF_ATTR_CODE, r.attnum - 1); /* Java attrs are 0-based */
+					}
+					else
+					{
+						/* scalararrayopexpr_to_pxffilter() should have never let this happen */
+						ereport(ERROR,
+								(errcode(ERRCODE_INTERNAL_ERROR),
+								 errmsg("internal error in pxffilters.c:pxf_serialize_"
+										 "filter_list. Found a non const+attr filter")));
+					}
+					appendStringInfo(resbuf, "%c%d", PXF_OPERATOR_CODE, o);
+					pxf_free_filter(filter);
+				} else {
+					/* if at least one expression item is not supported, whole filter doesn't make sense*/
+					elog(DEBUG1, "Query will not be optimized to use filter push-down.");
+					pfree(filter);
+					pfree(resbuf->data);
+					return NULL;
+				}
+				break;
+			}
 			case T_BoolExpr:
 			{
 				BoolExpr *expr = (BoolExpr *) node;
@@ -486,8 +660,6 @@ pxf_serialize_filter_list(List *expressionItems)
 static bool
 opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter)
 {
-	int		 i;
-	int		 nargs 		= sizeof(pxf_supported_opr) / sizeof(dbop_pxfop_map);
 	Node	*leftop 	= NULL;
 	Node	*rightop	= NULL;
 	Oid		 rightop_type = InvalidOid;
@@ -521,6 +693,12 @@ opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter)
 	if (!supported_filter_type(rightop_type) || !supported_filter_type(leftop_type))
 		return false;
 
+	/*
+	 * check if supported operator -
+	 */
+	if (!supported_operator_type_op_expr(expr->opno, filter))
+		return false;
+
 	/* arguments must be VAR and CONST */
 	if (IsA(leftop,  Var) && IsA(rightop, Const))
 	{
@@ -530,20 +708,18 @@ opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter)
 		if (filter->l.attnum <= InvalidAttrNumber)
 			return false; /* system attr not supported */
 
-		filter->r.opcode = PXF_CONST_CODE;
+		filter->r.opcode = PXF_SCALAR_CONST_CODE;
 		filter->r.attnum = InvalidAttrNumber;
 		filter->r.conststr = makeStringInfo();
-		initStringInfo(filter->r.conststr);
-		const_to_str((Const *)rightop, filter->r.conststr);
+		scalar_const_to_str((Const *)rightop, filter->r.conststr);
 		filter->r.consttype = ((Const *)rightop)->consttype;
 	}
 	else if (IsA(leftop, Const) && IsA(rightop, Var))
 	{
-		filter->l.opcode = PXF_CONST_CODE;
+		filter->l.opcode = PXF_SCALAR_CONST_CODE;
 		filter->l.attnum = InvalidAttrNumber;
 		filter->l.conststr = makeStringInfo();
-		initStringInfo(filter->l.conststr);
-		const_to_str((Const *)leftop, filter->l.conststr);
+		scalar_const_to_str((Const *)leftop, filter->l.conststr);
 		filter->l.consttype = ((Const *)leftop)->consttype;
 
 		filter->r.opcode = PXF_ATTR_CODE;
@@ -558,23 +734,110 @@ opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter)
 		return false;
 	}
 
-	/* is operator supported? if so, set the corresponding PXFOP */
-	for (i = 0; i < nargs; i++)
+	return true;
+}
+
+static bool
+scalar_array_op_expr_to_pxffilter(ScalarArrayOpExpr *expr, PxfFilterDesc *filter)
+{
+
+	Node	*leftop 	= NULL;
+	Node	*rightop	= NULL;
+
+	leftop = (Node *) linitial(expr->args);
+	rightop = (Node *) lsecond(expr->args);
+	Oid		 leftop_type = exprType(leftop);
+	Oid		 rightop_type = exprType(rightop);
+
+	/*
+	 * check if supported type -
+	 */
+	if (!supported_filter_type(rightop_type) || !supported_filter_type(leftop_type))
+		return false;
+
+	/*
+	 * check if supported operator -
+	 */
+	if(!supported_operator_type_scalar_array_op_expr(expr->opno, filter, expr->useOr))
+		return false;
+
+	if (IsA(leftop, Var) && IsA(rightop, Const))
 	{
-		/* NOTE: switch to hash table lookup if   */
-		/* array grows. for now it's cheap enough */
-		if(expr->opno == pxf_supported_opr[i].dbop)
-		{
-			filter->op = pxf_supported_opr[i].pxfop;
-			return true; /* filter qualifies! */
-		}
+		filter->l.opcode = PXF_ATTR_CODE;
+		filter->l.attnum = ((Var *) leftop)->varattno;
+		filter->l.consttype = InvalidOid;
+		if (filter->l.attnum <= InvalidAttrNumber)
+			return false; /* system attr not supported */
+
+		filter->r.opcode = PXF_LIST_CONST_CODE;
+		filter->r.attnum = InvalidAttrNumber;
+		filter->r.conststr = makeStringInfo();
+		list_const_to_str((Const *)rightop, filter->r.conststr);
+		filter->r.consttype = ((Const *)rightop)->consttype;
+	}
+	else if (IsA(leftop, Const) && IsA(rightop, Var))
+	{
+		filter->l.opcode = PXF_LIST_CONST_CODE;
+		filter->l.attnum = InvalidAttrNumber;
+		filter->l.conststr = makeStringInfo();
+		list_const_to_str((Const *)leftop, filter->l.conststr);
+		filter->l.consttype = ((Const *)leftop)->consttype;
+
+		filter->r.opcode = PXF_ATTR_CODE;
+		filter->r.attnum = ((Var *) rightop)->varattno;
+		filter->r.consttype = InvalidOid;
+		if (filter->r.attnum <= InvalidAttrNumber)
+			return false; /* system attr not supported */
+	}
+	else
+	{
+		elog(DEBUG1, "pxf_serialize_filter_list: expression is not a Var+Const");
+		return false;
 	}
 
-	elog(DEBUG1, "opexpr_to_pxffilter: operator is not supported, operator code: %d", expr->opno);
 
-	/* NOTE: if more validation needed, add it before the operators test
-	 * or alternatively change it to use a false flag and return true below */
-	return false;
+
+	return true;
+}
+
+static bool
+var_to_pxffilter(Var *var, PxfFilterDesc *filter)
+{
+	Oid var_type = InvalidOid;
+
+	if ((!var) || (!filter))
+		return false;
+
+	var_type = exprType((Node *)var);
+
+	/*
+	 * check if supported type -
+	 */
+	if (!supported_filter_type(var_type))
+		return false;
+
+	/* arguments must be VAR and CONST */
+	if (IsA(var,  Var))
+	{
+		filter->l.opcode = PXF_ATTR_CODE;
+		filter->l.attnum = var->varattno;
+		filter->l.consttype = InvalidOid;
+		if (filter->l.attnum <= InvalidAttrNumber)
+			return false; /* system attr not supported */
+
+		filter->r.opcode = PXF_SCALAR_CONST_CODE;
+		filter->r.attnum = InvalidAttrNumber;
+		filter->r.conststr = makeStringInfo();
+		appendStringInfo(filter->r.conststr, TrueConstValue);
+		filter->r.consttype = BOOLOID;
+	}
+	else
+	{
+		elog(DEBUG1, "var_to_pxffilter: expression is not a Var");
+		return false;
+	}
+
+	return true;
 }
 
 static List*
@@ -661,6 +924,55 @@ supported_filter_type(Oid type)
 	return false;
 }
 
+
+static bool
+supported_operator_type_op_expr(Oid type, PxfFilterDesc *filter)
+{
+
+	int nargs = sizeof(pxf_supported_opr_op_expr) / sizeof(dbop_pxfop_map);
+	int i;
+	/* is operator supported? if so, set the corresponding PXFOP */
+	for (i = 0; i < nargs; i++)
+	{
+		/* NOTE: switch to hash table lookup if   */
+		/* array grows. for now it's cheap enough */
+		if(type == pxf_supported_opr_op_expr[i].dbop)
+		{
+			filter->op = pxf_supported_opr_op_expr[i].pxfop;
+			return true; /* filter qualifies! */
+		}
+	}
+
+		elog(DEBUG1, "opexpr_to_pxffilter: operator is not supported, operator code: %d", type);
+
+		return false;
+}
+
+static bool
+supported_operator_type_scalar_array_op_expr(Oid type, PxfFilterDesc *filter, bool useOr)
+{
+
+	int nargs = sizeof(pxf_supported_opr_scalar_array_op_expr) / sizeof(dbop_pxfop_array_map);
+	int i;
+	/* is operator supported? if so, set the corresponding PXFOP */
+	for (i = 0; i < nargs; i++)
+	{
+		/* NOTE: switch to hash table lookup if   */
+		/* array grows. for now it's cheap enough */
+		if(useOr == pxf_supported_opr_scalar_array_op_expr[i].useOr && type == pxf_supported_opr_scalar_array_op_expr[i].dbop)
+		{
+			filter->op = pxf_supported_opr_scalar_array_op_expr[i].pxfop;
+			return true; /* filter qualifies! */
+		}
+	}
+
+		elog(DEBUG1, "supported_operator_type_scalar_array_op_expr: operator is not supported,
operator code: %d", type);
+
+		return false;
+}
+
+
+
 /*
  * const_to_str
  *
@@ -668,7 +980,7 @@ supported_filter_type(Oid type)
  * type is text based, make sure to escape the value with surrounding quotes.
  */
 static void
-const_to_str(Const *constval, StringInfo buf)
+scalar_const_to_str(Const *constval, StringInfo buf)
 {
 	Oid			typoutput;
 	bool		typIsVarlena;
@@ -677,7 +989,7 @@ const_to_str(Const *constval, StringInfo buf)
 	if (constval->constisnull)
 	{
 		/* TODO: test this edge case and its consequences */
-		appendStringInfo(buf, "\"NULL\"");
+		appendStringInfo(buf, NullConstValue);
 		return;
 	}
 
@@ -703,19 +1015,17 @@ const_to_str(Const *constval, StringInfo buf)
 		case TIMESTAMPOID:
 			appendStringInfo(buf, "%s", extval);
 			break;
-
 		case BOOLOID:
 			if (strcmp(extval, "t") == 0)
-				appendStringInfo(buf, "true");
+				appendStringInfo(buf, TrueConstValue);
 			else
-				appendStringInfo(buf, "false");
+				appendStringInfo(buf, FalseConstValue);
 			break;
-
 		default:
 			/* should never happen. we filter on types earlier */
 			ereport(ERROR,
 					(errcode(ERRCODE_INTERNAL_ERROR),
-					 errmsg("internal error in pxffilters.c:const_to_str. "
+					 errmsg("internal error in pxffilters.c:scalar_const_to_str. "
 							"Using unsupported data type (%d) (value %s)",
 							constval->consttype, extval)));
 
@@ -726,6 +1036,149 @@ const_to_str(Const *constval, StringInfo buf)
 
 
 /*
+ * list_const_to_str
+ *
+ * Extracts the value stored in a list constant to a string.
+ * Currently supported data types: int2[], int4[], int8[], text[], boolean[]
+ * Example:
+ * Input: ['abc', 'xyz']
+ * Output: s3dabcs3dxyz
+ *
+ */
+static void
+list_const_to_str(Const *constval, StringInfo buf)
+{
+	StringInfo	interm_buf;
+	Datum *dats;
+	ArrayType  *arr;
+	int len;
+
+	if (constval->constisnull)
+	{
+		elog(DEBUG1, "Null constant is not expected in this context.");
+		return;
+	}
+
+	if (constval->constbyval) {
+		elog(DEBUG1, "Constant passed by value is not expected in this context.");
+		return;
+	}
+
+	arr = DatumGetArrayTypeP(constval->constvalue);
+
+	interm_buf = makeStringInfo();
+
+	switch (constval->consttype)
+	{
+		case INT2ARRAYOID:
+		{
+			int16 value;
+			deconstruct_array(arr, INT2OID, sizeof (value), true, 's', &dats, NULL, &len);
+
+			for (int i = 0; i < len; i++)
+			{
+				value = DatumGetInt16(dats[i]);
+
+				appendStringInfo(interm_buf, "%hd", value);
+
+				appendStringInfo(buf, "%c%d%c%s",
+						PXF_SIZE_BYTES, interm_buf->len,
+						PXF_CONST_DATA, interm_buf->data);
+				resetStringInfo(interm_buf);
+			}
+			break;
+		}
+		case INT4ARRAYOID:
+		{
+			int32 value;
+			deconstruct_array(arr, INT4OID, sizeof (value), true, 'i', &dats, NULL, &len);
+
+			for (int i = 0; i < len; i++)
+			{
+				value = DatumGetInt32(dats[i]);
+
+				appendStringInfo(interm_buf, "%d", value);
+
+				appendStringInfo(buf, "%c%d%c%s",
+						PXF_SIZE_BYTES, interm_buf->len,
+						PXF_CONST_DATA, interm_buf->data);
+				resetStringInfo(interm_buf);
+			}
+			break;
+		}
+		case INT8ARRAYOID:
+		{
+			int64 value;
+			deconstruct_array(arr, INT8OID, sizeof (value), true, 'd', &dats, NULL, &len);
+
+			for (int i = 0; i < len; i++)
+			{
+				value = DatumGetInt64(dats[i]);
+
+				appendStringInfo(interm_buf, "%ld", value);
+
+				appendStringInfo(buf, "%c%d%c%s",
+						PXF_SIZE_BYTES, interm_buf->len,
+						PXF_CONST_DATA, interm_buf->data);
+				resetStringInfo(interm_buf);
+			}
+			break;
+		}
+		case TEXTARRAYOID:
+		{
+			char *value;
+
+			deconstruct_array(arr, TEXTOID, -1, false, 'i', &dats, NULL, &len);
+
+			for (int i = 0; i < len; i++)
+			{
+				value = DatumGetCString(DirectFunctionCall1(textout, dats[i]));
+
+				appendStringInfo(interm_buf, "%s", value);
+
+				appendStringInfo(buf, "%c%d%c%s",
+						PXF_SIZE_BYTES, interm_buf->len,
+						PXF_CONST_DATA, interm_buf->data);
+				resetStringInfo(interm_buf);
+			}
+			break;
+		}
+		case BOOLARRAYOID:
+		{
+			bool value;
+			deconstruct_array(arr, BOOLOID, sizeof (value), false, 'c', &dats, NULL, &len);
+
+			for (int i = 0; i < len; i++)
+			{
+				value = DatumGetBool(dats[i]);
+				if (value)
+					appendStringInfo(buf, "%c%lu%c%s",
+							PXF_SIZE_BYTES, strlen(TrueConstValue),
+							PXF_CONST_DATA, TrueConstValue);
+				else
+				{
+					appendStringInfo(buf, "%c%lu%c%s",
+							PXF_SIZE_BYTES, strlen(FalseConstValue),
+							PXF_CONST_DATA, FalseConstValue);
+				}
+			}
+			break;
+		}
+		default:
+			/* should never happen. we filter on types earlier */
+			ereport(ERROR,
+					(errcode(ERRCODE_INTERNAL_ERROR),
+					 errmsg("internal error in pxffilters.c:list_const_to_str. "
+							"Using unsupported data type (%d)",
+							constval->consttype)));
+
+	}
+
+	pfree(interm_buf->data);
+}
+
+
+/*
  * serializePxfFilterQuals
  *
  * Wrapper around pxf_make_filter_list -> pxf_serialize_filter_list.

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/ed3376ae/src/backend/access/external/test/pxffilters_test.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test/pxffilters_test.c b/src/backend/access/external/test/pxffilters_test.c
index 0e45eee..5d38e04 100644
--- a/src/backend/access/external/test/pxffilters_test.c
+++ b/src/backend/access/external/test/pxffilters_test.c
@@ -25,8 +25,10 @@
 #include "c.h"
 #include "../pxffilters.c"
 
-void run__const_to_str(Const* input, StringInfo result, char* expected);
-void run__const_to_str__negative(Const* input, StringInfo result, char* value);
+void run__scalar_const_to_str(Const* input, StringInfo result, char* expected);
+void run__scalar_const_to_str__negative(Const* input, StringInfo result, char* value);
+void run__list_const_to_str(Const* input, StringInfo result, char* expected);
+void run__list_const_to_str__negative(Const* input, StringInfo result, int len, Datum *dats);
 
 void
 test__supported_filter_type(void **state)
@@ -64,7 +66,7 @@ test__supported_filter_type(void **state)
 
 	/* go over pxf_supported_types array */
 	int nargs = sizeof(pxf_supported_types) / sizeof(Oid);
-	assert_int_equal(nargs, 13);
+	assert_int_equal(nargs, 18);
 	for (i = 0; i < nargs; ++i)
 	{
 		assert_true(supported_filter_type(pxf_supported_types[i]));
@@ -72,11 +74,109 @@ test__supported_filter_type(void **state)
 
 }
 
+void
+test__supported_operator_type_op_expr(void **state)
+{
+	Oid operator_oids[13][2] = {
+			{ Int2EqualOperator, PXFOP_EQ },
+			{ 95, PXFOP_LT },
+			{ 520, PXFOP_GT },
+			{ 522, PXFOP_LE },
+			{ 524, PXFOP_GE },
+			{ 519, PXFOP_NE },
+			{ Int4EqualOperator, PXFOP_EQ },
+			{ 97, PXFOP_LT },
+			{ 521, PXFOP_GT },
+			{ 523, PXFOP_LE },
+			{ 525, PXFOP_GE },
+			{ 518, PXFOP_NE },
+			{ InvalidOid, InvalidOid }
+	};
+
+	PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+
+	int array_size = sizeof(operator_oids) / sizeof(operator_oids[0]);
+	bool result = false;
+	int i = 0;
+
+	/* supported types */
+	for (; i < array_size-1; ++i)
+	{
+		result = supported_operator_type_op_expr(operator_oids[i][0], filter);
+		assert_true(result);
+		assert_true(operator_oids[i][1] == filter->op);
+	}
+
+	/* unsupported type */
+	result = supported_operator_type_op_expr(operator_oids[i][0], filter);
+	assert_false(result);
+
+	/* go over pxf_supported_opr_op_expr array */
+	int nargs = sizeof(pxf_supported_opr_op_expr) / sizeof(dbop_pxfop_map);
+	assert_int_equal(nargs, 91);
+	for (i = 0; i < nargs; ++i)
+	{
+		assert_true(supported_operator_type_op_expr(pxf_supported_opr_op_expr[i].dbop, filter));
+		assert_true(pxf_supported_opr_op_expr[i].pxfop == filter->op);
+	}
+
+}
+
+void
+test__supported_operator_type_scalar_array_op_expr(void **state)
+{
+	Oid operator_oids[15][2] = {
+			{Int2EqualOperator, PXFOP_IN},
+			{Int4EqualOperator, PXFOP_IN},
+			{Int8EqualOperator, PXFOP_IN},
+			{TextEqualOperator, PXFOP_IN},
+			{Int24EqualOperator, PXFOP_IN},
+			{Int42EqualOperator, PXFOP_IN},
+			{Int84EqualOperator, PXFOP_IN},
+			{Int48EqualOperator, PXFOP_IN},
+			{Int28EqualOperator, PXFOP_IN},
+			{Int82EqualOperator, PXFOP_IN},
+			{DateEqualOperator, PXFOP_IN},
+			{Float8EqualOperator, PXFOP_IN},
+			{1120 , PXFOP_IN},
+			{BPCharEqualOperator, PXFOP_IN},
+			{BooleanEqualOperator, PXFOP_IN},
+	};
+
+	PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+
+	int array_size = sizeof(operator_oids) / sizeof(operator_oids[0]);
+	bool result = false;
+	int i = 0;
+
+	/* supported types */
+	for (; i < array_size-1; ++i)
+	{
+		result = supported_operator_type_scalar_array_op_expr(operator_oids[i][0], filter, true);
+		assert_true(result);
+		assert_true(operator_oids[i][1] == filter->op);
+	}
+
+	/* unsupported type */
+	result = supported_operator_type_op_expr(InvalidOid, filter);
+	assert_false(result);
+
+	/* go over pxf_supported_opr_scalar_array_op_expr array */
+	int nargs = sizeof(pxf_supported_opr_scalar_array_op_expr) / sizeof(dbop_pxfop_array_map);
+	assert_int_equal(nargs, 15);
+	for (i = 0; i < nargs; ++i)
+	{
+		assert_true(supported_operator_type_scalar_array_op_expr(pxf_supported_opr_op_expr[i].dbop,
filter, pxf_supported_opr_scalar_array_op_expr[i].useOr));
+		assert_true(pxf_supported_opr_scalar_array_op_expr[i].pxfop == filter->op);
+	}
+
+}
+
 /*
- * const_value must be palloc'ed, it will be freed by const_to_str
+ * const_value must be palloc'ed, it will be freed by scalar_const_to_str
  */
 void
-mock__const_to_str(Oid const_type, char* const_value)
+mock__scalar_const_to_str(Oid const_type, char* const_value)
 {
 	expect_value(getTypeOutputInfo, type, const_type);
 	expect_any(getTypeOutputInfo, typOutput);
@@ -88,8 +188,41 @@ mock__const_to_str(Oid const_type, char* const_value)
 	will_return(OidOutputFunctionCall, const_value);
 }
 
+
+/*
+ * const_value must be palloc'ed, it will be freed by list_const_to_str
+ */
+void
+mock__list_const_to_str(Oid const_type, int len, Datum *dats) {
+
+	expect_any(pg_detoast_datum, datum);
+	will_return(pg_detoast_datum, NULL);
+
+	expect_any(deconstruct_array, array);
+	expect_any(deconstruct_array, elmtype);
+	expect_any(deconstruct_array, elmlen);
+	expect_any(deconstruct_array, elmbyval);
+	expect_any(deconstruct_array, elmalign);
+	expect_any(deconstruct_array, elemsp);
+	expect_any(deconstruct_array, nullsp);
+	expect_any(deconstruct_array, nelemsp);
+	will_return(deconstruct_array, NULL);
+	will_assign_value(deconstruct_array, nelemsp, len);
+	will_assign_value(deconstruct_array, elemsp, dats);
+
+	if (const_type == TEXTARRAYOID)
+	{
+		for (int i = 0; i < len; i++)
+		{
+			expect_any(DirectFunctionCall1, func);
+			expect_any(DirectFunctionCall1, arg1);
+			will_return(DirectFunctionCall1, dats[i]);
+		}
+	}
+}
+
 void
-verify__const_to_str(bool is_null, char* const_value, Oid const_type, char* expected)
+verify__scalar_const_to_str(bool is_null, char* const_value, Oid const_type, char* expected)
 {
 	StringInfo result = makeStringInfo();
 	char* value = NULL;
@@ -100,20 +233,20 @@ verify__const_to_str(bool is_null, char* const_value, Oid const_type,
char* expe
 	/* need to prepare inner functions */
 	if (!is_null)
 	{
-		value = strdup(const_value); /* will be free'd by const_to_str */
+		value = strdup(const_value); /* will be free'd by scalar_const_to_str */
 
-		mock__const_to_str(const_type, value);
+		mock__scalar_const_to_str(const_type, value);
 	}
 
 	/* no expected value means it's a negative test */
 	if (expected)
 	{
-		run__const_to_str(input, result, expected);
+		run__scalar_const_to_str(input, result, expected);
 	}
 	else
 	{
-		run__const_to_str__negative(input, result, value);
-		pfree(value); /* value was not freed by const_to_str b/c of failure */
+		run__scalar_const_to_str__negative(input, result, value);
+		pfree(value); /* value was not freed by scalar_const_to_str b/c of failure */
 	}
 
 	pfree(result->data);
@@ -121,25 +254,135 @@ verify__const_to_str(bool is_null, char* const_value, Oid const_type,
char* expe
 	pfree(input);
 }
 
-void run__const_to_str(Const* input, StringInfo result, char* expected)
+void
+verify__list_const_to_str(Oid const_type, char* expected, int len, Datum *dats)
 {
-	const_to_str(input, result);
+	StringInfo result = makeStringInfo();
+	Const* input = (Const*) palloc0(sizeof(Const));
+	input->constisnull = false;
+	input->consttype = const_type;
+
+	/* need to prepare inner functions */
+	mock__list_const_to_str(const_type, len, dats);
+
+	/* no expected value means it's a negative test */
+	if (expected)
+	{
+		run__list_const_to_str(input, result, expected);
+	}
+	else
+	{
+		run__list_const_to_str__negative(input, result, len, dats);
+	}
+
+	pfree(result->data);
+	pfree(result);
+	pfree(input);
+}
+
+void
+test__list_const_to_str__int(void **state) {
+
+	Datum dats8[3] = {Int8GetDatum(1), Int8GetDatum(2), Int8GetDatum(3)};
+
+	verify__list_const_to_str(INT2ARRAYOID, "s1d1s1d2s1d3", 3, dats8);
+
+	Datum dats16[1] = {Int16GetDatum(42)};
+	verify__list_const_to_str(INT4ARRAYOID, "s2d42", 1, dats16);
+
+	Datum dats32[2] = {Int32GetDatum(11), Int32GetDatum(22)};
+	verify__list_const_to_str(INT4ARRAYOID, "s2d11s2d22", 2, dats32);
+}
+
+
+void
+test__list_const_to_str__boolean(void **state)
+{
+	Datum dats1[2] = {BoolGetDatum(true), BoolGetDatum(false)};
+	verify__list_const_to_str(BOOLARRAYOID, "s4dtrues5dfalse", 2, dats1);
+
+	Datum dats2[2] = {BoolGetDatum(false), BoolGetDatum(true)};
+	verify__list_const_to_str(BOOLARRAYOID, "s5dfalses4dtrue", 2, dats2);
+
+	Datum dats3[1] = {BoolGetDatum(true)};
+	verify__list_const_to_str(BOOLARRAYOID, "s4dtrue", 1, dats3);
+
+	Datum dats4[1] = {BoolGetDatum(false)};
+	verify__list_const_to_str(BOOLARRAYOID, "s5dfalse", 1, dats4);
+}
+
+void
+test__list_const_to_str__text(void **state)
+{
+
+	Datum dats1[2] = {CStringGetDatum("row1"), CStringGetDatum("row2")};
+	verify__list_const_to_str(TEXTARRAYOID, "s4drow1s4drow2", 2, dats1);
+
+	Datum dats2[3] = {CStringGetDatum("r,o,w,1"), CStringGetDatum("r'o'w2"), CStringGetDatum("r\"o\"w3")};
+	verify__list_const_to_str(TEXTARRAYOID, "s7dr,o,w,1s6dr'o'w2s6dr\"o\"w3", 3, dats2);
+}
+
+void run__scalar_const_to_str(Const* input, StringInfo result, char* expected)
+{
+	scalar_const_to_str(input, result);
 	assert_string_equal(result->data, expected);
 }
 
-void run__const_to_str__negative(Const* input, StringInfo result, char* value)
+void run__scalar_const_to_str__negative(Const* input, StringInfo result, char* value)
 {
 
 	StringInfo err_msg = makeStringInfo();
 	appendStringInfo(err_msg,
-			"internal error in pxffilters.c:const_to_str. "
+			"internal error in pxffilters.c:scalar_const_to_str. "
 			"Using unsupported data type (%d) (value %s)", input->consttype, value);
 
 	/* Setting the test -- code omitted -- */
 	PG_TRY();
 	{
 		/* This will throw a ereport(ERROR).*/
-		const_to_str(input, result);
+		scalar_const_to_str(input, result);
+	}
+	PG_CATCH();
+	{
+		CurrentMemoryContext = 1;
+		ErrorData *edata = CopyErrorData();
+
+		/* Validate the type of expected error */
+		assert_true(edata->sqlerrcode == ERRCODE_INTERNAL_ERROR);
+		assert_true(edata->elevel == ERROR);
+		assert_string_equal(edata->message, err_msg->data);
+
+		pfree(err_msg->data);
+		pfree(err_msg);
+
+		return;
+	}
+	PG_END_TRY();
+
+	assert_true(false);
+}
+
+
+
+void run__list_const_to_str(Const* input, StringInfo result, char* expected)
+{
+	list_const_to_str(input, result);
+	assert_string_equal(result->data, expected);
+}
+
+void run__list_const_to_str__negative(Const* input, StringInfo result, int len, Datum *dats)
+{
+
+	StringInfo err_msg = makeStringInfo();
+	appendStringInfo(err_msg,
+			"internal error in pxffilters.c:list_const_to_str. "
+			"Using unsupported data type (%d) (len %d)", input->consttype, len);
+
+	/* Setting the test -- code omitted -- */
+	PG_TRY();
+	{
+		/* This will throw a ereport(ERROR).*/
+		list_const_to_str(input, result);
 	}
 	PG_CATCH();
 	{
@@ -163,46 +406,48 @@ void run__const_to_str__negative(Const* input, StringInfo result, char*
value)
 
 
 void
-test__const_to_str__null(void **state)
+test__scalar_const_to_str__null(void **state)
 {
-	verify__const_to_str(true, NULL, 1, "\"NULL\"");
+	verify__scalar_const_to_str(true, NULL, 1, NullConstValue);
 }
 
 void
-test__const_to_str__int(void **state)
+test__scalar_const_to_str__int(void **state)
 {
-	verify__const_to_str(false, "1234", INT2OID, "1234");
-	verify__const_to_str(false, "1234", INT4OID, "1234");
-	verify__const_to_str(false, "1234", INT8OID, "1234");
-	verify__const_to_str(false, "1.234", FLOAT4OID, "1.234");
-	verify__const_to_str(false, "1.234", FLOAT8OID, "1.234");
-	verify__const_to_str(false, "1234", NUMERICOID, "1234");
+	verify__scalar_const_to_str(false, "1234", INT2OID, "1234");
+	verify__scalar_const_to_str(false, "1234", INT4OID, "1234");
+	verify__scalar_const_to_str(false, "1234", INT8OID, "1234");
+	verify__scalar_const_to_str(false, "1.234", FLOAT4OID, "1.234");
+	verify__scalar_const_to_str(false, "1.234", FLOAT8OID, "1.234");
+	verify__scalar_const_to_str(false, "1234", NUMERICOID, "1234");
 }
 
 void
-test__const_to_str__text(void **state)
+test__scalar_const_to_str__text(void **state)
 {
-	verify__const_to_str(false, "that", TEXTOID, "that");
-	verify__const_to_str(false, "joke", VARCHAROID, "joke");
-	verify__const_to_str(false, "isn't", BPCHAROID, "isn't");
-	verify__const_to_str(false, "funny", CHAROID, "funny");
-	verify__const_to_str(false, "anymore", BYTEAOID, "anymore");
-	verify__const_to_str(false, "iamdate", DATEOID, "iamdate");
+	verify__scalar_const_to_str(false, "that", TEXTOID, "that");
+	verify__scalar_const_to_str(false, "joke", VARCHAROID, "joke");
+	verify__scalar_const_to_str(false, "isn't", BPCHAROID, "isn't");
+	verify__scalar_const_to_str(false, "funny", CHAROID, "funny");
+	verify__scalar_const_to_str(false, "anymore", BYTEAOID, "anymore");
+	verify__scalar_const_to_str(false, "iamdate", DATEOID, "iamdate");
 }
 
 void
-test__const_to_str__boolean(void **state)
+test__scalar_const_to_str__boolean(void **state)
 {
-	verify__const_to_str(false, "t", BOOLOID, "true");
-	verify__const_to_str(false, "f", BOOLOID, "false");
+	verify__scalar_const_to_str(false, "t", BOOLOID, "true");
+	verify__scalar_const_to_str(false, "f", BOOLOID, "false");
 }
 
 void
-test__const_to_str__NegativeCircle(void **state)
+test__scalar_const_to_str__NegativeCircle(void **state)
 {
-	verify__const_to_str(false, "<3,3,9>", CIRCLEOID, NULL);
+	verify__scalar_const_to_str(false, "<3,3,9>", CIRCLEOID, NULL);
 }
 
+
+
 void
 test__opexpr_to_pxffilter__null(void **state)
 {
@@ -304,7 +549,7 @@ Const* build_const(Oid oid, char* value)
 	arg_const->consttype = oid;
 	if (value != NULL)
 	{
-		mock__const_to_str(oid, value);
+		mock__scalar_const_to_str(oid, value);
 	}
 
 	return arg_const;
@@ -369,7 +614,7 @@ void run__opexpr_to_pxffilter__positive(Oid dbop, PxfOperatorCode expectedPxfOp)
 	OpExpr *expr = build_op_expr(arg_var, arg_const, dbop);
 	PxfFilterDesc* expected = build_filter(
 			PXF_ATTR_CODE, 1, NULL,
-			PXF_CONST_CODE, 0, "1984",
+			PXF_SCALAR_CONST_CODE, 0, "1984",
 			expectedPxfOp);
 
 	/* run test */
@@ -393,14 +638,14 @@ test__opexpr_to_pxffilter__intGT(void **state)
 void
 test__opexpr_to_pxffilter__allSupportedTypes(void **state)
 {
-	int nargs = sizeof(pxf_supported_opr) / sizeof(dbop_pxfop_map);
+	int nargs = sizeof(pxf_supported_opr_op_expr) / sizeof(dbop_pxfop_map);
 	PxfOperatorCode pxfop = 0;
 	Oid dbop = InvalidOid;
 
 	for (int i = 0; i < nargs; ++i)
 	{
-		dbop = pxf_supported_opr[i].dbop;
-		pxfop = pxf_supported_opr[i].pxfop;
+		dbop = pxf_supported_opr_op_expr[i].dbop;
+		pxfop = pxf_supported_opr_op_expr[i].pxfop;
 		run__opexpr_to_pxffilter__positive(dbop, pxfop);
 	}
 }
@@ -417,7 +662,7 @@ test__opexpr_to_pxffilter__attributeEqualsNull(void **state)
 
 	PxfFilterDesc* expected = build_filter(
 				PXF_ATTR_CODE, 1, NULL,
-				PXF_CONST_CODE, 0, "\"NULL\"",
+				PXF_SCALAR_CONST_CODE, 0, NullConstValue,
 				PXFOP_EQ);
 
 	/* run test */
@@ -460,7 +705,7 @@ test__opexpr_to_pxffilter__differentTypes(void **state)
 	/* run test */
 	assert_true(opexpr_to_pxffilter(expr, filter));
 	PxfFilterDesc *expected = build_filter(
-			PXF_CONST_CODE, 0, "13",
+			PXF_SCALAR_CONST_CODE, 0, "13",
 			PXF_ATTR_CODE, 3, NULL,
 			PXFOP_LT);
 	compare_filters(filter, expected);
@@ -509,8 +754,7 @@ test__opexpr_to_pxffilter__unsupportedOpNot(void **state)
 {
 	PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
 	Var *arg_var = build_var(INT2OID, 3);
-	char* const_value = strdup("not"); /* will be free'd by const_to_str */
-	Const *arg_const = build_const(INT2OID, const_value);
+	Const *arg_const = build_const(INT2OID, NULL);
 	OpExpr *expr = build_op_expr(arg_const, arg_var, 1877 /* int2not */);
 
 	/* run test */
@@ -576,6 +820,7 @@ test__pxf_serialize_filter_list__manyFilters(void **state)
 	expressionItems = lappend(expressionItems, expressionItem3);
 	expressionItems = lappend(expressionItems, expressionItem4);
 	expressionItems = lappend(expressionItems, expressionItem5);
+
 	expressionItems = lappend(expressionItems, expressionItem6);
 	expressionItems = lappend(expressionItems, expressionItem7);
 
@@ -599,11 +844,15 @@ main(int argc, char* argv[])
 
 	const UnitTest tests[] = {
 			unit_test(test__supported_filter_type),
-			unit_test(test__const_to_str__null),
-			unit_test(test__const_to_str__int),
-			unit_test(test__const_to_str__text),
-			unit_test(test__const_to_str__boolean),
-			unit_test(test__const_to_str__NegativeCircle),
+			unit_test(test__supported_operator_type_op_expr),
+			unit_test(test__scalar_const_to_str__null),
+			unit_test(test__scalar_const_to_str__int),
+			unit_test(test__scalar_const_to_str__text),
+			unit_test(test__scalar_const_to_str__boolean),
+			unit_test(test__scalar_const_to_str__NegativeCircle),
+			unit_test(test__list_const_to_str__int),
+			unit_test(test__list_const_to_str__boolean),
+			unit_test(test__list_const_to_str__text),
 			unit_test(test__opexpr_to_pxffilter__null),
 			unit_test(test__opexpr_to_pxffilter__unary_expr),
 			unit_test(test__opexpr_to_pxffilter__intGT),

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/ed3376ae/src/include/access/pxffilters.h
----------------------------------------------------------------------
diff --git a/src/include/access/pxffilters.h b/src/include/access/pxffilters.h
index f194966..c7e8aa8 100644
--- a/src/include/access/pxffilters.h
+++ b/src/include/access/pxffilters.h
@@ -46,7 +46,8 @@ typedef enum PxfOperatorCode
 	PXFOP_NE,
 	PXFOP_LIKE,
 	PXFOP_IS_NULL,
-	PXFOP_IS_NOTNULL
+	PXFOP_IS_NOTNULL,
+	PXFOP_IN
 
 } PxfOperatorCode;
 
@@ -56,12 +57,17 @@ typedef enum PxfOperatorCode
  * string that gets pushed down.
  */
 #define PXF_ATTR_CODE				'a'
-#define PXF_CONST_CODE				'c'
+#define PXF_SCALAR_CONST_CODE		'c'
+#define PXF_LIST_CONST_CODE			'm'
 #define PXF_SIZE_BYTES				's'
 #define PXF_CONST_DATA				'd'
 #define PXF_OPERATOR_CODE			'o'
 #define PXF_LOGICAL_OPERATOR_CODE	'l'
 
+#define NullConstValue   "NULL"
+#define TrueConstValue   "true"
+#define FalseConstValue   "false"
+
 /*
  * An Operand has any of the above codes, and the information specific to
  * its type. This could be compacted but filter structures are expected to
@@ -69,10 +75,10 @@ typedef enum PxfOperatorCode
  */
 typedef struct PxfOperand
 {
-	char		opcode;		/* PXF_ATTR_CODE or PXF_CONST_CODE*/
+	char		opcode;		/* PXF_ATTR_CODE, PXF_SCALAR_CONST_CODE, PXF_LIST_CONST_CODE*/
 	AttrNumber 	attnum;		/* used when opcode is PXF_ATTR_CODE */
-	StringInfo 	conststr;	/* used when opcode is PXF_CONST_CODE */
-	Oid 		consttype; 	/* used when opcode is PXF_CONST_CODE */
+	StringInfo 	conststr;	/* used when opcode is PXF_SCALAR_CONST_CODE or PXF_LIST_CONST_CODE*/
+	Oid 		consttype; 	/* used when opcode is PXF_SCALAR_CONST_CODE or PXF_LIST_CONST_CODE*/
 
 } PxfOperand;
 
@@ -88,7 +94,7 @@ typedef struct PxfFilterDesc
 } PxfFilterDesc;
 
 /*
- * HAWQ operator OID to PXF operator code mapping
+ * HAWQ operator OID to PXF operator code mapping used for OpExpr
  */
 typedef struct dbop_pxfop_map
 {
@@ -97,6 +103,16 @@ typedef struct dbop_pxfop_map
 
 } dbop_pxfop_map;
 
+/*
+ * HAWQ operator OID to PXF operator code mapping used for ScalarArrayOpExpr
+ */
+typedef struct dbop_pxfop_array_map
+{
+	Oid				dbop;
+	PxfOperatorCode	pxfop;
+	bool			useOr;
+
+} dbop_pxfop_array_map;
 
 typedef struct ExpressionItem
 {
@@ -110,9 +126,14 @@ static inline bool pxfoperand_is_attr(PxfOperand x)
 	return (x.opcode == PXF_ATTR_CODE);
 }
 
-static inline bool pxfoperand_is_const(PxfOperand x)
+static inline bool pxfoperand_is_scalar_const(PxfOperand x)
+{
+	return (x.opcode == PXF_SCALAR_CONST_CODE);
+}
+
+static inline bool pxfoperand_is_list_const(PxfOperand x)
 {
-	return (x.opcode == PXF_CONST_CODE);
+	return (x.opcode == PXF_LIST_CONST_CODE);
 }
 
 char *serializePxfFilterQuals(List *quals);

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/ed3376ae/src/include/catalog/pg_type.h
----------------------------------------------------------------------
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 3411c45..6d4f6d5 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -487,6 +487,7 @@ DESCR("network IP address/netmask, network address");
 
 /*  OIDS 1000 - 1099  */
 DATA(insert OID = 1000 (	_bool	   PGNSP PGUID -1 f b t \054 0	16 array_in array_out array_recv
array_send - i x f 0 -1 0 _null_ _null_ ));
+#define BOOLARRAYOID 1000
 DATA(insert OID = 1001 (	_bytea	   PGNSP PGUID -1 f b t \054 0	17 array_in array_out array_recv
array_send - i x f 0 -1 0 _null_ _null_ ));
 DATA(insert OID = 1002 (	_char	   PGNSP PGUID -1 f b t \054 0	18 array_in array_out array_recv
array_send - i x f 0 -1 0 _null_ _null_ ));
 DATA(insert OID = 1003 (	_name	   PGNSP PGUID -1 f b t \054 0	19 array_in array_out array_recv
array_send - i x f 0 -1 0 _null_ _null_ ));



Mime
View raw message