This is an automated email from the ASF dual-hosted git repository.

junegunn pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new 86fc236adb9 HBASE-30033 Scan.setFilter() should validate against 
existing batch setting (#7988)
86fc236adb9 is described below

commit 86fc236adb925ef1621103cc75431a8ca6e78e21
Author: Jeongmin Ju <[email protected]>
AuthorDate: Tue Apr 7 11:59:29 2026 +0900

    HBASE-30033 Scan.setFilter() should validate against existing batch setting 
(#7988)
    
    Scan.setBatch() validates that the scan does not have a filter with
    hasFilterRow()=true. However, Scan.setFilter() does not perform the
    reverse check. This allows creating an invalid Scan by calling
    setBatch() before setFilter(), bypassing the validation that
    setBatch() was designed to enforce.
    
    Added validation in setFilter() to throw IncompatibleFilterException
    when a filter with hasFilterRow()=true is set on a scan that already
    has batch configured.
    
    Signed-off-by: Junegunn Choi <[email protected]>
    Signed-off-by: Pankaj Kumar <[email protected]>
    Signed-off-by: Xiao Liu <[email protected]>
    Reviewed-by: Vaibhav Joshi <[email protected]>
---
 .../java/org/apache/hadoop/hbase/client/Scan.java  |  4 +++
 .../apache/hadoop/hbase/client/TestOperation.java  |  2 +-
 .../org/apache/hadoop/hbase/client/TestScan.java   | 33 ++++++++++++++++++++++
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git 
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Scan.java 
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Scan.java
index 5cc0d0fac87..630edc4a6ff 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Scan.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Scan.java
@@ -554,6 +554,10 @@ public class Scan extends Query {
 
   @Override
   public Scan setFilter(Filter filter) {
+    if (filter != null && filter.hasFilterRow() && this.batch > 0) {
+      throw new IncompatibleFilterException(
+        "Cannot set a filter that returns true for filter.hasFilterRow on a 
scan with batch set");
+    }
     super.setFilter(filter);
     return this;
   }
diff --git 
a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java 
b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java
index 24dc93a9311..06b688a052a 100644
--- 
a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java
+++ 
b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestOperation.java
@@ -371,7 +371,7 @@ public class TestOperation {
     scan.setLimit(5);
     scan.setReadType(Scan.ReadType.PREAD);
     scan.setNeedCursorResult(true);
-    scan.setFilter(SCV_FILTER);
+    scan.setFilter(VALUE_FILTER);
     scan.setReplicaId(1);
     scan.setConsistency(Consistency.STRONG);
     scan.setLoadColumnFamiliesOnDemand(true);
diff --git 
a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java 
b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java
index dcc624ff112..05c1cc6bcf8 100644
--- a/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java
+++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java
@@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.client;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
@@ -29,6 +30,8 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.client.Scan.ReadType;
 import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.IncompatibleFilterException;
+import org.apache.hadoop.hbase.filter.PageFilter;
 import org.apache.hadoop.hbase.security.access.Permission;
 import org.apache.hadoop.hbase.security.visibility.Authorizations;
 import org.apache.hadoop.hbase.testclassification.ClientTests;
@@ -254,6 +257,36 @@ public class TestScan {
       "Make sure copy constructor adds all the fields in the copied object");
   }
 
+  @Test
+  public void testSetFilterWithBatchThrows() {
+    Scan scan = new Scan();
+    scan.setBatch(5);
+    assertThrows(IncompatibleFilterException.class, () -> scan.setFilter(new 
PageFilter(10)));
+  }
+
+  @Test
+  public void testSetFilterWithoutBatchDoesNotThrow() {
+    Scan scan = new Scan();
+    scan.setFilter(new PageFilter(10));
+    // no exception expected
+  }
+
+  @Test
+  public void testSetFilterWithBatchAndNonFilterRowFilter() {
+    Scan scan = new Scan();
+    scan.setBatch(5);
+    scan.setFilter(new FilterList());
+    // FilterList.hasFilterRow() returns false, so no exception expected
+  }
+
+  @Test
+  public void testSetFilterWithBatchAndNullFilter() {
+    Scan scan = new Scan();
+    scan.setBatch(5);
+    scan.setFilter(null);
+    // null filter should not throw
+  }
+
   @Test
   public void testScanReadType() throws Exception {
     Scan scan = new Scan();

Reply via email to