Index: src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java (revision 1497740) +++ src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java (working copy) @@ -296,7 +296,11 @@ || kv.getMemstoreTS() > maxReadPointToTrackVersions) { // always include or it is not time yet to check whether it is OK // to purge deltes or not - return MatchCode.INCLUDE; + if (!isUserScan) { + // if this is a user scan (i.e. a "raw" scan), + // fall through to normal version and timerange checking. + return MatchCode.INCLUDE; + } } else if (keepDeletedCells) { if (timestamp < earliestPutTs) { // keeping delete rows, but there are no puts older than Index: src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java (revision 1497740) +++ src/test/java/org/apache/hadoop/hbase/regionserver/TestKeepDeletes.java (working copy) @@ -276,16 +276,16 @@ p.add(c0, c0, T3); region.put(p); - Delete d = new Delete(T1, ts+1, null); - region.delete(d, null, true); + Delete d = new Delete(T1, ts+1); + region.delete(d, true); - d = new Delete(T1, ts+2, null); + d = new Delete(T1, ts+2); d.deleteColumn(c0, c0, ts+2); - region.delete(d, null, true); + region.delete(d, true); - d = new Delete(T1, ts+3, null); + d = new Delete(T1, ts+3); d.deleteColumns(c0, c0, ts+3); - region.delete(d, null, true); + region.delete(d, true); Scan s = new Scan(); s.setRaw(true); @@ -293,13 +293,55 @@ InternalScanner scan = region.getScanner(s); List kvs = new ArrayList(); scan.next(kvs); + assertEquals(8, kvs.size()); assertTrue(kvs.get(0).isDeleteFamily()); assertEquals(kvs.get(1).getValue(), T3); assertTrue(kvs.get(2).isDelete()); assertTrue(kvs.get(3).isDeleteType()); assertEquals(kvs.get(4).getValue(), T2); assertEquals(kvs.get(5).getValue(), T1); + // we have 3 CFs, so there are two more delete markers + assertTrue(kvs.get(6).isDeleteFamily()); + assertTrue(kvs.get(7).isDeleteFamily()); + // verify that raw scans honor the passed timerange + s = new Scan(); + s.setRaw(true); + s.setMaxVersions(); + s.setTimeRange(0, 1); + scan = region.getScanner(s); + kvs = new ArrayList(); + scan.next(kvs); + // nothing in this interval, not even delete markers + assertTrue(kvs.isEmpty()); + + // filter new delete markers + s = new Scan(); + s.setRaw(true); + s.setMaxVersions(); + s.setTimeRange(0, ts+2); + scan = region.getScanner(s); + kvs = new ArrayList(); + scan.next(kvs); + assertEquals(4, kvs.size()); + assertTrue(kvs.get(0).isDeleteFamily()); + assertEquals(kvs.get(1).getValue(), T1); + // we have 3 CFs + assertTrue(kvs.get(2).isDeleteFamily()); + assertTrue(kvs.get(3).isDeleteFamily()); + + // filter old delete markers + s = new Scan(); + s.setRaw(true); + s.setMaxVersions(); + s.setTimeRange(ts+3, ts+5); + scan = region.getScanner(s); + kvs = new ArrayList(); + scan.next(kvs); + assertEquals(2, kvs.size()); + assertEquals(kvs.get(0).getValue(), T3); + assertTrue(kvs.get(1).isDelete()); + region.close(); region.getLog().closeAndDelete(); }