http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/f7aaa280/core/sql/src/main/java/org/trafodion/sql/HTableClient.java
----------------------------------------------------------------------
diff --git a/core/sql/src/main/java/org/trafodion/sql/HTableClient.java
b/core/sql/src/main/java/org/trafodion/sql/HTableClient.java
index 5d936bc..ba29f99 100644
--- a/core/sql/src/main/java/org/trafodion/sql/HTableClient.java
+++ b/core/sql/src/main/java/org/trafodion/sql/HTableClient.java
@@ -365,417 +365,417 @@ public class HTableClient {
table.setAutoFlush(true, true);
}
- private enum Op {
- EQUAL, EQUAL_NULL, NOT_EQUAL, NOT_EQUAL_NULL, LESS, LESS_NULL,
LESS_OR_EQUAL, LESS_OR_EQUAL_NULL, GREATER, GREATER_NULL,
- GREATER_OR_EQUAL, GREATER_OR_EQUAL_NULL, NO_OP,
NO_OP_NULL,IS_NULL, IS_NULL_NULL, IS_NOT_NULL, IS_NOT_NULL_NULL, AND, OR};
-
- private Filter SingleColumnValueExcludeOrNotFilter(byte[]
columnToFilter,
-
CompareOp op,
-
ByteArrayComparable comparator,
-
HashMap<String,Object> columnsToRemove,
-
Boolean... filterIfMissing){
- Filter result;
- boolean fMissing =
filterIfMissing.length>0?filterIfMissing[0]:false;//default to false
- if ((columnsToRemove == null) ||
!columnsToRemove.containsKey(new String(columnToFilter))){
- result = new
SingleColumnValueFilter(getFamily(columnToFilter), getName(columnToFilter), op,
comparator);
-
((SingleColumnValueFilter)result).setFilterIfMissing(fMissing);
- }
- else{
- result= new
SingleColumnValueExcludeFilter(getFamily(columnToFilter),
getName(columnToFilter), op, comparator);
-
((SingleColumnValueExcludeFilter)result).setFilterIfMissing(fMissing);
- }
- return result;
- }
-
- // construct the hbase filter
- // optimizes for OR and AND associativity
- // optimizes for detection of a<? and a>? on nullable and non nullable
column equivalent to a<>?
- // optimize for null check factorization (A not null and (A <op> ?)) or
(A not null and A <op2> ?) -> A not null and (A <op> ? or A <op2> ?)
- // this is an important optimzation for IN statement on
non null column
- // uses the columnToRemove parametter to know if we need to use the
SingleColumnValue Exclude or not method to limit returned columns
-
- private Filter constructV2Filter(Object[] colNamesToFilter,
+ private enum Op {
+ EQUAL, EQUAL_NULL, NOT_EQUAL, NOT_EQUAL_NULL, LESS, LESS_NULL,
LESS_OR_EQUAL, LESS_OR_EQUAL_NULL, GREATER, GREATER_NULL,
+ GREATER_OR_EQUAL, GREATER_OR_EQUAL_NULL, NO_OP, NO_OP_NULL,IS_NULL,
IS_NULL_NULL, IS_NOT_NULL, IS_NOT_NULL_NULL, AND, OR};
+
+ private Filter SingleColumnValueExcludeOrNotFilter(byte[] columnToFilter,
+ CompareOp op,
+ ByteArrayComparable
comparator,
+ HashMap<String,Object>
columnsToRemove,
+ Boolean...
filterIfMissing){
+ Filter result;
+ boolean fMissing =
filterIfMissing.length>0?filterIfMissing[0]:false;//default to false
+ if ((columnsToRemove == null) || !columnsToRemove.containsKey(new
String(columnToFilter))){
+ result = new SingleColumnValueFilter(getFamily(columnToFilter),
getName(columnToFilter), op, comparator);
+ ((SingleColumnValueFilter)result).setFilterIfMissing(fMissing);
+ }
+ else{
+ result= new
SingleColumnValueExcludeFilter(getFamily(columnToFilter),
getName(columnToFilter), op, comparator);
+
((SingleColumnValueExcludeFilter)result).setFilterIfMissing(fMissing);
+ }
+ return result;
+ }
+
+ // construct the hbase filter
+ // optimizes for OR and AND associativity
+ // optimizes for detection of a<? and a>? on nullable and non nullable
column equivalent to a<>?
+ // optimize for null check factorization (A not null and (A <op> ?)) or (A
not null and A <op2> ?) -> A not null and (A <op> ? or A <op2> ?)
+ // this is an important optimzation for IN statement on non null
column
+ // uses the columnToRemove parametter to know if we need to use the
SingleColumnValue Exclude or not method to limit returned columns
+
+ private Filter constructV2Filter(Object[] colNamesToFilter,
Object[] compareOpList,
Object[] colValuesToCompare,
HashMap<String,Object> columnsToRemove){
- LinkedList linkedList = new LinkedList();
- //populate the list with nodes in reverse polish notation order.
- int k=0;//column index
- int kk=0;//value index
- for (int i=1; i<compareOpList.length; i++){ // skip first one
containing "V2" marker
- String opStr = new String((byte[])compareOpList[i]);
- switch(Op.valueOf(opStr)){
-
- case EQUAL:
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
- CompareOp.EQUAL,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
- columnsToRemove
- ));
- k++;kk++;
- break;
- case EQUAL_NULL:
- linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
-
new BinaryPrefixComparator(new byte[]{0x00}),//check for null
indicator = 0 representing non null
-
columnsToRemove,
-
true //filterIfMissing
-
),
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
-
new BinaryComparator((byte[])colValuesToCompare[kk]),
-
columnsToRemove)));
- k++;kk++;
- break;
- case NOT_EQUAL:
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
- CompareOp.NOT_EQUAL,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
- columnsToRemove));
- k++;kk++;
- break;
- case NOT_EQUAL_NULL:
- linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
- new
BinaryPrefixComparator(new byte[]{0x00}),//check for null indicator = 0
representing non null
-
columnsToRemove,
- true),
//filterIfMissing,
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.NOT_EQUAL,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
-
columnsToRemove)));
- k++;kk++;
- break;
- case LESS:
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
- CompareOp.LESS,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
- columnsToRemove));
- k++;kk++;
- break;
- case LESS_NULL:
- linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
- new
BinaryPrefixComparator(new byte[]{0x00}),//check for null indicator = 0
representing non null
-
columnsToRemove,
- true),
//filterIfMissing,
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.LESS,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
-
columnsToRemove)));
- k++;kk++;
- break;
- case LESS_OR_EQUAL:
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.LESS_OR_EQUAL,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
- columnsToRemove));
- k++;kk++;
- break;
- case LESS_OR_EQUAL_NULL:
- linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
- new
BinaryPrefixComparator(new byte[]{0x00}),//check for null indicator = 0
representing non null
-
columnsToRemove,
- true),
//filterIfMissing,
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.LESS_OR_EQUAL,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
-
columnsToRemove)));
- k++;kk++;
- break;
- case GREATER:
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
- CompareOp.GREATER,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
- columnsToRemove));
- k++;kk++;
- break;
- case GREATER_NULL:
- linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
- new
BinaryPrefixComparator(new byte[]{0x00}),//check for null indicator = 0
representing non null
-
columnsToRemove,
- true),
//filterIfMissing,
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.GREATER,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
-
columnsToRemove)));
- k++;kk++;
- break;
- case GREATER_OR_EQUAL:
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.GREATER_OR_EQUAL,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
- columnsToRemove));
- k++;kk++;
- break;
- case GREATER_OR_EQUAL_NULL:
- linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
- new
BinaryPrefixComparator(new byte[]{0x00}),//check for null indicator = 0
representing non null
-
columnsToRemove,
- true),
//filterIfMissing,
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.GREATER_OR_EQUAL,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
-
columnsToRemove)));
- k++;kk++;
- break;
- case NO_OP:
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
- CompareOp.NO_OP,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
- columnsToRemove));
- k++;kk++;
- break;
- case NO_OP_NULL:
- linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
- new
BinaryPrefixComparator(new byte[]{0x00}),//check for null indicator = 0
representing non null
-
columnsToRemove,
- true),
//filterIfMissing,
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.NO_OP,
- new
BinaryComparator((byte[])colValuesToCompare[kk]),
-
columnsToRemove)));
- k++;kk++;
- break;
- case IS_NULL:
- // is null on a non nullable column!
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
- CompareOp.NO_OP,
//exclude everything
- new
BinaryPrefixComparator((new byte[]{})),
- columnsToRemove));
- k++;
- break;
- case IS_NULL_NULL:
- // is_null on nullable column: is
absent OR has the first byte set to FF indicating NULL.
- linkedList.addLast(
- new
FilterList(FilterList.Operator.MUST_PASS_ONE, //OR
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
-
new NullComparator(),//is absent?
-
columnsToRemove),
-
SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
-
CompareOp.EQUAL,
-
new BinaryPrefixComparator(new byte[]{-1}),//0xFF has null prefix
indicator
-
columnsToRemove)));
- k++;
- break;
- case IS_NOT_NULL:
- // is not null on a non nullable column!
- // do nothing, always true
- k++;
- break;
- case IS_NOT_NULL_NULL:
- // is_not_null on nullable column: is
not absent AND has the first byte not set to FF indicating NULL.
-
linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
-
(byte[])colNamesToFilter[k],
- CompareOp.NOT_EQUAL,
- new
BinaryPrefixComparator(new byte[]{-1}),// 0xFF has null prefix indicator
- columnsToRemove,
- true));//filter if
missing (if absent null)
- k++;
- break;
- case AND:
- linkedList.addLast("AND");
- break;
- case OR:
- linkedList.addLast("OR");
- break;
- default:
- }//switch
- }//for
- //evaluate the reverse polish notation list
- while (linkedList.size()>1){// evaluate until only one element
is left in the list
- //look for first operator (AND or OR)
- int j=0;
- while (j<linkedList.size() && !(linkedList.get(j)
instanceof String)){
- j++;
- }
- //here j points on the first operator; (all operands
are of type Filter)
- if
(j==linkedList.size()){logger.error("j==linkedList.size()");return null;} //
should not happen
- Filter leftOperand;
- Filter rightOperand;
- switch(Op.valueOf((String)linkedList.get(j))){
- case AND:
- FilterList filterListAnd = new
FilterList(FilterList.Operator.MUST_PASS_ALL); //AND filterList
- //left operand
- leftOperand = (Filter)linkedList.get(j-2);
- if (leftOperand instanceof FilterList &&
((FilterList)leftOperand).getOperator()==FilterList.Operator.MUST_PASS_ALL){//associativity
of AND optimization
- //for(Filter
f:((FilterList)leftOperand).getFilters())
- // filterListAnd.addFilter(f);
- filterListAnd =
(FilterList)leftOperand; //more efficient than the 2 lines above (kept
commented out for code lisibility)
- }else{
- filterListAnd.addFilter(leftOperand);
- }
- // right operand
- rightOperand = (Filter)linkedList.get(j-1);
- if (rightOperand instanceof FilterList &&
((FilterList)rightOperand).getOperator()==FilterList.Operator.MUST_PASS_ALL){//associativity
of AND optimization
- for(Filter
f:((FilterList)rightOperand).getFilters())
- filterListAnd.addFilter(f);
- }else{
- filterListAnd.addFilter(rightOperand);
- }
- // setup evaluated filter
- linkedList.set(j,filterListAnd); // replace the
operator with the constructer filter
- linkedList.remove(j-1);// remove right operand
- linkedList.remove(j-2);// remove left operand.
warning order matter
- break;
- case OR:
- FilterList filterListOr = new
FilterList(FilterList.Operator.MUST_PASS_ONE); //OR filterList
- leftOperand = (Filter)linkedList.get(j-2);
- rightOperand = (Filter)linkedList.get(j-1);
- //begin detection of null check factorization
(A not null and (A <op> ?)) or (A not null and A <op2> ?) -> A not null and (A
<op> ? or A <op2> ?)
- //the code is doing more than just nullcheck,
but any factorization where left operands are identical
- if (leftOperand instanceof FilterList &&
rightOperand instanceof FilterList &&
- ((FilterList)leftOperand).getOperator()
== FilterList.Operator.MUST_PASS_ALL &&
-
((FilterList)rightOperand).getOperator() == FilterList.Operator.MUST_PASS_ALL &&
-
((FilterList)leftOperand).getFilters().size() == 2 &&
-
((FilterList)rightOperand).getFilters().size() == 2 &&
-
((FilterList)leftOperand).getFilters().get(0) instanceof
SingleColumnValueFilter && //cannot be SingleColumnValueExcludeFilter when we
have the optimization scenario
-
((FilterList)rightOperand).getFilters().get(0) instanceof
SingleColumnValueFilter){//cannot be SingleColumnValueExcludeFilter when we
have the optimization scenario
- SingleColumnValueFilter scvfLeft =
(SingleColumnValueFilter)((FilterList)leftOperand).getFilters().get(0);
- SingleColumnValueFilter scvfRight =
(SingleColumnValueFilter)((FilterList)rightOperand).getFilters().get(0);
- if (scvfLeft.getOperator() ==
scvfRight.getOperator() && //more general case than just for null check
(identical operands)
-
Arrays.equals(scvfLeft.getQualifier(),scvfRight.getQualifier()) &&
-
Arrays.equals(scvfLeft.getFamily(),scvfRight.getFamily()) &&
-
Arrays.equals(scvfLeft.getComparator().getValue(),scvfRight.getComparator().getValue())
&&
- (scvfLeft.getFilterIfMissing()
== scvfRight.getFilterIfMissing())){
- Filter left =
((FilterList)leftOperand).getFilters().get(1);
- Filter right =
((FilterList)rightOperand).getFilters().get(1);
- if (left instanceof FilterList
&&
((FilterList)left).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
- //for(Filter
f:((FilterList)left).getFilters())
- //
filterListOr.addFilter(f);
- filterListOr =
(FilterList)left; // more efficient than the 2 lines above (kept commented out
for code lisibility)
- }else{
-
filterListOr.addFilter(left);
- }
- // right operand
- if (right instanceof FilterList
&&
((FilterList)right).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
- for(Filter
f:((FilterList)right).getFilters())
-
filterListOr.addFilter(f);
- }else{
-
filterListOr.addFilter(right);
- }
- linkedList.set(j,new
FilterList(FilterList.Operator.MUST_PASS_ALL,scvfLeft,filterListOr));//resulting
factorized AND filter
- linkedList.remove(j-1);//
remove right operand
- linkedList.remove(j-2);//
remove left operand. warning order matter
- break;
- }
- }
- //end detection of null (and more) check
factorization
- //begin detection of RangeSpec a<>? transformed
to a<? or a>? to convert it back to a <> ? when we push down
- //check for <> on non nullable columns
- if (leftOperand instanceof
SingleColumnValueFilter && rightOperand instanceof SingleColumnValueFilter){
- SingleColumnValueFilter leftscvf =
(SingleColumnValueFilter)leftOperand;
- SingleColumnValueFilter rightscvf =
(SingleColumnValueFilter)rightOperand;
- if (leftscvf.getOperator() ==
CompareOp.LESS && rightscvf.getOperator()== CompareOp.GREATER &&
-
Arrays.equals(leftscvf.getQualifier(), rightscvf.getQualifier()) &&
-
Arrays.equals(leftscvf.getFamily(), rightscvf.getFamily()) &&
-
Arrays.equals(leftscvf.getComparator().getValue(),rightscvf.getComparator().getValue())
- ){
- // setup evaluated filter
- linkedList.set(j,new
SingleColumnValueFilter(leftscvf.getFamily(), leftscvf.getQualifier(),
CompareOp.NOT_EQUAL, leftscvf.getComparator())); // replace the operator with
the constructer filter
- linkedList.remove(j-1);//
remove right operand
- linkedList.remove(j-2);//
remove left operand. warning order matter
- break;
- }
- }
- //check for <> on nullable column
- if( leftOperand instanceof FilterList &&
rightOperand instanceof FilterList){
- //no need to check FilterList size, as
all possible case FilterList size is at least 2.
- if
(((FilterList)leftOperand).getFilters().get(1) instanceof
SingleColumnValueFilter &&
-
((FilterList)rightOperand).getFilters().get(1) instanceof
SingleColumnValueFilter){
- SingleColumnValueFilter
leftscvf =
(SingleColumnValueFilter)((FilterList)leftOperand).getFilters().get(1);
- SingleColumnValueFilter
rightscvf =
(SingleColumnValueFilter)((FilterList)rightOperand).getFilters().get(1);
- if (leftscvf.getOperator() ==
CompareOp.LESS && rightscvf.getOperator()== CompareOp.GREATER &&
-
Arrays.equals(leftscvf.getQualifier(), rightscvf.getQualifier()) &&
-
Arrays.equals(leftscvf.getFamily(), rightscvf.getFamily()) &&
-
Arrays.equals(leftscvf.getComparator().getValue(),rightscvf.getComparator().getValue())
- ){
- // setup evaluated
filter
- SingleColumnValueFilter
nullCheck = new SingleColumnValueFilter(// null checker
-
leftscvf.getFamily(), leftscvf.getQualifier(),
-
CompareOp.EQUAL,
- new
BinaryPrefixComparator(new byte[]{0x00}));
-
nullCheck.setFilterIfMissing(true);
- linkedList.set(j,new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
-
nullCheck,
- new
SingleColumnValueFilter(
-
leftscvf.getFamily(), leftscvf.getQualifier(),
-
CompareOp.NOT_EQUAL,
-
leftscvf.getComparator())));
-
linkedList.remove(j-1);// remove right operand
-
linkedList.remove(j-2);// remove left operand. warning order matter
- break;
- }
- }
- }
- //end detection of RangeSpec a<>?
- //now general case...
- //left operand
- if (leftOperand instanceof FilterList &&
((FilterList)leftOperand).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
- //for(Filter
f:((FilterList)leftOperand).getFilters())
- // filterListOr.addFilter(f);
- filterListOr = (FilterList)leftOperand;
// more efficient than the 2 lines above (kept commented out for code
lisibility)
- }else{
- filterListOr.addFilter(leftOperand);
- }
- // right operand
- if (rightOperand instanceof FilterList &&
((FilterList)rightOperand).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
- for(Filter
f:((FilterList)rightOperand).getFilters())
- filterListOr.addFilter(f);
- }else{
- filterListOr.addFilter(rightOperand);
- }
- // setup evaluated filter
- linkedList.set(j,filterListOr); // replace the
operator with the constructer filter
- linkedList.remove(j-1);// remove right operand
- linkedList.remove(j-2);// remove left operand.
warning order matter
- break;
- default:
- logger.error("operator different than
OR or AND???");
- return null;//should never happen
- }
- }
- // after evaluation, the linkedList contains only one element
containing the filter built
- return (Filter)linkedList.pop();
- }
-
-
+ LinkedList linkedList = new LinkedList();
+ //populate the list with nodes in reverse polish notation order.
+ int k=0;//column index
+ int kk=0;//value index
+ for (int i=1; i<compareOpList.length; i++){ // skip first one
containing "V2" marker
+ String opStr = new String((byte[])compareOpList[i]);
+ switch(Op.valueOf(opStr)){
+
+ case EQUAL:
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove
+ ));
+ k++;kk++;
+ break;
+ case EQUAL_NULL:
+ linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}),//check for null indicator = 0 representing non null
+ columnsToRemove,
+ true //filterIfMissing
+ ),
+ SingleColumnValueExcludeOrNotFilter(
+
(byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove)));
+ k++;kk++;
+ break;
+ case NOT_EQUAL:
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.NOT_EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove));
+ k++;kk++;
+ break;
+ case NOT_EQUAL_NULL:
+ linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}),//check for null indicator = 0 representing non null
+ columnsToRemove,
+ true), //filterIfMissing,
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.NOT_EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove)));
+ k++;kk++;
+ break;
+ case LESS:
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.LESS,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove));
+ k++;kk++;
+ break;
+ case LESS_NULL:
+ linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}),//check for null indicator = 0 representing non null
+ columnsToRemove,
+ true), //filterIfMissing,
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.LESS,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove)));
+ k++;kk++;
+ break;
+ case LESS_OR_EQUAL:
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.LESS_OR_EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove));
+ k++;kk++;
+ break;
+ case LESS_OR_EQUAL_NULL:
+ linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}),//check for null indicator = 0 representing non null
+ columnsToRemove,
+ true), //filterIfMissing,
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.LESS_OR_EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove)));
+ k++;kk++;
+ break;
+ case GREATER:
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.GREATER,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove));
+ k++;kk++;
+ break;
+ case GREATER_NULL:
+ linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}),//check for null indicator = 0 representing non null
+ columnsToRemove,
+ true), //filterIfMissing,
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.GREATER,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove)));
+ k++;kk++;
+ break;
+ case GREATER_OR_EQUAL:
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.GREATER_OR_EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove));
+ k++;kk++;
+ break;
+ case GREATER_OR_EQUAL_NULL:
+ linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}),//check for null indicator = 0 representing non null
+ columnsToRemove,
+ true), //filterIfMissing,
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.GREATER_OR_EQUAL,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove)));
+ k++;kk++;
+ break;
+ case NO_OP:
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.NO_OP,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove));
+ k++;kk++;
+ break;
+ case NO_OP_NULL:
+ linkedList.addLast(new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}),//check for null indicator = 0 representing non null
+ columnsToRemove,
+ true), //filterIfMissing,
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.NO_OP,
+ new
BinaryComparator((byte[])colValuesToCompare[kk]),
+ columnsToRemove)));
+ k++;kk++;
+ break;
+ case IS_NULL:
+ // is null on a non nullable column!
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.NO_OP, //exclude everything
+ new BinaryPrefixComparator((new byte[]{})),
+ columnsToRemove));
+ k++;
+ break;
+ case IS_NULL_NULL:
+ // is_null on nullable column: is absent OR has the first
byte set to FF indicating NULL.
+ linkedList.addLast(
+ new FilterList(FilterList.Operator.MUST_PASS_ONE,
//OR
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new NullComparator(),//is absent?
+ columnsToRemove),
+ SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{-1}),//0xFF has null prefix indicator
+ columnsToRemove)));
+ k++;
+ break;
+ case IS_NOT_NULL:
+ // is not null on a non nullable column!
+ // do nothing, always true
+ k++;
+ break;
+ case IS_NOT_NULL_NULL:
+ // is_not_null on nullable column: is not absent AND has
the first byte not set to FF indicating NULL.
+ linkedList.addLast(SingleColumnValueExcludeOrNotFilter(
+ (byte[])colNamesToFilter[k],
+ CompareOp.NOT_EQUAL,
+ new BinaryPrefixComparator(new byte[]{-1}),// 0xFF
has null prefix indicator
+ columnsToRemove,
+ true));//filter if missing (if absent null)
+ k++;
+ break;
+ case AND:
+ linkedList.addLast("AND");
+ break;
+ case OR:
+ linkedList.addLast("OR");
+ break;
+ default:
+ }//switch
+ }//for
+ //evaluate the reverse polish notation list
+ while (linkedList.size()>1){// evaluate until only one element is left
in the list
+ //look for first operator (AND or OR)
+ int j=0;
+ while (j<linkedList.size() && !(linkedList.get(j) instanceof
String)){
+ j++;
+ }
+ //here j points on the first operator; (all operands are of type
Filter)
+ if
(j==linkedList.size()){logger.error("j==linkedList.size()");return null;} //
should not happen
+ Filter leftOperand;
+ Filter rightOperand;
+ switch(Op.valueOf((String)linkedList.get(j))){
+ case AND:
+ FilterList filterListAnd = new
FilterList(FilterList.Operator.MUST_PASS_ALL); //AND filterList
+ //left operand
+ leftOperand = (Filter)linkedList.get(j-2);
+ if (leftOperand instanceof FilterList &&
((FilterList)leftOperand).getOperator()==FilterList.Operator.MUST_PASS_ALL){//associativity
of AND optimization
+ //for(Filter f:((FilterList)leftOperand).getFilters())
+ // filterListAnd.addFilter(f);
+ filterListAnd = (FilterList)leftOperand; //more efficient
than the 2 lines above (kept commented out for code lisibility)
+ }else{
+ filterListAnd.addFilter(leftOperand);
+ }
+ // right operand
+ rightOperand = (Filter)linkedList.get(j-1);
+ if (rightOperand instanceof FilterList &&
((FilterList)rightOperand).getOperator()==FilterList.Operator.MUST_PASS_ALL){//associativity
of AND optimization
+ for(Filter f:((FilterList)rightOperand).getFilters())
+ filterListAnd.addFilter(f);
+ }else{
+ filterListAnd.addFilter(rightOperand);
+ }
+ // setup evaluated filter
+ linkedList.set(j,filterListAnd); // replace the operator with
the constructer filter
+ linkedList.remove(j-1);// remove right operand
+ linkedList.remove(j-2);// remove left operand. warning order
matter
+ break;
+ case OR:
+ FilterList filterListOr = new
FilterList(FilterList.Operator.MUST_PASS_ONE); //OR filterList
+ leftOperand = (Filter)linkedList.get(j-2);
+ rightOperand = (Filter)linkedList.get(j-1);
+ //begin detection of null check factorization (A not null and
(A <op> ?)) or (A not null and A <op2> ?) -> A not null and (A <op> ? or A
<op2> ?)
+ //the code is doing more than just nullcheck, but any
factorization where left operands are identical
+ if (leftOperand instanceof FilterList && rightOperand
instanceof FilterList &&
+ ((FilterList)leftOperand).getOperator() ==
FilterList.Operator.MUST_PASS_ALL &&
+ ((FilterList)rightOperand).getOperator() ==
FilterList.Operator.MUST_PASS_ALL &&
+ ((FilterList)leftOperand).getFilters().size() == 2 &&
+ ((FilterList)rightOperand).getFilters().size() == 2 &&
+ ((FilterList)leftOperand).getFilters().get(0) instanceof
SingleColumnValueFilter && //cannot be SingleColumnValueExcludeFilter when we
have the optimization scenario
+ ((FilterList)rightOperand).getFilters().get(0) instanceof
SingleColumnValueFilter){//cannot be SingleColumnValueExcludeFilter when we
have the optimization scenario
+ SingleColumnValueFilter scvfLeft =
(SingleColumnValueFilter)((FilterList)leftOperand).getFilters().get(0);
+ SingleColumnValueFilter scvfRight =
(SingleColumnValueFilter)((FilterList)rightOperand).getFilters().get(0);
+ if (scvfLeft.getOperator() == scvfRight.getOperator() &&
//more general case than just for null check (identical operands)
+
Arrays.equals(scvfLeft.getQualifier(),scvfRight.getQualifier()) &&
+
Arrays.equals(scvfLeft.getFamily(),scvfRight.getFamily()) &&
+
Arrays.equals(scvfLeft.getComparator().getValue(),scvfRight.getComparator().getValue())
&&
+ (scvfLeft.getFilterIfMissing() ==
scvfRight.getFilterIfMissing())){
+ Filter left =
((FilterList)leftOperand).getFilters().get(1);
+ Filter right =
((FilterList)rightOperand).getFilters().get(1);
+ if (left instanceof FilterList &&
((FilterList)left).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
+ //for(Filter f:((FilterList)left).getFilters())
+ // filterListOr.addFilter(f);
+ filterListOr = (FilterList)left; // more efficient
than the 2 lines above (kept commented out for code lisibility)
+ }else{
+ filterListOr.addFilter(left);
+ }
+ // right operand
+ if (right instanceof FilterList &&
((FilterList)right).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
+ for(Filter f:((FilterList)right).getFilters())
+ filterListOr.addFilter(f);
+ }else{
+ filterListOr.addFilter(right);
+ }
+ linkedList.set(j,new
FilterList(FilterList.Operator.MUST_PASS_ALL,scvfLeft,filterListOr));//resulting
factorized AND filter
+ linkedList.remove(j-1);// remove right operand
+ linkedList.remove(j-2);// remove left operand. warning
order matter
+ break;
+ }
+ }
+ //end detection of null (and more) check factorization
+ //begin detection of RangeSpec a<>? transformed to a<? or a>?
to convert it back to a <> ? when we push down
+ //check for <> on non nullable columns
+ if (leftOperand instanceof SingleColumnValueFilter &&
rightOperand instanceof SingleColumnValueFilter){
+ SingleColumnValueFilter leftscvf =
(SingleColumnValueFilter)leftOperand;
+ SingleColumnValueFilter rightscvf =
(SingleColumnValueFilter)rightOperand;
+ if (leftscvf.getOperator() == CompareOp.LESS &&
rightscvf.getOperator()== CompareOp.GREATER &&
+ Arrays.equals(leftscvf.getQualifier(),
rightscvf.getQualifier()) &&
+ Arrays.equals(leftscvf.getFamily(),
rightscvf.getFamily()) &&
+
Arrays.equals(leftscvf.getComparator().getValue(),rightscvf.getComparator().getValue())
+ ){
+ // setup evaluated filter
+ linkedList.set(j,new
SingleColumnValueFilter(leftscvf.getFamily(), leftscvf.getQualifier(),
CompareOp.NOT_EQUAL, leftscvf.getComparator())); // replace the operator with
the constructer filter
+ linkedList.remove(j-1);// remove right operand
+ linkedList.remove(j-2);// remove left operand. warning
order matter
+ break;
+ }
+ }
+ //check for <> on nullable column
+ if( leftOperand instanceof FilterList && rightOperand
instanceof FilterList){
+ //no need to check FilterList size, as all possible case
FilterList size is at least 2.
+ if (((FilterList)leftOperand).getFilters().get(1)
instanceof SingleColumnValueFilter &&
+ ((FilterList)rightOperand).getFilters().get(1)
instanceof SingleColumnValueFilter){
+ SingleColumnValueFilter leftscvf =
(SingleColumnValueFilter)((FilterList)leftOperand).getFilters().get(1);
+ SingleColumnValueFilter rightscvf =
(SingleColumnValueFilter)((FilterList)rightOperand).getFilters().get(1);
+ if (leftscvf.getOperator() == CompareOp.LESS &&
rightscvf.getOperator()== CompareOp.GREATER &&
+ Arrays.equals(leftscvf.getQualifier(),
rightscvf.getQualifier()) &&
+ Arrays.equals(leftscvf.getFamily(),
rightscvf.getFamily()) &&
+
Arrays.equals(leftscvf.getComparator().getValue(),rightscvf.getComparator().getValue())
+ ){
+ // setup evaluated filter
+ SingleColumnValueFilter nullCheck = new
SingleColumnValueFilter(// null checker
+ leftscvf.getFamily(),
leftscvf.getQualifier(),
+ CompareOp.EQUAL,
+ new BinaryPrefixComparator(new
byte[]{0x00}));
+ nullCheck.setFilterIfMissing(true);
+ linkedList.set(j,new
FilterList(FilterList.Operator.MUST_PASS_ALL, //AND between if not null and the
actual
+ nullCheck,
+ new SingleColumnValueFilter(
+ leftscvf.getFamily(),
leftscvf.getQualifier(),
+ CompareOp.NOT_EQUAL,
+ leftscvf.getComparator())));
+ linkedList.remove(j-1);// remove right operand
+ linkedList.remove(j-2);// remove left operand.
warning order matter
+ break;
+ }
+ }
+ }
+ //end detection of RangeSpec a<>?
+ //now general case...
+ //left operand
+ if (leftOperand instanceof FilterList &&
((FilterList)leftOperand).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
+ //for(Filter f:((FilterList)leftOperand).getFilters())
+ // filterListOr.addFilter(f);
+ filterListOr = (FilterList)leftOperand; // more efficient
than the 2 lines above (kept commented out for code lisibility)
+ }else{
+ filterListOr.addFilter(leftOperand);
+ }
+ // right operand
+ if (rightOperand instanceof FilterList &&
((FilterList)rightOperand).getOperator()==FilterList.Operator.MUST_PASS_ONE){//associativity
of OR optimization
+ for(Filter f:((FilterList)rightOperand).getFilters())
+ filterListOr.addFilter(f);
+ }else{
+ filterListOr.addFilter(rightOperand);
+ }
+ // setup evaluated filter
+ linkedList.set(j,filterListOr); // replace the operator with
the constructer filter
+ linkedList.remove(j-1);// remove right operand
+ linkedList.remove(j-2);// remove left operand. warning order
matter
+ break;
+ default:
+ logger.error("operator different than OR or AND???");
+ return null;//should never happen
+ }
+ }
+ // after evaluation, the linkedList contains only one element
containing the filter built
+ return (Filter)linkedList.pop();
+ }
+
+
public boolean startScan(long transID, byte[] startRow, byte[] stopRow,
Object[] columns, long timestamp,
boolean cacheBlocks, int numCacheRows,
@@ -839,140 +839,140 @@ public class HTableClient {
else
numColsInScan = 0;
if (colNamesToFilter != null) {
- FilterList list;
- boolean narrowDownResultColumns = false; //to check if we need
a narrow down column filter (V2 only feature)
- if (compareOpList == null)return false;
- if (new String((byte[])compareOpList[0]).equals("V2")){ // are
we dealing with predicate pushdown V2
- list = new
FilterList(FilterList.Operator.MUST_PASS_ALL);
- HashMap<String,Object> columnsToRemove = new
HashMap<String,Object>();
- //if columnsToRemove not null, we are narrowing down
using the SingleColumnValue[Exclude]Filter method
- //else we will use the explicit FamilyFilter and
QualifierFilter
- //the simplified logic is that we can use the first
method if and only if each and every column in the
- //pushed down predicate shows up only once.
- for (int i = 0; i < colNamesToFilter.length; i++) {
- byte[] colName = (byte[])colNamesToFilter[i];
-
- // check if the filter column is already part of the
column list, if not add it if we are limiting columns (not *)
- if(columns!=null && columns.length > 0){// if not *
- boolean columnAlreadyIn = false; //assume column not
yet in the scan object
- for (int k=0; k<columns.length;k++){
- if (Arrays.equals(colName,
(byte[])columns[k])){
- columnAlreadyIn = true;//found
already exist
- break;//no need to look further
- }
- }
- if (!columnAlreadyIn){// column was not already in,
so add it
-
scan.addColumn(getFamily(colName),getName(colName));
- narrowDownResultColumns = true; //since we
added a column for predicate eval, we need to remove it later out of result set
- String strColName = new String(colName);
- if (columnsToRemove != null &&
columnsToRemove.containsKey(strColName)){// if we already added this column, it
means it shows up more than once
- columnsToRemove = null; // therefore,
use the FamilyFilter/QualifierFilter method
- }else if (columnsToRemove != null)// else
- columnsToRemove.put(strColName,null);
// add it to the list of column that should be nuked with the Exclude version
of the SingleColumnValueFilter
- }
- }
- }
- if (columnsToRemove != null)
- { //we are almost done checking if Exclude version of
SingleColumnnValueFilter can be used. Th elast check s about to know if there
is a IS_NULL_NULL
- //operation that cannot be using the Exclude method, as
it is transformed in a filterList with OR, therefore we cannot guaranty that
the SingleColumnValueExcludeFilter
- //performing the exclusion will be reached.
- boolean is_null_nullFound = false;
- for (Object o:compareOpList ){
- if (new
String((byte[])o).equals("IS_NULL_NULL")){
- is_null_nullFound = true;
- break;
- }
- }
- if (is_null_nullFound){
- columnsToRemove = null; // disable Exclude
method version of SingleColumnnValueFilter
- }else
- narrowDownResultColumns = false; // we will use
the Exclude version of SingleColumnnValueFilter, so bypass the
Family/QualifierFilter method
- }
- Filter f
=constructV2Filter(colNamesToFilter,compareOpList,colValuesToCompare,
columnsToRemove);
- if (f==null) return false; // error logging done inside
constructV2Filter
- list.addFilter(f);
- }//end V2
- else{// deal with V1
- list = new FilterList(FilterList.Operator.MUST_PASS_ALL);
-
- for (int i = 0; i < colNamesToFilter.length; i++) {
- byte[] colName = (byte[])colNamesToFilter[i];
- byte[] coByte = (byte[])compareOpList[i];
- byte[] colVal = (byte[])colValuesToCompare[i];
-
- if ((coByte == null) || (colVal == null)) {
- return false;
- }
- String coStr = new String(coByte);
- CompareOp co = CompareOp.valueOf(coStr);
-
- SingleColumnValueFilter filter1 =
- new SingleColumnValueFilter(getFamily(colName),
getName(colName),
- co, colVal);
- list.addFilter(filter1);
- }
- }//end V1
- // if we added a column for predicate eval, we need to filter down
result columns
- FilterList resultColumnsOnlyFilter = null;
- if (narrowDownResultColumns){
- HashMap<String,ArrayList<byte[]>> hm = new
HashMap<String,ArrayList<byte[]>>(3);//use to deal with multiple family table
- // initialize hm with list of columns requested for output
- for (int i=0; i<columns.length; i++){ // if we are here
we know columns is not null
- if (hm.containsKey(new
String(getFamily((byte[])columns[i])))){
- hm.get(new
String(getFamily((byte[])columns[i]))).add((byte[])columns[i]);
- }else{
- ArrayList<byte[]> al = new
ArrayList<byte[]>();
- al.add((byte[])columns[i]);
- hm.put(new
String(getFamily((byte[])columns[i])), al);
- }
- }
-
- if (hm.size()==1){//only one column family
- resultColumnsOnlyFilter = new
FilterList(FilterList.Operator.MUST_PASS_ALL);
- if (columns.length == 1){
- resultColumnsOnlyFilter.addFilter(new
QualifierFilter(CompareOp.EQUAL, new
BinaryComparator(getName((byte[])columns[0]))));
- }else{// more than one column
- FilterList flColumns = new
FilterList(FilterList.Operator.MUST_PASS_ONE);
- for(int i=0; i<columns.length;i++)
- flColumns.addFilter(new
QualifierFilter(CompareOp.EQUAL, new
BinaryComparator(getName((byte[])columns[i]))));
- resultColumnsOnlyFilter.addFilter(flColumns);
- }
- // note the optimization puting family check at the end
- resultColumnsOnlyFilter.addFilter(new
FamilyFilter(CompareOp.EQUAL, new
BinaryComparator(getFamily((byte[])columns[0]))));
- }else{//more than one column family
- resultColumnsOnlyFilter = new
FilterList(FilterList.Operator.MUST_PASS_ONE);
- for (Map.Entry<String,ArrayList<byte[]>> entry :
hm.entrySet()){//for each column family
- ArrayList<byte[]> alb = entry.getValue();
- if (alb.size() == 1){// when only one column
for the family
- resultColumnsOnlyFilter.addFilter(
- new
FilterList(FilterList.Operator.MUST_PASS_ALL,
-
new QualifierFilter(CompareOp.EQUAL, new
BinaryComparator(getName(alb.get(0)))),
-
new FamilyFilter(CompareOp.EQUAL, new BinaryComparator(getFamily(alb.get(0)))))
- );
- }else{// when multiple columns for the family
- FamilyFilter familyFilter = null;
- FilterList filterListCol = new
FilterList(FilterList.Operator.MUST_PASS_ONE);
- for(int j = 0; j<alb.size(); j++){
- if (familyFilter == null)
- familyFilter = new
FamilyFilter(CompareOp.EQUAL, new BinaryComparator(getFamily(alb.get(0))));
- filterListCol.addFilter(new
QualifierFilter(CompareOp.EQUAL, new BinaryComparator(getName(alb.get(j)))));
- }
- resultColumnsOnlyFilter.addFilter(new
FilterList(FilterList.Operator.MUST_PASS_ALL,filterListCol,familyFilter));
- }
- }
- }
- list.addFilter(resultColumnsOnlyFilter); // add column limiting
filter
- }//end narrowDownResultColumns
+ FilterList list;
+ boolean narrowDownResultColumns = false; //to check if we need
a narrow down column filter (V2 only feature)
+ if (compareOpList == null)return false;
+ if (new String((byte[])compareOpList[0]).equals("V2")){ // are
we dealing with predicate pushdown V2
+ list = new FilterList(FilterList.Operator.MUST_PASS_ALL);
+ HashMap<String,Object> columnsToRemove = new
HashMap<String,Object>();
+ //if columnsToRemove not null, we are narrowing down using
the SingleColumnValue[Exclude]Filter method
+ //else we will use the explicit FamilyFilter and
QualifierFilter
+ //the simplified logic is that we can use the first method
if and only if each and every column in the
+ //pushed down predicate shows up only once.
+ for (int i = 0; i < colNamesToFilter.length; i++) {
+ byte[] colName = (byte[])colNamesToFilter[i];
+
+ // check if the filter column is already part of the
column list, if not add it if we are limiting columns (not *)
+ if(columns!=null && columns.length > 0){// if not *
+ boolean columnAlreadyIn = false; //assume column not
yet in the scan object
+ for (int k=0; k<columns.length;k++){
+ if (Arrays.equals(colName, (byte[])columns[k])){
+ columnAlreadyIn = true;//found already exist
+ break;//no need to look further
+ }
+ }
+ if (!columnAlreadyIn){// column was not already in,
so add it
+
scan.addColumn(getFamily(colName),getName(colName));
+ narrowDownResultColumns = true; //since we added
a column for predicate eval, we need to remove it later out of result set
+ String strColName = new String(colName);
+ if (columnsToRemove != null &&
columnsToRemove.containsKey(strColName)){// if we already added this column, it
means it shows up more than once
+ columnsToRemove = null; // therefore, use the
FamilyFilter/QualifierFilter method
+ }else if (columnsToRemove != null)// else
+ columnsToRemove.put(strColName,null); // add
it to the list of column that should be nuked with the Exclude version of the
SingleColumnValueFilter
+ }
+ }
+ }
+ if (columnsToRemove != null)
+ { //we are almost done checking if Exclude version of
SingleColumnnValueFilter can be used. Th elast check s about to know if there
is a IS_NULL_NULL
+ //operation that cannot be using the Exclude method, as
it is transformed in a filterList with OR, therefore we cannot guaranty that
the SingleColumnValueExcludeFilter
+ //performing the exclusion will be reached.
+ boolean is_null_nullFound = false;
+ for (Object o:compareOpList ){
+ if (new String((byte[])o).equals("IS_NULL_NULL")){
+ is_null_nullFound = true;
+ break;
+ }
+ }
+ if (is_null_nullFound){
+ columnsToRemove = null; // disable Exclude method
version of SingleColumnnValueFilter
+ }else
+ narrowDownResultColumns = false; // we will use the
Exclude version of SingleColumnnValueFilter, so bypass the
Family/QualifierFilter method
+ }
+ Filter f
=constructV2Filter(colNamesToFilter,compareOpList,colValuesToCompare,
columnsToRemove);
+ if (f==null) return false; // error logging done inside
constructV2Filter
+ list.addFilter(f);
+ }//end V2
+ else{// deal with V1
+ list = new FilterList(FilterList.Operator.MUST_PASS_ALL);
+
+ for (int i = 0; i < colNamesToFilter.length; i++) {
+ byte[] colName = (byte[])colNamesToFilter[i];
+ byte[] coByte = (byte[])compareOpList[i];
+ byte[] colVal = (byte[])colValuesToCompare[i];
+
+ if ((coByte == null) || (colVal == null)) {
+ return false;
+ }
+ String coStr = new String(coByte);
+ CompareOp co = CompareOp.valueOf(coStr);
+
+ SingleColumnValueFilter filter1 =
+ new SingleColumnValueFilter(getFamily(colName),
getName(colName),
+ co, colVal);
+ list.addFilter(filter1);
+ }
+ }//end V1
+ // if we added a column for predicate eval, we need to filter
down result columns
+ FilterList resultColumnsOnlyFilter = null;
+ if (narrowDownResultColumns){
+ HashMap<String,ArrayList<byte[]>> hm = new
HashMap<String,ArrayList<byte[]>>(3);//use to deal with multiple family table
+ // initialize hm with list of columns requested for output
+ for (int i=0; i<columns.length; i++){ // if we are here
we know columns is not null
+ if (hm.containsKey(new
String(getFamily((byte[])columns[i])))){
+ hm.get(new
String(getFamily((byte[])columns[i]))).add((byte[])columns[i]);
+ }else{
+ ArrayList<byte[]> al = new ArrayList<byte[]>();
+ al.add((byte[])columns[i]);
+ hm.put(new
String(getFamily((byte[])columns[i])), al);
+ }
+ }
+
+ if (hm.size()==1){//only one column family
+ resultColumnsOnlyFilter = new
FilterList(FilterList.Operator.MUST_PASS_ALL);
+ if (columns.length == 1){
+ resultColumnsOnlyFilter.addFilter(new
QualifierFilter(CompareOp.EQUAL, new
BinaryComparator(getName((byte[])columns[0]))));
+ }else{// more than one column
+ FilterList flColumns = new
FilterList(FilterList.Operator.MUST_PASS_ONE);
+ for(int i=0; i<columns.length;i++)
+ flColumns.addFilter(new
QualifierFilter(CompareOp.EQUAL, new
BinaryComparator(getName((byte[])columns[i]))));
+ resultColumnsOnlyFilter.addFilter(flColumns);
+ }
+ // note the optimization puting family check at the end
+ resultColumnsOnlyFilter.addFilter(new
FamilyFilter(CompareOp.EQUAL, new
BinaryComparator(getFamily((byte[])columns[0]))));
+ }else{//more than one column family
+ resultColumnsOnlyFilter = new
FilterList(FilterList.Operator.MUST_PASS_ONE);
+ for (Map.Entry<String,ArrayList<byte[]>> entry :
hm.entrySet()){//for each column family
+ ArrayList<byte[]> alb = entry.getValue();
+ if (alb.size() == 1){// when only one column for
the family
+ resultColumnsOnlyFilter.addFilter(
+ new
FilterList(FilterList.Operator.MUST_PASS_ALL,
+ new
QualifierFilter(CompareOp.EQUAL, new BinaryComparator(getName(alb.get(0)))),
+ new
FamilyFilter(CompareOp.EQUAL, new BinaryComparator(getFamily(alb.get(0)))))
+ );
+ }else{// when multiple columns for the family
+ FamilyFilter familyFilter = null;
+ FilterList filterListCol = new
FilterList(FilterList.Operator.MUST_PASS_ONE);
+ for(int j = 0; j<alb.size(); j++){
+ if (familyFilter == null)
+ familyFilter = new
FamilyFilter(CompareOp.EQUAL, new BinaryComparator(getFamily(alb.get(0))));
+ filterListCol.addFilter(new
QualifierFilter(CompareOp.EQUAL, new BinaryComparator(getName(alb.get(j)))));
+ }
+ resultColumnsOnlyFilter.addFilter(new
FilterList(FilterList.Operator.MUST_PASS_ALL,filterListCol,familyFilter));
+ }
+ }
+ }
+ list.addFilter(resultColumnsOnlyFilter); // add column
limiting filter
+ }//end narrowDownResultColumns
if (samplePercent > 0.0f)
list.addFilter(new RandomRowFilter(samplePercent));
- // last optimization is making sure we remove top level filter list
if it is singleton MUST_PASS_ALL filterlist
- if (list.getFilters().size()==1){
- scan.setFilter(list.getFilters().get(0));
- if (logger.isTraceEnabled()) logger.trace("Pushed down
filter:"+list.getFilters().get(0));
- }else{
+ // last optimization is making sure we remove top level filter list if
it is singleton MUST_PASS_ALL filterlist
+ if (list.getFilters().size()==1){
+ scan.setFilter(list.getFilters().get(0));
+ if (logger.isTraceEnabled()) logger.trace("Pushed down
filter:"+list.getFilters().get(0));
+ }else{
scan.setFilter(list);
- if (logger.isTraceEnabled()) logger.trace("Pushed down
filter:"+list );
- }
+ if (logger.isTraceEnabled()) logger.trace("Pushed down filter:"+list );
+ }
} else if (samplePercent > 0.0f) {
scan.setFilter(new RandomRowFilter(samplePercent));
}