Repository: incubator-hawq
Updated Branches:
  refs/heads/HAWQ-1114_ [created] 3988fa9d6


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/f5369009
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/f5369009
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/f5369009

Branch: refs/heads/HAWQ-1114_
Commit: f5369009872e61bbbc83dfc296671f79f0094826
Parents: cb68111
Author: Oleksandr Diachenko <[email protected]>
Authored: Tue Nov 22 15:36:49 2016 -0800
Committer: Oleksandr Diachenko <[email protected]>
Committed: Tue Nov 22 15:36:49 2016 -0800

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


http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/f5369009/src/backend/access/external/pxffilters.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/pxffilters.c 
b/src/backend/access/external/pxffilters.c
index 3961b48..86f11e6 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,
@@ -187,7 +254,13 @@ Oid pxf_supported_types[] =
        BYTEAOID,
        BOOLOID,
        DATEOID,
-       TIMESTAMPOID
+       TIMESTAMPOID,
+       /* complex datatypes*/
+       INT2ARRAYOID,
+       INT4ARRAYOID,
+       INT8ARRAYOID,
+       BOOLARRAYOID,
+       TEXTARRAYOID
 };
 
 static void
@@ -248,7 +321,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);
@@ -274,10 +349,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:
@@ -364,7 +456,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.
@@ -377,6 +468,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);
@@ -387,18 +518,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 */
@@ -422,6 +553,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;
@@ -479,8 +653,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;
@@ -514,6 +686,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))
        {
@@ -523,20 +701,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;
@@ -551,23 +727,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;
 
-       elog(DEBUG1, "opexpr_to_pxffilter: operator is not supported, operator 
code: %d", expr->opno);
+               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;
+       }
 
-       /* 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*
@@ -654,6 +917,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
  *
@@ -661,7 +973,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;
@@ -670,7 +982,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;
        }
 
@@ -696,19 +1008,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)));
 
@@ -719,6 +1029,143 @@ const_to_str(Const *constval, StringInfo buf)
 
 
 /*
+ * list_const_to_str
+ *
+ */
+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/f5369009/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 e618563..2ed8850 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)
@@ -65,7 +67,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, 14);
+       assert_int_equal(nargs, 19);
        for (i = 0; i < nargs; ++i)
        {
                assert_true(supported_filter_type(pxf_supported_types[i]));
@@ -73,11 +75,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);
@@ -89,8 +189,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;
@@ -101,20 +234,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);
@@ -122,25 +255,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();
        {
@@ -164,46 +407,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)
 {
@@ -305,7 +550,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;
@@ -370,7 +615,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 */
@@ -394,14 +639,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);
        }
 }
@@ -418,7 +663,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 */
@@ -461,7 +706,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);
@@ -510,8 +755,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 */
@@ -577,6 +821,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);
 
@@ -600,11 +845,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/f5369009/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/f5369009/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_ ));


Reply via email to