Index: hbase-server/src/main/java/org/apache/hadoop/hbase/filter/Filter.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/filter/Filter.java (revision 1373687) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/filter/Filter.java (working copy) @@ -23,6 +23,7 @@ import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.io.Writable; import java.util.List; @@ -167,4 +168,13 @@ * not sure which key to seek to next. */ public KeyValue getNextKeyHint(final KeyValue currentKV); + + + + /** + * To do the filtering sanity check before getScanner() + * @param scan + * + */ + public void sanityCheck(final Scan scan); } Index: hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterBase.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterBase.java (revision 1373687) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterBase.java (working copy) @@ -22,6 +22,7 @@ import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.client.Scan; import java.util.List; import java.util.ArrayList; @@ -133,6 +134,15 @@ public KeyValue getNextKeyHint(KeyValue currentKV) { return null; } + + + + /** + * The criteria defined in the filter is correct. + */ + @Override + public void sanityCheck(final Scan scan){ + } /** * Given the filter's arguments it constructs the filter Index: hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java (revision 1373687) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterList.java (working copy) @@ -24,6 +24,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.io.HbaseObjectWritable; import org.apache.hadoop.io.Writable; @@ -328,6 +329,13 @@ } return keyHint; } + + @Override + public void sanityCheck(Scan scan) { + for (Filter filter : filters) { + filter.sanityCheck(scan); + } + } @Override public String toString() { @@ -344,4 +352,5 @@ this.filters.size(), this.filters.subList(0, endIndex).toString()); } + } Index: hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterWrapper.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterWrapper.java (revision 1373687) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/filter/FilterWrapper.java (working copy) @@ -28,6 +28,7 @@ import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.client.Scan; /** * This is a Filter wrapper class which is used in the server side. Some filter @@ -111,5 +112,9 @@ kvs.clear(); } } + + public void sanityCheck(final Scan scan){ + this.filter.sanityCheck(scan); + } } \ No newline at end of file Index: hbase-server/src/main/java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java (revision 1373687) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java (working copy) @@ -34,8 +34,11 @@ import java.io.DataOutput; import java.io.IOException; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.NavigableSet; import com.google.common.base.Preconditions; @@ -79,6 +82,8 @@ private boolean matchedColumn = false; private boolean filterIfMissing = false; private boolean latestVersionOnly = true; + + private boolean toRemoveCriteriaColumn = false; /** * Writable constructor, do not use. @@ -301,6 +306,7 @@ this.matchedColumn = in.readBoolean(); this.filterIfMissing = in.readBoolean(); this.latestVersionOnly = in.readBoolean(); + this.toRemoveCriteriaColumn = in.readBoolean(); } public void write(final DataOutput out) throws IOException { @@ -313,6 +319,7 @@ out.writeBoolean(matchedColumn); out.writeBoolean(filterIfMissing); out.writeBoolean(latestVersionOnly); + out.writeBoolean(toRemoveCriteriaColumn); } @Override @@ -322,4 +329,51 @@ Bytes.toStringBinary(this.columnQualifier), this.compareOp.name(), Bytes.toStringBinary(this.comparator.getValue())); } + + + /** + * If the tested columns don't include criteria column, + * add the criteria column into the scan and + * mark toRemoveCriteriaColumn as true + */ + @Override + public void sanityCheck(final Scan scan){ + checkUnspecifiedQualifier(scan); + if( this.toRemoveCriteriaColumn ) { + // The following line will add one column if it is missing in the tested set + LOG.warn("Missing filtered Qualifier : " + new String(this.columnFamily) + ":" + + new String(this.columnQualifier) + " in the criteria."); + scan.addColumn(this.columnFamily, this.columnQualifier); + } + return ; + } + + @Override + public void filterRow(List ignored) { + Iterator it = ignored.iterator(); + while(it.hasNext()){ + KeyValue kv = it.next(); + if(this.toRemoveCriteriaColumn && + kv.matchingColumn(this.columnFamily, this.columnQualifier)) { + LOG.debug("REMOVE KEY=" + kv.toString() + ", value=" + Bytes.toString(kv.getValue())); + it.remove(); + } + } + } + + private void checkUnspecifiedQualifier(final Scan scan){ + Map> cols = scan.getFamilyMap(); + for( byte[] columnfamily : cols.keySet() ) { + if( (cols.get(columnfamily) != null && cols.get(columnfamily).size() != 0 ) + && Bytes.equals(this.columnFamily, columnfamily) ){ + this.toRemoveCriteriaColumn = true; + Iterator it = cols.get(columnfamily).iterator(); + while(it.hasNext()){ + if(Bytes.equals(this.columnQualifier, it.next())){ + this.toRemoveCriteriaColumn = false; + } + } + } + } + } } Index: hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (revision 1373687) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (working copy) @@ -3444,6 +3444,8 @@ } this.batch = scan.getBatch(); + if(this.filter!=null) filter.sanityCheck(scan); + if (Bytes.equals(scan.getStopRow(), HConstants.EMPTY_END_ROW)) { this.stopRow = null; } else {