Skip to content

Commit f6b74b3

Browse files
authored
HBASE-26762 Un-Deprecate and improve documentation for Scan#setRowPrefixFilter (#4119)
Signed-off-by: Andrew Purtell <apurtell@apache.org> Signed-off-by: Duo Zhang <zhangduo@apache.org>
1 parent e85bf41 commit f6b74b3

File tree

8 files changed

+68
-78
lines changed

8 files changed

+68
-78
lines changed

hbase-client/src/main/java/org/apache/hadoop/hbase/client/ImmutableScan.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ public Scan withStopRow(byte[] stopRow, boolean inclusive) {
9595
}
9696

9797
@Override
98-
public Scan setRowPrefixFilter(byte[] rowPrefix) {
98+
public Scan setStartStopRowForPrefixScan(byte[] rowPrefix) {
9999
throw new UnsupportedOperationException(
100-
"ImmutableScan does not allow access to setRowPrefixFilter");
100+
"ImmutableScan does not allow access to setStartStopRowForPrefixScan");
101101
}
102102

103103
@Override

hbase-client/src/main/java/org/apache/hadoop/hbase/client/Scan.java

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,11 @@ public Scan setTimestamp(long timestamp) {
339339
* <p>
340340
* If the specified row does not exist, the Scanner will start from the next closest row after the
341341
* specified row.
342+
* <p>
343+
* <b>Note:</b> <strong>Do NOT use this in combination with
344+
* {@link #setRowPrefixFilter(byte[])} or {@link #setStartStopRowForPrefixScan(byte[])}.</strong>
345+
* Doing so will make the scan result unexpected or even undefined.
346+
* </p>
342347
* @param startRow row to start scanner at or after
343348
* @return this
344349
* @throws IllegalArgumentException if startRow does not meet criteria for a row key (when length
@@ -354,7 +359,9 @@ public Scan withStartRow(byte[] startRow) {
354359
* If the specified row does not exist, or the {@code inclusive} is {@code false}, the Scanner
355360
* will start from the next closest row after the specified row.
356361
* <p>
357-
* <b>Note:</b> When use {@link #setRowPrefixFilter(byte[])}, the result might be unexpected.
362+
* <b>Note:</b> <strong>Do NOT use this in combination with
363+
* {@link #setRowPrefixFilter(byte[])} or {@link #setStartStopRowForPrefixScan(byte[])}.</strong>
364+
* Doing so will make the scan result unexpected or even undefined.
358365
* </p>
359366
* @param startRow row to start scanner at or after
360367
* @param inclusive whether we should include the start row when scan
@@ -377,8 +384,9 @@ public Scan withStartRow(byte[] startRow, boolean inclusive) {
377384
* <p>
378385
* The scan will include rows that are lexicographically less than the provided stopRow.
379386
* <p>
380-
* <b>Note:</b> When doing a filter for a rowKey <u>Prefix</u> use
381-
* {@link #setRowPrefixFilter(byte[])}. The 'trailing 0' will not yield the desired result.
387+
* <b>Note:</b> <strong>Do NOT use this in combination with
388+
* {@link #setRowPrefixFilter(byte[])} or {@link #setStartStopRowForPrefixScan(byte[])}.</strong>
389+
* Doing so will make the scan result unexpected or even undefined.
382390
* </p>
383391
* @param stopRow row to end at (exclusive)
384392
* @return this
@@ -394,6 +402,11 @@ public Scan withStopRow(byte[] stopRow) {
394402
* <p>
395403
* The scan will include rows that are lexicographically less than (or equal to if
396404
* {@code inclusive} is {@code true}) the provided stopRow.
405+
* <p>
406+
* <b>Note:</b> <strong>Do NOT use this in combination with
407+
* {@link #setRowPrefixFilter(byte[])} or {@link #setStartStopRowForPrefixScan(byte[])}.</strong>
408+
* Doing so will make the scan result unexpected or even undefined.
409+
* </p>
397410
* @param stopRow row to end at
398411
* @param inclusive whether we should include the stop row when scan
399412
* @return this
@@ -416,18 +429,32 @@ public Scan withStopRow(byte[] stopRow, boolean inclusive) {
416429
* <p>This is a utility method that converts the desired rowPrefix into the appropriate values
417430
* for the startRow and stopRow to achieve the desired result.</p>
418431
* <p>This can safely be used in combination with setFilter.</p>
419-
* <p><b>NOTE: Doing a {@link #withStartRow(byte[])} and/or {@link #withStopRow(byte[])}
420-
* after this method will yield undefined results.</b></p>
432+
* <p><strong>This CANNOT be used in combination with withStartRow and/or withStopRow.</strong>
433+
* Such a combination will yield unexpected and even undefined results.</p>
421434
* @param rowPrefix the prefix all rows must start with. (Set <i>null</i> to remove the filter.)
422435
* @return this
423-
* @deprecated since 3.0.0. The scan result might be unexpected in some cases.
424-
* e.g. startRow : "112" and rowPrefixFilter : "11"
425-
* The Result of this scan might contains : "111"
426-
* This method implements the filter by setting startRow and stopRow,
427-
* but does not take care of the scenario where startRow has been set.
436+
* @deprecated since 2.5.0, will be removed in 4.0.0.
437+
* The name of this method is considered to be confusing as it does not
438+
* use a {@link Filter} but uses setting the startRow and stopRow instead.
439+
* Use {@link #setStartStopRowForPrefixScan(byte[])} instead.
428440
*/
429441
@Deprecated
430442
public Scan setRowPrefixFilter(byte[] rowPrefix) {
443+
return setStartStopRowForPrefixScan(rowPrefix);
444+
}
445+
446+
/**
447+
* <p>Set a filter (using stopRow and startRow) so the result set only contains rows where the
448+
* rowKey starts with the specified prefix.</p>
449+
* <p>This is a utility method that converts the desired rowPrefix into the appropriate values
450+
* for the startRow and stopRow to achieve the desired result.</p>
451+
* <p>This can safely be used in combination with setFilter.</p>
452+
* <p><strong>This CANNOT be used in combination with withStartRow and/or withStopRow.</strong>
453+
* Such a combination will yield unexpected and even undefined results.</p>
454+
* @param rowPrefix the prefix all rows must start with. (Set <i>null</i> to remove the filter.)
455+
* @return this
456+
*/
457+
public Scan setStartStopRowForPrefixScan(byte[] rowPrefix) {
431458
if (rowPrefix == null) {
432459
withStartRow(HConstants.EMPTY_START_ROW);
433460
withStopRow(HConstants.EMPTY_END_ROW);

hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ public static Scan makeQuotaSnapshotScanForTable(TableName tn) {
288288
// Limit to "u:v" column
289289
s.addColumn(QUOTA_FAMILY_USAGE, QUOTA_QUALIFIER_POLICY);
290290
if (null == tn) {
291-
s.setRowPrefixFilter(QUOTA_TABLE_ROW_KEY_PREFIX);
291+
s.setStartStopRowForPrefixScan(QUOTA_TABLE_ROW_KEY_PREFIX);
292292
} else {
293293
byte[] row = getTableRowKey(tn);
294294
// Limit rowspace to the "t:" prefix
@@ -637,7 +637,8 @@ static void deleteTableUsageSnapshotsForNamespace(Connection connection, String
637637
throws IOException {
638638
Scan s = new Scan();
639639
//Get rows for all tables in namespace
640-
s.setRowPrefixFilter(Bytes.add(QUOTA_TABLE_ROW_KEY_PREFIX, Bytes.toBytes(namespace + TableName.NAMESPACE_DELIM)));
640+
s.setStartStopRowForPrefixScan(
641+
Bytes.add(QUOTA_TABLE_ROW_KEY_PREFIX, Bytes.toBytes(namespace + TableName.NAMESPACE_DELIM)));
641642
//Scan for table usage column (u:p) in quota table
642643
s.addColumn(QUOTA_FAMILY_USAGE,QUOTA_QUALIFIER_POLICY);
643644
//Scan for table quota column (q:s) if table has a space quota defined
@@ -706,7 +707,7 @@ static Scan createScanForNamespaceSnapshotSizes(String namespace) {
706707
Scan s = new Scan();
707708
if (namespace == null || namespace.isEmpty()) {
708709
// Read all namespaces, just look at the row prefix
709-
s.setRowPrefixFilter(QUOTA_NAMESPACE_ROW_KEY_PREFIX);
710+
s.setStartStopRowForPrefixScan(QUOTA_NAMESPACE_ROW_KEY_PREFIX);
710711
} else {
711712
// Fetch the exact row for the table
712713
byte[] rowkey = getNamespaceRowKey(namespace);
@@ -727,7 +728,7 @@ static Scan createScanForSpaceSnapshotSizes(TableName table) {
727728
Scan s = new Scan();
728729
if (null == table) {
729730
// Read all tables, just look at the row prefix
730-
s.setRowPrefixFilter(QUOTA_TABLE_ROW_KEY_PREFIX);
731+
s.setStartStopRowForPrefixScan(QUOTA_TABLE_ROW_KEY_PREFIX);
731732
} else {
732733
// Fetch the exact row for the table
733734
byte[] rowkey = getTableRowKey(table);

hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestImmutableScan.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public void testScanCopyConstructor() throws Exception {
8484
.setReplicaId(3)
8585
.setReversed(true)
8686
.setRowOffsetPerColumnFamily(5)
87-
.setRowPrefixFilter(Bytes.toBytes("row_"))
87+
.setStartStopRowForPrefixScan(Bytes.toBytes("row_"))
8888
.setScanMetricsEnabled(true)
8989
.setReadType(Scan.ReadType.STREAM)
9090
.withStartRow(Bytes.toBytes("row_1"))
@@ -181,10 +181,11 @@ private void testUnmodifiableSetters(Scan scanCopy) throws IOException {
181181
assertEquals("ImmutableScan does not allow access to withStopRow", e.getMessage());
182182
}
183183
try {
184-
scanCopy.setRowPrefixFilter(new byte[] { 1, 2 });
184+
scanCopy.setStartStopRowForPrefixScan(new byte[] { 1, 2 });
185185
throw new RuntimeException("Should not reach here");
186186
} catch (UnsupportedOperationException e) {
187-
assertEquals("ImmutableScan does not allow access to setRowPrefixFilter", e.getMessage());
187+
assertEquals("ImmutableScan does not allow access to setStartStopRowForPrefixScan",
188+
e.getMessage());
188189
}
189190
try {
190191
scanCopy.readAllVersions();

hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public void testScanCopyConstructor() throws Exception {
246246
.setReplicaId(3)
247247
.setReversed(true)
248248
.setRowOffsetPerColumnFamily(5)
249-
.setRowPrefixFilter(Bytes.toBytes("row_"))
249+
.setStartStopRowForPrefixScan(Bytes.toBytes("row_"))
250250
.setScanMetricsEnabled(true)
251251
.setReadType(ReadType.STREAM)
252252
.withStartRow(Bytes.toBytes("row_1"))

hbase-server/src/test/java/org/apache/hadoop/hbase/filter/TestScanRowPrefix.java

Lines changed: 16 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
import org.slf4j.LoggerFactory;
4343

4444
/**
45-
* Test if Scan.setRowPrefixFilter works as intended.
45+
* Test if Scan.setStartStopRowForPrefixScan works as intended.
4646
*/
4747
@Category({FilterTests.class, MediumTests.class})
4848
public class TestScanRowPrefix extends FilterTestingCluster {
@@ -64,8 +64,8 @@ public void testPrefixScanning() throws IOException {
6464
Table table = openTable(tableName);
6565

6666
/**
67-
* Note that about half of these tests were relevant for an different implementation approach
68-
* of setRowPrefixFilter. These test cases have been retained to ensure that also the
67+
* Note that about half of these tests were relevant for a different implementation approach
68+
* of setStartStopRowForPrefixScan. These test cases have been retained to ensure that also the
6969
* edge cases found there are still covered.
7070
*/
7171

@@ -119,16 +119,16 @@ public void testPrefixScanning() throws IOException {
119119
// ========
120120
// PREFIX 0
121121
Scan scan = new Scan();
122-
scan.setRowPrefixFilter(prefix0);
122+
scan.setStartStopRowForPrefixScan(prefix0);
123123
verifyScanResult(table, scan, expected0, "Scan empty prefix failed");
124124

125125
// ========
126126
// PREFIX 1
127127
scan = new Scan();
128-
scan.setRowPrefixFilter(prefix1);
128+
scan.setStartStopRowForPrefixScan(prefix1);
129129
verifyScanResult(table, scan, expected1, "Scan normal prefix failed");
130130

131-
scan.setRowPrefixFilter(null);
131+
scan.setStartStopRowForPrefixScan(null);
132132
verifyScanResult(table, scan, expected0, "Scan after prefix reset failed");
133133

134134
scan = new Scan();
@@ -138,10 +138,10 @@ public void testPrefixScanning() throws IOException {
138138
// ========
139139
// PREFIX 2
140140
scan = new Scan();
141-
scan.setRowPrefixFilter(prefix2);
141+
scan.setStartStopRowForPrefixScan(prefix2);
142142
verifyScanResult(table, scan, expected2, "Scan edge 0xFF prefix failed");
143143

144-
scan.setRowPrefixFilter(null);
144+
scan.setStartStopRowForPrefixScan(null);
145145
verifyScanResult(table, scan, expected0, "Scan after prefix reset failed");
146146

147147
scan = new Scan();
@@ -151,10 +151,10 @@ public void testPrefixScanning() throws IOException {
151151
// ========
152152
// PREFIX 3
153153
scan = new Scan();
154-
scan.setRowPrefixFilter(prefix3);
154+
scan.setStartStopRowForPrefixScan(prefix3);
155155
verifyScanResult(table, scan, expected3, "Scan normal with 0x00 ends failed");
156156

157-
scan.setRowPrefixFilter(null);
157+
scan.setStartStopRowForPrefixScan(null);
158158
verifyScanResult(table, scan, expected0, "Scan after prefix reset failed");
159159

160160
scan = new Scan();
@@ -164,10 +164,10 @@ public void testPrefixScanning() throws IOException {
164164
// ========
165165
// PREFIX 4
166166
scan = new Scan();
167-
scan.setRowPrefixFilter(prefix4);
167+
scan.setStartStopRowForPrefixScan(prefix4);
168168
verifyScanResult(table, scan, expected4, "Scan end prefix failed");
169169

170-
scan.setRowPrefixFilter(null);
170+
scan.setStartStopRowForPrefixScan(null);
171171
verifyScanResult(table, scan, expected0, "Scan after prefix reset failed");
172172

173173
scan = new Scan();
@@ -178,13 +178,13 @@ public void testPrefixScanning() throws IOException {
178178
// COMBINED
179179
// Prefix + Filter
180180
scan = new Scan();
181-
scan.setRowPrefixFilter(prefix1);
181+
scan.setStartStopRowForPrefixScan(prefix1);
182182
verifyScanResult(table, scan, expected1, "Prefix filter failed");
183183

184184
scan.setFilter(new ColumnPrefixFilter(prefix2));
185185
verifyScanResult(table, scan, expected2, "Combined Prefix + Filter failed");
186186

187-
scan.setRowPrefixFilter(null);
187+
scan.setStartStopRowForPrefixScan(null);
188188
verifyScanResult(table, scan, expected2, "Combined Prefix + Filter; removing Prefix failed");
189189

190190
scan.setFilter(null);
@@ -196,55 +196,16 @@ public void testPrefixScanning() throws IOException {
196196
scan.setFilter(new ColumnPrefixFilter(prefix2));
197197
verifyScanResult(table, scan, expected2, "Test filter failed");
198198

199-
scan.setRowPrefixFilter(prefix1);
199+
scan.setStartStopRowForPrefixScan(prefix1);
200200
verifyScanResult(table, scan, expected2, "Combined Filter + Prefix failed");
201201

202202
scan.setFilter(null);
203203
verifyScanResult(table, scan, expected1, "Combined Filter + Prefix ; removing Filter failed");
204204

205-
scan.setRowPrefixFilter(null);
205+
scan.setStartStopRowForPrefixScan(null);
206206
verifyScanResult(table, scan, expected0, "Scan after prefix reset failed");
207207
}
208208

209-
@Test
210-
public void testRowPrefixFilterAndStartRow() throws IOException {
211-
final TableName tableName = TableName.valueOf(name.getMethodName());
212-
createTable(tableName,"F");
213-
Table table = openTable(tableName);
214-
215-
final byte[][] rowkeys = {Bytes.toBytes("111"), Bytes.toBytes("112")};
216-
final byte[] prefixFilter = Bytes.toBytes("11");
217-
for (byte[] rowkey: rowkeys) {
218-
Put p = new Put(rowkey);
219-
p.addColumn(Bytes.toBytes("F"), Bytes.toBytes("f"), Bytes.toBytes("test value"));
220-
table.put(p);
221-
}
222-
223-
List<byte[]> expected0 = new ArrayList<>();
224-
expected0.add(rowkeys[0]);
225-
expected0.add(rowkeys[1]);
226-
227-
List<byte[]> expected1 = new ArrayList<>();
228-
expected1.add(rowkeys[1]);
229-
230-
// ========
231-
// First scan
232-
// Set startRow before setRowPrefixFilter
233-
Scan scan = new Scan();
234-
scan.withStartRow(rowkeys[1]);
235-
scan.setRowPrefixFilter(prefixFilter);
236-
verifyScanResult(table, scan, expected0, "Set startRow before setRowPrefixFilter unexpected");
237-
238-
// ========
239-
// Second scan
240-
// Set startRow after setRowPrefixFilter
241-
// The result is different from first scan
242-
scan = new Scan();
243-
scan.setRowPrefixFilter(prefixFilter);
244-
scan.withStartRow(rowkeys[1]);
245-
verifyScanResult(table, scan, expected1, "Set startRow after setRowPrefixFilter unexpected");
246-
}
247-
248209
private void verifyScanResult(Table table, Scan scan, List<byte[]> expectedKeys, String message) {
249210
List<byte[]> actualKeys = new ArrayList<>();
250211
try {

hbase-shell/src/main/ruby/hbase/table.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def _deleterows_internal(row, column = nil,
208208

209209
# create scan to get table names using prefix
210210
scan = org.apache.hadoop.hbase.client.Scan.new
211-
scan.setRowPrefixFilter(prefix.to_java_bytes)
211+
scan.setStartStopRowForPrefixScan(prefix.to_java_bytes)
212212
# Run the scanner to get all rowkeys
213213
scanner = @table.getScanner(scan)
214214
# Create a list to store all deletes
@@ -536,7 +536,7 @@ def _hash_to_scan(args)
536536
end
537537

538538
# This will overwrite any startrow/stoprow settings
539-
scan.setRowPrefixFilter(rowprefixfilter.to_java_bytes) if rowprefixfilter
539+
scan.setStartStopRowForPrefixScan(rowprefixfilter.to_java_bytes) if rowprefixfilter
540540

541541
# Clear converters from last scan.
542542
@converters.clear

src/main/asciidoc/_chapters/datamodel.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ Table table = ... // instantiate a Table instance
300300
301301
Scan scan = new Scan();
302302
scan.addColumn(CF, ATTR);
303-
scan.setRowPrefixFilter(Bytes.toBytes("row"));
303+
scan.setStartStopRowForPrefixScan(Bytes.toBytes("row"));
304304
ResultScanner rs = table.getScanner(scan);
305305
try {
306306
for (Result r = rs.next(); r != null; r = rs.next()) {

0 commit comments

Comments
 (0)