You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by od...@apache.org on 2016/10/13 21:19:33 UTC
incubator-hawq git commit: HAWQ-1048. Support OR,
NOT logical operators in the HAWQ/PXF Bridge.
Repository: incubator-hawq
Updated Branches:
refs/heads/master 2cc152eb0 -> 7f3658d3a
HAWQ-1048. Support OR, NOT logical operators in the HAWQ/PXF Bridge.
Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/7f3658d3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/7f3658d3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/7f3658d3
Branch: refs/heads/master
Commit: 7f3658d3aa5933028835b753df8fb6cfc4934856
Parents: 2cc152e
Author: Oleksandr Diachenko <od...@pivotal.io>
Authored: Thu Oct 13 14:19:12 2016 -0700
Committer: Oleksandr Diachenko <od...@pivotal.io>
Committed: Thu Oct 13 14:19:29 2016 -0700
----------------------------------------------------------------------
src/backend/access/external/pxffilters.c | 328 ++++++++++++-------
.../access/external/test/pxffilters_test.c | 106 +++---
src/include/access/pxffilters.h | 10 +-
3 files changed, 260 insertions(+), 184 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f3658d3/src/backend/access/external/pxffilters.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/pxffilters.c b/src/backend/access/external/pxffilters.c
index 354c719..56aea55 100644
--- a/src/backend/access/external/pxffilters.c
+++ b/src/backend/access/external/pxffilters.c
@@ -31,14 +31,14 @@
#include "utils/guc.h"
#include "utils/lsyscache.h"
-static List* pxf_make_filter_list(List* quals);
+static List* pxf_make_expression_items_list(List *quals, Node *parent, bool *logicalOpsNum);
static void pxf_free_filter(PxfFilterDesc* filter);
-static void pxf_free_filter_list(List *filters);
static char* pxf_serialize_filter_list(List *filters);
static bool opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter);
static bool supported_filter_type(Oid type);
static void const_to_str(Const *constval, StringInfo buf);
static List* append_attr_from_var(Var* var, List* attrs);
+static void enrich_trivial_expression(List *expressionItems);
/*
* All supported HAWQ operators, and their respective HFDS operator code.
@@ -135,7 +135,40 @@ dbop_pxfop_map pxf_supported_opr[] =
{1097 /* date_gt */, PXFOP_GT},
{1096 /* date_le */, PXFOP_LE},
{1098 /* date_ge */, PXFOP_GE},
- {1094 /* date_ne */, PXFOP_NE}
+ {1094 /* date_ne */, PXFOP_NE},
+
+ /* float8 */
+ {Float8EqualOperator /* float8eq */, PXFOP_EQ},
+ {672 /* float8lt */, PXFOP_LT},
+ {674 /* float8gt */, PXFOP_GT},
+ {673 /* float8le */, PXFOP_LE},
+ {675 /* float8ge */, PXFOP_GE},
+ {671 /* float8ne */, PXFOP_NE},
+
+ /* float48 */
+ {1120 /* float48eq */, PXFOP_EQ},
+ {1122 /* float48lt */, PXFOP_LT},
+ {1123 /* float48gt */, PXFOP_GT},
+ {1124 /* float48le */, PXFOP_LE},
+ {1125 /* float48ge */, PXFOP_GE},
+ {1121 /* float48ne */, PXFOP_NE},
+
+ /* bpchar */
+ {BPCharEqualOperator /* bpchareq */, PXFOP_EQ},
+ {1058 /* bpcharlt */, PXFOP_LT},
+ {1060 /* bpchargt */, PXFOP_GT},
+ {1059 /* bpcharle */, PXFOP_LE},
+ {1061 /* bpcharge */, PXFOP_GE},
+ {1057 /* bpcharne */, PXFOP_NE}
+
+ /* bytea */
+ // TODO: uncomment once HAWQ-1085 is done
+ //,{ByteaEqualOperator /* byteaeq */, PXFOP_EQ},
+ //{1957 /* bytealt */, PXFOP_LT},
+ //{1959 /* byteagt */, PXFOP_GT},
+ //{1958 /* byteale */, PXFOP_LE},
+ //{1960 /* byteage */, PXFOP_GE},
+ //{1956 /* byteane */, PXFOP_NE}
};
@@ -153,72 +186,102 @@ Oid pxf_supported_types[] =
CHAROID,
BYTEAOID,
BOOLOID,
- DATEOID
+ DATEOID,
+ TIMESTAMPOID
};
+static void
+pxf_free_expression_items_list(List *expressionItems, bool freeBoolExprNodes)
+{
+ ListCell *lc = NULL;
+ ExpressionItem *expressionItem = NULL;
+ int previousLength;
+
+ while (list_length(expressionItems) > 0)
+ {
+ expressionItem = (ExpressionItem *) lfirst(list_head(expressionItems));
+ if (freeBoolExprNodes && nodeTag(expressionItem->node) == T_BoolExpr)
+ {
+ pfree((BoolExpr *)expressionItem->node);
+ }
+ pfree(expressionItem);
+
+ /* to avoid freeing already freed items - delete all occurrences of current expression*/
+ previousLength = expressionItems->length + 1;
+ while (expressionItems != NULL && previousLength > expressionItems->length)
+ {
+ previousLength = expressionItems->length;
+ expressionItems = list_delete_ptr(expressionItems, expressionItem);
+ }
+ }
+}
+
/*
- * pxf_make_filter_list
+ * pxf_make_expression_items_list
*
* Given a scan node qual list, find the filters that are eligible to be used
- * by PXF, construct a PxfFilterDesc list that describes the filter information,
+ * by PXF, construct an expressions list, which consists of OpExpr or BoolExpr nodes
* and return it to the caller.
*
- * Caller is responsible for pfreeing the returned PxfFilterDesc List.
+ * Basically this function just transforms expression tree to Reversed Polish Notation list.
+ *
+ *
*/
static List *
-pxf_make_filter_list(List *quals)
+pxf_make_expression_items_list(List *quals, Node *parent, bool *logicalOpsNum)
{
+ ExpressionItem *expressionItem = NULL;
List *result = NIL;
ListCell *lc = NULL;
+ ListCell *ilc = NULL;
if (list_length(quals) == 0)
return NIL;
- /*
- * Iterate over all implicitly ANDed qualifiers and add the ones
- * that are supported for push-down into the result filter list.
- */
foreach (lc, quals)
{
Node *node = (Node *) lfirst(lc);
NodeTag tag = nodeTag(node);
+ expressionItem = (ExpressionItem *) palloc0(sizeof(ExpressionItem));
+ expressionItem->node = node;
+ expressionItem->parent = parent;
+ expressionItem->processed = false;
switch (tag)
{
case T_OpExpr:
{
- OpExpr *expr = (OpExpr *) node;
- PxfFilterDesc *filter;
-
- filter = (PxfFilterDesc *) palloc0(sizeof(PxfFilterDesc));
- elog(DEBUG5, "pxf_make_filter_list: node tag %d (T_OpExpr)", tag);
-
- if (opexpr_to_pxffilter(expr, filter))
- result = lappend(result, filter);
- else
- pfree(filter);
-
+ result = lappend(result, expressionItem);
break;
}
case T_BoolExpr:
{
+ (*logicalOpsNum)++;
BoolExpr *expr = (BoolExpr *) node;
- BoolExprType boolType = expr->boolop;
- elog(DEBUG5, "pxf_make_filter_list: node tag %d (T_BoolExpr), bool node type %d %s",
- tag, boolType, boolType==AND_EXPR ? "(AND_EXPR)" : "");
+ List *inner_result = pxf_make_expression_items_list(expr->args, node, logicalOpsNum);
+ result = list_concat(result, inner_result);
+
+ int childNodesNum = 0;
- /* only AND_EXPR is supported */
- if (expr->boolop == AND_EXPR)
+ /* Find number of child nodes on first level*/
+ foreach (ilc, inner_result)
{
- List *inner_result = pxf_make_filter_list(expr->args);
- elog(DEBUG5, "pxf_make_filter_list: inner result size %d", list_length(inner_result));
- result = list_concat(result, inner_result);
+ ExpressionItem *ei = (ExpressionItem *) lfirst(ilc);
+ if (!ei->processed && ei->parent == node)
+ {
+ ei->processed = true;
+ childNodesNum++;
+ }
+ }
+
+ for (int i = 0; i < childNodesNum - 1; i++)
+ {
+ result = lappend(result, expressionItem);
}
break;
}
default:
- /* expression not supported. ignore */
- elog(DEBUG5, "pxf_make_filter_list: unsupported node tag %d", tag);
+ elog(DEBUG1, "pxf_make_expression_items_list: unsupported node tag %d", tag);
break;
}
}
@@ -249,33 +312,9 @@ pxf_free_filter(PxfFilterDesc* filter)
}
/*
- * pxf_free_filter_list
- *
- * free all memory associated with the filters once no longer needed.
- * alternatively we could have allocated them in a shorter lifespan
- * memory context, however explicitly freeing them is easier and makes
- * more sense.
- */
-static void
-pxf_free_filter_list(List *filters)
-{
- ListCell *lc = NULL;
- PxfFilterDesc *filter = NULL;
-
- if (list_length(filters) == 0)
- return;
-
- foreach (lc, filters)
- {
- filter = (PxfFilterDesc *) lfirst(lc);
- pxf_free_filter(filter);
- }
-}
-
-/*
* pxf_serialize_filter_list
*
- * Given a list of implicitly ANDed PxfFilterDesc objects, produce a
+ * Takes expression items list in RPN notation, produce a
* serialized string representation in order to communicate this list
* over the wire.
*
@@ -287,9 +326,7 @@ pxf_free_filter_list(List *filters)
*
* Example filter list:
*
- * Column(0) > 1
- * Column(0) < 5
- * Column(2) == "third"
+ * Column(0) > 1 AND Column(0) < 5 AND Column(2) == "third"
*
* Yields the following serialized string:
*
@@ -297,72 +334,86 @@ pxf_free_filter_list(List *filters)
*
*/
static char *
-pxf_serialize_filter_list(List *filters)
+pxf_serialize_filter_list(List *expressionItems)
{
+
StringInfo resbuf;
- StringInfo curbuf;
ListCell *lc = NULL;
- if (list_length(filters) == 0)
+ if (list_length(expressionItems) == 0)
return NULL;
resbuf = makeStringInfo();
initStringInfo(resbuf);
- curbuf = makeStringInfo();
- initStringInfo(curbuf);
/*
- * Iterate through the filters in the list and serialize them one after
- * the other. We use buffer copying because it's clear. Considering the
- * typical small number of memcpy's this generates overall, there's no
- * point in optimizing, better keep it clear.
+ * Iterate through the expression items in the list and serialize them one after the other.
*/
- foreach (lc, filters)
+ foreach (lc, expressionItems)
{
- PxfFilterDesc *filter = (PxfFilterDesc *) lfirst(lc);
- PxfOperand l = filter->l;
- PxfOperand r = filter->r;
- PxfOperatorCode o = filter->op;
-
- /* last result is stored in 'oldbuf'. start 'curbuf' clean */
- resetStringInfo(curbuf);
-
- /* format the operands */
- if (pxfoperand_is_attr(l) && pxfoperand_is_const(r))
- {
- appendStringInfo(curbuf, "%c%d%c%s",
- PXF_ATTR_CODE, l.attnum - 1, /* Java attrs are 0-based */
- PXF_CONST_CODE, (r.conststr)->data);
- }
- else if (pxfoperand_is_const(l) && pxfoperand_is_attr(r))
- {
- appendStringInfo(curbuf, "%c%s%c%d",
- PXF_CONST_CODE, (l.conststr)->data,
- PXF_ATTR_CODE, r.attnum - 1); /* Java attrs are 0-based */
- }
- else
- {
- /* pxf_make_filter_list() 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")));
- }
-
- /* format the operator */
- appendStringInfo(curbuf, "%c%d", PXF_OPERATOR_CODE, o);
-
- /* append this result to the previous result */
- appendBinaryStringInfo(resbuf, curbuf->data, curbuf->len);
+ ExpressionItem *expressionItem = (ExpressionItem *) lfirst(lc);
+ Node *node = expressionItem->node;
+ NodeTag tag = nodeTag(node);
- /* if there was a previous result, append a trailing AND operator */
- if(resbuf->len > curbuf->len)
+ switch (tag)
{
- appendStringInfo(resbuf, "%c%d", PXF_OPERATOR_CODE, PXFOP_AND);
+ case T_OpExpr:
+ {
+ elog(DEBUG1, "pxf_serialize_filter_list: node tag %d (T_OpExpr)", tag);
+ PxfFilterDesc *filter = (PxfFilterDesc *) palloc0(sizeof(PxfFilterDesc));
+ OpExpr *expr = (OpExpr *) node;
+ if (opexpr_to_pxffilter(expr, filter))
+ {
+ PxfOperand l = filter->l;
+ PxfOperand r = filter->r;
+ PxfOperatorCode o = filter->op;
+ if (pxfoperand_is_attr(l) && pxfoperand_is_const(r))
+ {
+ appendStringInfo(resbuf, "%c%d%c%s",
+ PXF_ATTR_CODE, l.attnum - 1, /* Java attrs are 0-based */
+ PXF_CONST_CODE, (r.conststr)->data);
+ }
+ else if (pxfoperand_is_const(l) && pxfoperand_is_attr(r))
+ {
+ appendStringInfo(resbuf, "%c%s%c%d",
+ PXF_CONST_CODE, (l.conststr)->data,
+ PXF_ATTR_CODE, r.attnum - 1); /* Java attrs are 0-based */
+ }
+ else
+ {
+ /* opexpr_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;
+ BoolExprType boolType = expr->boolop;
+ elog(DEBUG1, "pxf_serialize_filter_list: node tag %d (T_BoolExpr), bool node type %d", tag, boolType);
+ appendStringInfo(resbuf, "%c%d", PXF_LOGICAL_OPERATOR_CODE, boolType);
+ break;
+ }
}
}
- pfree(curbuf->data);
+ if (resbuf->len == 0)
+ {
+ pfree(resbuf->data);
+ return NULL;
+ }
return resbuf->data;
}
@@ -395,12 +446,12 @@ opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter)
/* only binary oprs supported currently */
if (!rightop)
{
- elog(DEBUG5, "opexpr_to_pxffilter: unary op! leftop_type: %d, op: %d",
+ elog(DEBUG1, "opexpr_to_pxffilter: unary op! leftop_type: %d, op: %d",
leftop_type, expr->opno);
return false;
}
- elog(DEBUG5, "opexpr_to_gphdfilter: leftop (expr type: %d, arg type: %d), "
+ elog(DEBUG1, "opexpr_to_gphdfilter: leftop (expr type: %d, arg type: %d), "
"rightop_type (expr type: %d, arg type %d), op: %d",
leftop_type, nodeTag(leftop),
rightop_type, nodeTag(rightop),
@@ -441,6 +492,7 @@ opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter)
}
else
{
+ elog(DEBUG1, "opexpr_to_pxffilter: expression is not a Var+Const");
return false;
}
@@ -456,9 +508,10 @@ opexpr_to_pxffilter(OpExpr *expr, PxfFilterDesc *filter)
}
}
+ 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;
}
@@ -540,6 +593,9 @@ supported_filter_type(Oid type)
if (type == pxf_supported_types[i])
return true;
}
+
+ elog(DEBUG1, "supported_filter_type: filter pushdown is not supported for datatype oid: %d", type);
+
return false;
}
@@ -585,6 +641,7 @@ const_to_str(Const *constval, StringInfo buf)
case CHAROID:
case BYTEAOID:
case DATEOID:
+ case TIMESTAMPOID:
appendStringInfo(buf, "\\\"%s\\\"", extval);
break;
@@ -626,16 +683,53 @@ char *serializePxfFilterQuals(List *quals)
if (pxf_enable_filter_pushdown)
{
- List *filters = pxf_make_filter_list(quals);
- result = pxf_serialize_filter_list(filters);
- pxf_free_filter_list(filters);
+ int logicalOpsNum = 0;
+ List *expressionItems = pxf_make_expression_items_list(quals, NULL, &logicalOpsNum);
+
+ //Trivial expression means list of OpExpr implicitly ANDed
+ bool isTrivialExpression = logicalOpsNum == 0 && expressionItems && expressionItems->length > 1;
+
+ if (isTrivialExpression)
+ {
+ enrich_trivial_expression(expressionItems);
+ }
+ result = pxf_serialize_filter_list(expressionItems);
+ pxf_free_expression_items_list(expressionItems, isTrivialExpression);
}
- elog(DEBUG2, "serializePxfFilterQuals: filter result: %s", (result == NULL) ? "null" : result);
+
+
+ elog(DEBUG1, "serializePxfFilterQuals: filter result: %s", (result == NULL) ? "null" : result);
return result;
}
+/*
+ * Takes list of expression items which supposed to be just a list of OpExpr
+ * and adds needed number of AND items
+ *
+ */
+void enrich_trivial_expression(List *expressionItems) {
+
+
+ int logicalOpsNumNeeded = expressionItems->length - 1;
+
+ if (logicalOpsNumNeeded > 0)
+ {
+ ExpressionItem *andExpressionItem = (ExpressionItem *) palloc0(sizeof(ExpressionItem));
+ BoolExpr *andExpr = makeNode(BoolExpr);
+
+ andExpr->boolop = AND_EXPR;
+
+ andExpressionItem->node = andExpr;
+ andExpressionItem->parent = NULL;
+ andExpressionItem->processed = false;
+
+ for (int i = 0; i < logicalOpsNumNeeded; i++) {
+ expressionItems = lappend(expressionItems, andExpressionItem);
+ }
+ }
+}
/*
* Returns a list of attributes, extracted from quals.
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f3658d3/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 7dc3aec..76be330 100644
--- a/src/backend/access/external/test/pxffilters_test.c
+++ b/src/backend/access/external/test/pxffilters_test.c
@@ -65,7 +65,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, 14);
for (i = 0; i < nargs; ++i)
{
assert_true(supported_filter_type(pxf_supported_types[i]));
@@ -323,6 +323,21 @@ OpExpr* build_op_expr(void* left, void* right, int op)
return expr;
}
+ExpressionItem* build_expression_item(int lattnum, Oid lattrtype, char* rconststr, Oid rattrtype, int op) {
+
+ ExpressionItem *expressionItem = (ExpressionItem*) palloc0(sizeof(ExpressionItem));
+
+ Var *leftop = build_var(lattrtype, lattnum);
+ Const *rightop = build_const(rattrtype, strdup(rconststr));
+ OpExpr *operationExpression = build_op_expr(leftop, rightop, op);
+
+ expressionItem->node = operationExpression;
+ expressionItem->processed = false;
+ expressionItem->parent = NULL;
+
+ return expressionItem;
+}
+
void run__opexpr_to_pxffilter__positive(Oid dbop, PxfOperatorCode expectedPxfOp)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
@@ -475,91 +490,50 @@ test__opexpr_to_pxffilter__unsupportedOpNot(void **state)
pfree(expr);
}
-void
-test__pxf_serialize_filter_list__oneFilter(void **state)
-{
- List* filter_list = NIL;
+void test__pxf_serialize_filter_list__oneFilter(void **state) {
- PxfFilterDesc* filter = build_filter(
- PXF_ATTR_CODE, 1, NULL,
- PXF_CONST_CODE, 0, "1984",
- PXFOP_GT);
- filter_list = lappend(filter_list, filter);
+ List* expressionItems = NIL;
- char* result = pxf_serialize_filter_list(filter_list);
- assert_string_equal(result, "a0c1984o2");
+ ExpressionItem* filterExpressionItem = build_expression_item(1, TEXTOID, "1984", TEXTOID, TextEqualOperator);
- pxf_free_filter_list(filter_list);
- filter_list = NIL;
- pfree(result);
-
- filter = build_filter(
- PXF_ATTR_CODE, 8, NULL,
- PXF_CONST_CODE, 0, "\"George Orwell\"",
- PXFOP_EQ);
- filter_list = lappend(filter_list, filter);
+ expressionItems = lappend(expressionItems, filterExpressionItem);
- result = pxf_serialize_filter_list(filter_list);
- assert_string_equal(result, "a7c\"George Orwell\"o5");
+ char* result = pxf_serialize_filter_list(expressionItems);
+ assert_string_equal(result, "a0c\\\"1984\\\"o5");
- pxf_free_filter_list(filter_list);
+ pxf_free_expression_items_list(expressionItems, true);
+ expressionItems = NIL;
pfree(result);
+
}
void
test__pxf_serialize_filter_list__manyFilters(void **state)
{
char* result = NULL;
- List* filter_list = NIL;
+ List* expressionItems = NIL;
- PxfFilterDesc* filter1 = build_filter(
- PXF_ATTR_CODE, 2, NULL,
- PXF_CONST_CODE, 0, "1983",
- PXFOP_GT);
- PxfFilterDesc* filter2 = build_filter(
- PXF_ATTR_CODE, 3, NULL,
- PXF_CONST_CODE, 0, "1985",
- PXFOP_LT);
- PxfFilterDesc* filter3 = build_filter(
- PXF_ATTR_CODE, 4, NULL,
- PXF_CONST_CODE, 0, "\"George Orwell\"",
- PXFOP_EQ);
- PxfFilterDesc* filter4 = build_filter(
- PXF_ATTR_CODE, 5, NULL,
- PXF_CONST_CODE, 0, "\"Winston\"",
- PXFOP_GE);
- PxfFilterDesc* filter5 = build_filter(
- PXF_ATTR_CODE, 6, NULL,
- PXF_CONST_CODE, 0, "\"Eric-%\"",
- PXFOP_LIKE);
-
- filter_list = lappend(filter_list, filter1);
- filter_list = lappend(filter_list, filter2);
-
- result = pxf_serialize_filter_list(filter_list);
- assert_string_equal(result, "a1c1983o2a2c1985o1o7");
- pfree(result);
-
- filter_list = lappend(filter_list, filter3);
+ ExpressionItem* expressionItem1 = build_expression_item(1, TEXTOID, "1984", TEXTOID, TextEqualOperator);
+ ExpressionItem* expressionItem2 = build_expression_item(2, TEXTOID, "\"George Orwell\"", TEXTOID, TextEqualOperator);
+ ExpressionItem* expressionItem3 = build_expression_item(3, TEXTOID, "\"Winston\"", TEXTOID, TextEqualOperator);
+ ExpressionItem* expressionItem4 = build_expression_item(4, TEXTOID, "\"Eric-%\"", TEXTOID, 1209);
- result = pxf_serialize_filter_list(filter_list);
- assert_string_equal(result, "a1c1983o2a2c1985o1o7a3c\"George Orwell\"o5o7");
- pfree(result);
- filter_list = lappend(filter_list, filter4);
+ expressionItems = lappend(expressionItems, expressionItem1);
+ expressionItems = lappend(expressionItems, expressionItem2);
+ expressionItems = lappend(expressionItems, expressionItem3);
+ expressionItems = lappend(expressionItems, expressionItem4);
- result = pxf_serialize_filter_list(filter_list);
- assert_string_equal(result, "a1c1983o2a2c1985o1o7a3c\"George Orwell\"o5o7a4c\"Winston\"o4o7");
+ result = pxf_serialize_filter_list(expressionItems);
+ assert_string_equal(result, "a0c\\\"1984\\\"o5a1c\\\"\"George Orwell\"\\\"o5a2c\\\"\"Winston\"\\\"o5a3c\\\"\"Eric-%\"\\\"o7");
pfree(result);
- filter_list = lappend(filter_list, filter5);
+ enrich_trivial_expression(expressionItems);
- result = pxf_serialize_filter_list(filter_list);
- assert_string_equal(result, "a1c1983o2a2c1985o1o7a3c\"George Orwell\"o5o7a4c\"Winston\"o4o7a5c\"Eric-%\"o8o7");
- pfree(result);
+ assert_int_equal(expressionItems->length, 7);
- pxf_free_filter_list(filter_list);
- filter_list = NIL;
+ pxf_free_expression_items_list(expressionItems, true);
+ expressionItems = NIL;
}
int
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7f3658d3/src/include/access/pxffilters.h
----------------------------------------------------------------------
diff --git a/src/include/access/pxffilters.h b/src/include/access/pxffilters.h
index f54c47c..894337b 100644
--- a/src/include/access/pxffilters.h
+++ b/src/include/access/pxffilters.h
@@ -44,7 +44,6 @@ typedef enum PxfOperatorCode
PXFOP_GE,
PXFOP_EQ,
PXFOP_NE,
- PXFOP_AND,
PXFOP_LIKE
} PxfOperatorCode;
@@ -57,6 +56,7 @@ typedef enum PxfOperatorCode
#define PXF_ATTR_CODE 'a'
#define PXF_CONST_CODE 'c'
#define PXF_OPERATOR_CODE 'o'
+#define PXF_LOGICAL_OPERATOR_CODE 'l'
/*
* An Operand has any of the above codes, and the information specific to
@@ -92,6 +92,14 @@ typedef struct dbop_pxfop_map
} dbop_pxfop_map;
+
+typedef struct ExpressionItem
+{
+ Node *node;
+ Node *parent;
+ bool processed;
+} ExpressionItem;
+
static inline bool pxfoperand_is_attr(PxfOperand x)
{
return (x.opcode == PXF_ATTR_CODE);