Index: test/org/apache/hadoop/hbase/filter/TestSingleColumnValueFilter.java =================================================================== --- test/org/apache/hadoop/hbase/filter/TestSingleColumnValueFilter.java (revision 834993) +++ test/org/apache/hadoop/hbase/filter/TestSingleColumnValueFilter.java (working copy) @@ -77,7 +77,7 @@ new RegexStringComparator(QUICK_REGEX)); } - private void basicFilterTests(Filter filter) + private void basicFilterTests(SingleColumnValueFilter filter) throws Exception { KeyValue kv = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2); assertTrue("basicFilter1", filter.filterKeyValue(kv) == Filter.ReturnCode.INCLUDE); @@ -93,6 +93,13 @@ assertTrue("basicFilter4", filter.filterKeyValue(kv) == Filter.ReturnCode.NEXT_ROW); assertFalse("basicFilterAllRemaining", filter.filterAllRemaining()); assertTrue("basicFilterNotNull", filter.filterRow()); + filter.reset(); + filter.setLatestVersionOnly(false); + kv = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_1); + assertTrue("basicFilter5", filter.filterKeyValue(kv) == Filter.ReturnCode.INCLUDE); + kv = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2); + assertTrue("basicFilter5", filter.filterKeyValue(kv) == Filter.ReturnCode.INCLUDE); + assertFalse("basicFilterNotNull", filter.filterRow()); } private void substrFilterTests(Filter filter) @@ -144,7 +151,7 @@ * @throws Exception */ public void testStop() throws Exception { - basicFilterTests(basicFilter); + basicFilterTests((SingleColumnValueFilter)basicFilter); substrFilterTests(substrFilter); regexFilterTests(regexFilter); } @@ -155,10 +162,10 @@ */ public void testSerialization() throws Exception { Filter newFilter = serializationTest(basicFilter); - basicFilterTests(newFilter); + basicFilterTests((SingleColumnValueFilter)newFilter); newFilter = serializationTest(substrFilter); substrFilterTests(newFilter); newFilter = serializationTest(regexFilter); regexFilterTests(newFilter); } -} \ No newline at end of file +} Index: java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java =================================================================== --- java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java (revision 834993) +++ java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java (working copy) @@ -48,10 +48,13 @@ *

* To prevent the entire row from being emitted if the column is not found * on a row, use {@link #setFilterIfMissing}. - *

* Otherwise, if the column is found, the entire row will be emitted only if * the value passes. If the value fails, the row will be filtered out. *

+ * In order to test values of previous versions (timestamps), set + * {@link #setLatestVersionOnly} to false. The default is true, meaning that + * only the latest version's value is tested and all previous versions are ignored. + *

* To filter based on the value of all scanned columns, use {@link ValueFilter}. */ public class SingleColumnValueFilter implements Filter { @@ -64,7 +67,8 @@ private boolean foundColumn = false; private boolean matchedColumn = false; private boolean filterIfMissing = false; - + private boolean latestVersionOnly = true; + /** * Writable constructor, do not use. */ @@ -120,7 +124,7 @@ if (this.matchedColumn) { // We already found and matched the single column, all keys now pass return ReturnCode.INCLUDE; - } else if (this.foundColumn) { + } else if (this.latestVersionOnly && this.foundColumn) { // We found but did not match the single column, skip to next row return ReturnCode.NEXT_ROW; } @@ -130,7 +134,7 @@ foundColumn = true; if (filterColumnValue(keyValue.getBuffer(), keyValue.getValueOffset(), keyValue.getValueLength())) { - return ReturnCode.NEXT_ROW; + return this.latestVersionOnly? ReturnCode.NEXT_ROW: ReturnCode.INCLUDE; } this.matchedColumn = true; return ReturnCode.INCLUDE; @@ -196,6 +200,26 @@ this.filterIfMissing = filterIfMissing; } + /** + * Get whether only the latest version of the column value should be compared. + * If true, the row will be returned if only the latest version of the column + * value matches. If false, the row will be returned if any version of the + * column value matches. The default is true. + */ + public boolean getLatestVersionOnly() { + return latestVersionOnly; + } + + /** + * Set whether only the latest version of the column value should be compared. + * If true, the row will be returned if only the latest version of the column + * value matches. If false, the row will be returned if any version of the + * column value matches. The default is true. + */ + public void setLatestVersionOnly(boolean latestVersionOnly) { + this.latestVersionOnly = latestVersionOnly; + } + public void readFields(final DataInput in) throws IOException { this.columnFamily = Bytes.readByteArray(in); if(this.columnFamily.length == 0) { @@ -211,6 +235,7 @@ this.foundColumn = in.readBoolean(); this.matchedColumn = in.readBoolean(); this.filterIfMissing = in.readBoolean(); + this.latestVersionOnly = in.readBoolean(); } public void write(final DataOutput out) throws IOException { @@ -222,5 +247,6 @@ out.writeBoolean(foundColumn); out.writeBoolean(matchedColumn); out.writeBoolean(filterIfMissing); + out.writeBoolean(latestVersionOnly); } -} \ No newline at end of file +}