HBASE-5257 Allow INCLUDE_AND_NEXT_COL in filters and use it in ColumnPaginationFilter (Varun)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1402209 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Zhihong Yu 2012-10-25 16:32:06 +00:00
parent 283746e49a
commit bd7c0c96f9
8 changed files with 84 additions and 7 deletions

View File

@ -59,7 +59,7 @@ public class ColumnCountGetFilter extends FilterBase {
@Override
public ReturnCode filterKeyValue(KeyValue v) {
this.count++;
return filterAllRemaining() ? ReturnCode.SKIP: ReturnCode.INCLUDE;
return filterAllRemaining() ? ReturnCode.NEXT_COL : ReturnCode.INCLUDE_AND_NEXT_COL;
}
@Override

View File

@ -32,7 +32,8 @@ import com.google.protobuf.InvalidProtocolBufferException;
/**
* A filter, based on the ColumnCountGetFilter, takes two arguments: limit and offset.
* This filter can be used for row-based indexing, where references to other tables are stored across many columns,
* in order to efficient lookups and paginated results for end users.
* in order to efficient lookups and paginated results for end users. Only most recent versions are considered
* for pagination.
*/
@InterfaceAudience.Public
@InterfaceStability.Stable
@ -72,7 +73,8 @@ public class ColumnPaginationFilter extends FilterBase
return ReturnCode.NEXT_ROW;
}
ReturnCode code = count < offset ? ReturnCode.SKIP : ReturnCode.INCLUDE;
ReturnCode code = count < offset ? ReturnCode.NEXT_COL :
ReturnCode.INCLUDE_AND_NEXT_COL;
count++;
return code;
}

View File

@ -115,6 +115,10 @@ public abstract class Filter {
* Include the KeyValue
*/
INCLUDE,
/**
* Include the KeyValue and seek to the next column skipping older versions.
*/
INCLUDE_AND_NEXT_COL,
/**
* Skip this KeyValue
*/

View File

@ -202,6 +202,9 @@ public class FilterList extends Filter {
}
ReturnCode code = filter.filterKeyValue(v);
switch (code) {
// Override INCLUDE and continue to evaluate.
case INCLUDE_AND_NEXT_COL:
rc = ReturnCode.INCLUDE_AND_NEXT_COL;
case INCLUDE:
continue;
default:
@ -214,7 +217,12 @@ public class FilterList extends Filter {
switch (filter.filterKeyValue(v)) {
case INCLUDE:
rc = ReturnCode.INCLUDE;
if (rc != ReturnCode.INCLUDE_AND_NEXT_COL) {
rc = ReturnCode.INCLUDE;
}
break;
case INCLUDE_AND_NEXT_COL:
rc = ReturnCode.INCLUDE_AND_NEXT_COL;
// must continue here to evaluate all filters
break;
case NEXT_ROW:

View File

@ -338,8 +338,9 @@ public class ScanQueryMatcher {
* counter for even that KV which may be discarded later on by Filter. This
* would lead to incorrect results in certain cases.
*/
ReturnCode filterResponse = ReturnCode.SKIP;
if (filter != null) {
ReturnCode filterResponse = filter.filterKeyValue(kv);
filterResponse = filter.filterKeyValue(kv);
if (filterResponse == ReturnCode.SKIP) {
return MatchCode.SKIP;
} else if (filterResponse == ReturnCode.NEXT_COL) {
@ -361,6 +362,9 @@ public class ScanQueryMatcher {
*/
if (colChecker == MatchCode.SEEK_NEXT_ROW) {
stickyNextRow = true;
} else if (filter != null && colChecker == MatchCode.INCLUDE &&
filterResponse == ReturnCode.INCLUDE_AND_NEXT_COL) {
return MatchCode.INCLUDE_AND_SEEK_NEXT_COL;
}
return colChecker;

View File

@ -76,7 +76,7 @@ public class TestColumnPaginationFilter
private void basicFilterTests(ColumnPaginationFilter filter) throws Exception
{
KeyValue kv = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_1);
assertTrue("basicFilter1", filter.filterKeyValue(kv) == Filter.ReturnCode.INCLUDE);
assertTrue("basicFilter1", filter.filterKeyValue(kv) == Filter.ReturnCode.INCLUDE_AND_NEXT_COL);
}
/**

View File

@ -1493,8 +1493,14 @@ public class TestFilter {
@Test
public void testColumnPaginationFilter() throws Exception {
// Test that the filter skips multiple column versions.
Put p = new Put(ROWS_ONE[0]);
p.setWriteToWAL(false);
p.add(FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]);
this.region.put(p);
this.region.flushcache();
// Set of KVs (page: 1; pageSize: 1) - the first set of 1 column per row
// Set of KVs (page: 1; pageSize: 1) - the first set of 1 column per row
KeyValue [] expectedKVs = {
// testRowOne-0
new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),

View File

@ -285,6 +285,59 @@ public class TestFilterList {
orderingTest(ProtobufUtil.toFilter(ProtobufUtil.toFilter(getOrderingFilter())));
}
/**
* Test filterKeyValue logic.
* @throws Exception
*/
public void testFilterKeyValue() throws Exception {
Filter includeFilter = new FilterBase() {
@Override
public Filter.ReturnCode filterKeyValue(KeyValue v) {
return Filter.ReturnCode.INCLUDE;
}
};
Filter alternateFilter = new FilterBase() {
boolean returnInclude = true;
@Override
public Filter.ReturnCode filterKeyValue(KeyValue v) {
Filter.ReturnCode returnCode = returnInclude ? Filter.ReturnCode.INCLUDE :
Filter.ReturnCode.SKIP;
returnInclude = !returnInclude;
return returnCode;
}
};
Filter alternateIncludeFilter = new FilterBase() {
boolean returnIncludeOnly = false;
@Override
public Filter.ReturnCode filterKeyValue(KeyValue v) {
Filter.ReturnCode returnCode = returnIncludeOnly ? Filter.ReturnCode.INCLUDE :
Filter.ReturnCode.INCLUDE_AND_NEXT_COL;
returnIncludeOnly = !returnIncludeOnly;
return returnCode;
}
};
// Check must pass one filter.
FilterList mpOnefilterList = new FilterList(Operator.MUST_PASS_ONE,
Arrays.asList(new Filter[] { includeFilter, alternateIncludeFilter, alternateFilter }));
// INCLUDE, INCLUDE, INCLUDE_AND_NEXT_COL.
assertEquals(Filter.ReturnCode.INCLUDE_AND_NEXT_COL, mpOnefilterList.filterKeyValue(null));
// INCLUDE, SKIP, INCLUDE.
assertEquals(Filter.ReturnCode.INCLUDE, mpOnefilterList.filterKeyValue(null));
// Check must pass all filter.
FilterList mpAllfilterList = new FilterList(Operator.MUST_PASS_ALL,
Arrays.asList(new Filter[] { includeFilter, alternateIncludeFilter, alternateFilter }));
// INCLUDE, INCLUDE, INCLUDE_AND_NEXT_COL.
assertEquals(Filter.ReturnCode.INCLUDE_AND_NEXT_COL, mpAllfilterList.filterKeyValue(null));
// INCLUDE, SKIP, INCLUDE.
assertEquals(Filter.ReturnCode.SKIP, mpAllfilterList.filterKeyValue(null));
}
/**
* Test pass-thru of hints.
*/