Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -644,9 +644,13 @@ static byte[] getNextForFuzzyRule(boolean reverse, byte[] row, int offset, int l

byte[] trailingZerosTrimmed = trimTrailingZeroes(result, fuzzyKeyMeta, toInc);
if (reverse) {
// In the reverse case we increase last non-max byte to make sure that the proper row is
// selected next.
return PrivateCellUtil.increaseLastNonMaxByte(trailingZerosTrimmed);
// In the reverse case we usually increase last non-max byte to make sure that the proper row
// is selected next.
byte[] nextRowKeyCandidate = PrivateCellUtil.increaseLastNonMaxByte(trailingZerosTrimmed);
// If the adjusted hint is the current row, return the unadjusted candidate so the hint moves.
return Bytes.equals(row, offset, length, nextRowKeyCandidate, 0, nextRowKeyCandidate.length)
? trailingZerosTrimmed
: nextRowKeyCandidate;
} else {
return trailingZerosTrimmed;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ public void testGetNextForFuzzyRuleReverse() {
assertNext(true, new byte[] { 0, 1, 0, 0 }, // fuzzy row
new byte[] { 0, -1, 0, 0 }, // mask
new byte[] { 5, 1, (byte) 255, 1 }, // current
new byte[] { 5, 1, (byte) 255, 1 }); // expected next
new byte[] { 5, 1, (byte) 255, 0 }); // expected next
Comment on lines 265 to +268

assertNext(true, new byte[] { 0, 1, 0, 1 }, // fuzzy row
new byte[] { 0, -1, 0, -1 }, // mask
Expand Down Expand Up @@ -305,27 +305,27 @@ public void testGetNextForFuzzyRuleReverse() {
assertNext(true, new byte[] { 1, 0, 1 }, // fuzzy row
new byte[] { -1, 0, -1 }, // mask
new byte[] { 1, (byte) 128, 2 }, // row to check
new byte[] { 1, (byte) 128, 2 }); // expected next
new byte[] { 1, (byte) 128, 1 }); // expected next

assertNext(true, new byte[] { 0, 1, 0, 1 }, // fuzzy row
new byte[] { 0, -1, 0, -1 }, // mask
new byte[] { 5, 1, 0, 2 }, // row to check
new byte[] { 5, 1, 0, 2 }); // expected next
new byte[] { 5, 1, 0, 1 }); // expected next

assertNext(true, new byte[] { 5, 1, 1, 0 }, // fuzzy row
new byte[] { -1, -1, 0, 0 }, // mask
new byte[] { 5, 1, (byte) 0xFF, 1 }, // row to check
new byte[] { 5, 1, (byte) 0xFF, 1 }); // expected next
new byte[] { 5, 1, (byte) 0xFF, 0 }); // expected next

assertNext(true, new byte[] { 1, 1, 1, 1 }, // fuzzy row
new byte[] { -1, -1, 0, 0 }, // mask
new byte[] { 1, 1, 2, 2 }, // row to check
new byte[] { 1, 1, 2, 2 }); // expected next
new byte[] { 1, 1, 2, 1 }); // expected next

assertNext(true, new byte[] { 1, 1, 1, 1 }, // fuzzy row
new byte[] { 0, 0, 0, 0 }, // mask
new byte[] { 1, 1, 2, 3 }, // row to check
new byte[] { 1, 1, 2, 3 }); // expected next
new byte[] { 1, 1, 2, 2 }); // expected next

// no before cell than current which satisfies the fuzzy row -> null
assertNull(FuzzyRowFilter.getNextForFuzzyRule(true, new byte[] { 1, 1, 1, 3, 0 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.hadoop.hbase.filter;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.io.IOException;
Expand Down Expand Up @@ -330,6 +331,47 @@ public void testHBASE26967(TestInfo testInfo) throws IOException {
TEST_UTIL.deleteTable(TableName.valueOf(name));
}

@Test
public void testReverseScanMovesPastSameRowFuzzyHint(TestInfo testInfo) throws IOException {
final String cf = "f";
final String cq = "q";

String name = testInfo.getTestMethod().orElseThrow(AssertionError::new).getName();
try (Table ht = TEST_UTIL.createTable(TableName.valueOf(name), Bytes.toBytes(cf))) {
List<Put> puts = Lists.newArrayList();
puts.add(new Put(Bytes.toBytes("aaa")).addColumn(Bytes.toBytes(cf), Bytes.toBytes(cq),
Bytes.toBytes("v")));
puts.add(new Put(Bytes.toBytes("aba")).addColumn(Bytes.toBytes(cf), Bytes.toBytes(cq),
Bytes.toBytes("v")));
puts.add(new Put(Bytes.toBytes("abb")).addColumn(Bytes.toBytes(cf), Bytes.toBytes(cq),
Bytes.toBytes("v")));
puts.add(new Put(Bytes.toBytes("abc")).addColumn(Bytes.toBytes(cf), Bytes.toBytes(cq),
Bytes.toBytes("v")));
ht.put(puts);

TEST_UTIL.flush();

List<Pair<byte[], byte[]>> fuzzyList = new LinkedList<>();
fuzzyList.add(new Pair<>(Bytes.toBytes("aaa"), new byte[] { 0, 1, 0 }));

Scan scan = new Scan();
scan.setReversed(true);
scan.setFilter(new FuzzyRowFilter(fuzzyList));

try (ResultScanner scanner = ht.getScanner(scan)) {
Result result = scanner.next();
assertNotNull(result);
assertEquals("aba", Bytes.toString(result.getRow()));
result = scanner.next();
assertNotNull(result);
assertEquals("aaa", Bytes.toString(result.getRow()));
assertNull(scanner.next());
}
}

TEST_UTIL.deleteTable(TableName.valueOf(name));
}

@Test
public void testHBASE28634(TestInfo testInfo) throws IOException {
final String CF = "f";
Expand Down
Loading