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

tkhurana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/master by this push:
     new dd3cae6eee PHOENIX-8018: Disable global index read repair for 
ROW_SIZE() and RAW_ROW_SIZE() scans (#2646)
dd3cae6eee is described below

commit dd3cae6eee4e9dc10b1534a59667d6471fa7ceb9
Author: Wu Shuwen <[email protected]>
AuthorDate: Fri Nov 6 04:16:35 2026 +0800

    PHOENIX-8018: Disable global index read repair for ROW_SIZE() and 
RAW_ROW_SIZE() scans (#2646)
    
    * PHOENIX-8018: Disable index read repair for row-size scans
    
    Keep read repair disabled for index rebuilds, and skip enabling it for 
ROW_SIZE() and RAW_ROW_SIZE() scans. These functions should inspect stored 
index state without performing repair.
    
    Generated-by: Pi 1.4.0 (gpt-6-luna)
    
    * Add row size coverage for unverified index rows
---
 .../java/org/apache/phoenix/util/ScanUtil.java     | 12 ++++--
 .../end2end/index/GlobalIndexCheckerIT.java        | 47 ++++++++++++++++++++++
 .../java/org/apache/phoenix/util/ScanUtilTest.java | 35 ++++++++++++++++
 3 files changed, 91 insertions(+), 3 deletions(-)

diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/ScanUtil.java 
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/ScanUtil.java
index 0be1157de8..e66a93d054 100644
--- a/phoenix-core-client/src/main/java/org/apache/phoenix/util/ScanUtil.java
+++ b/phoenix-core-client/src/main/java/org/apache/phoenix/util/ScanUtil.java
@@ -1208,6 +1208,14 @@ public class ScanUtil {
     return 
scan.getAttribute((BaseScannerRegionObserverConstants.REBUILD_INDEXES)) != null;
   }
 
+  static void setIndexReadRepairAttribute(Scan scan, StatementContext context) 
{
+    if (
+      !isIndexRebuild(scan) && !context.hasRowSizeFunction() && 
!context.hasRawRowSizeFunction()
+    ) {
+      
scan.setAttribute(BaseScannerRegionObserverConstants.CHECK_VERIFY_COLUMN, 
TRUE_BYTES);
+    }
+  }
+
   public static boolean isSyncTableChunkFormationEnabled(Scan scan) {
     return Arrays.equals(
       
scan.getAttribute(BaseScannerRegionObserverConstants.SYNC_TABLE_CHUNK_FORMATION),
 TRUE_BYTES);
@@ -1488,9 +1496,7 @@ public class ScanUtil {
         scan.setAttribute(PhoenixIndexCodec.INDEX_PROTO_MD, 
ByteUtil.copyKeyBytesIfNecessary(ptr));
       }
       if (IndexUtil.isCoveredGlobalIndex(indexTable)) {
-        if (!isIndexRebuild(scan)) {
-          
scan.setAttribute(BaseScannerRegionObserverConstants.CHECK_VERIFY_COLUMN, 
TRUE_BYTES);
-        }
+        setIndexReadRepairAttribute(scan, context);
       } else {
         
scan.setAttribute(BaseScannerRegionObserverConstants.UNCOVERED_GLOBAL_INDEX, 
TRUE_BYTES);
       }
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexCheckerIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexCheckerIT.java
index 46db55076f..79986d30e2 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexCheckerIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalIndexCheckerIT.java
@@ -1016,6 +1016,53 @@ public class GlobalIndexCheckerIT extends BaseTest {
     }
   }
 
+  @Test
+  public void testRowSizeFunctionsOnIndexWithUnverifiedRows() throws Exception 
{
+    if (async) {
+      // No need to run the same test twice for async = true and async = false.
+      return;
+    }
+    try (Connection conn = DriverManager.getConnection(getUrl())) {
+      String dataTableName = generateUniqueName();
+      conn.createStatement().execute("create table " + dataTableName
+        + " (id varchar(10) not null primary key, val1 varchar(10), val2 
varchar(10), val3 varchar(10))"
+        + tableDDLOptions);
+      String indexTableName = generateUniqueName();
+      conn.createStatement().execute("CREATE INDEX " + indexTableName + " on " 
+ dataTableName
+        + " (val1) include (val2, val3)" + this.indexDDLOptions);
+
+      // Fail the data-table write after the index write, leaving an 
unverified index row.
+      IndexRegionObserver.setFailDataTableUpdatesForTesting(true);
+      conn.createStatement()
+        .execute("upsert into " + dataTableName + " values ('a', 'ab','abc', 
'abcd')");
+      commitWithException(conn);
+      IndexRegionObserver.setFailDataTableUpdatesForTesting(false);
+
+      // Write a separate authoritative row so the unverified index row 
remains in the index.
+      conn.createStatement()
+        .execute("upsert into " + dataTableName + " (id, val1, val2) values 
('b', 'ab','abc')");
+      conn.commit();
+      waitForEventualConsistency();
+
+      String rowSizeSql = "SELECT SUM(ROW_SIZE()) FROM " + dataTableName + " 
WHERE val1 = 'ab'";
+      assertExplainPlan(conn, rowSizeSql, dataTableName, indexTableName);
+      try (ResultSet rs = conn.createStatement().executeQuery(rowSizeSql)) {
+        assertTrue(rs.next());
+        assertTrue(rs.getLong(1) > 0);
+        assertFalse(rs.next());
+      }
+
+      String rawRowSizeSql =
+        "SELECT SUM(RAW_ROW_SIZE()) FROM " + dataTableName + " WHERE val1 = 
'ab'";
+      assertExplainPlan(conn, rawRowSizeSql, dataTableName, indexTableName);
+      try (ResultSet rs = conn.createStatement().executeQuery(rawRowSizeSql)) {
+        assertTrue(rs.next());
+        assertTrue(rs.getLong(1) > 0);
+        assertFalse(rs.next());
+      }
+    }
+  }
+
   @Test
   public void testUnverifiedRowRepair() throws Exception {
     if (async) {
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/util/ScanUtilTest.java 
b/phoenix-core/src/test/java/org/apache/phoenix/util/ScanUtilTest.java
index 57cea98aa7..50f30da503 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/ScanUtilTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/ScanUtilTest.java
@@ -18,11 +18,16 @@
 package org.apache.phoenix.util;
 
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.StatementContext;
+import org.apache.phoenix.coprocessorclient.BaseScannerRegionObserverConstants;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.query.KeyRange.Bound;
 import org.apache.phoenix.query.QueryConstants;
@@ -40,6 +45,7 @@ import org.junit.experimental.runners.Enclosed;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
+import org.mockito.Mockito;
 
 import org.apache.phoenix.thirdparty.com.google.common.base.Function;
 import org.apache.phoenix.thirdparty.com.google.common.collect.Lists;
@@ -515,6 +521,35 @@ public class ScanUtilTest {
       assertArrayEquals(expectedStartKey, startKey);
       assertArrayEquals(expectedEndKey, endKey);
     }
+
+    @Test
+    public void testRowSizeScansDoNotEnableIndexReadRepair() {
+      StatementContext context = Mockito.mock(StatementContext.class);
+      Scan regularScan = new Scan();
+      ScanUtil.setIndexReadRepairAttribute(regularScan, context);
+      assertNotNull(
+        
regularScan.getAttribute(BaseScannerRegionObserverConstants.CHECK_VERIFY_COLUMN));
+
+      Mockito.when(context.hasRowSizeFunction()).thenReturn(true);
+      Scan rowSizeScan = new Scan();
+      ScanUtil.setIndexReadRepairAttribute(rowSizeScan, context);
+      assertNull(
+        
rowSizeScan.getAttribute(BaseScannerRegionObserverConstants.CHECK_VERIFY_COLUMN));
+
+      Mockito.when(context.hasRowSizeFunction()).thenReturn(false);
+      Mockito.when(context.hasRawRowSizeFunction()).thenReturn(true);
+      Scan rawRowSizeScan = new Scan();
+      ScanUtil.setIndexReadRepairAttribute(rawRowSizeScan, context);
+      assertNull(
+        
rawRowSizeScan.getAttribute(BaseScannerRegionObserverConstants.CHECK_VERIFY_COLUMN));
+
+      Scan indexRebuildScan = new Scan();
+      
indexRebuildScan.setAttribute(BaseScannerRegionObserverConstants.REBUILD_INDEXES,
+        Bytes.toBytes(true));
+      ScanUtil.setIndexReadRepairAttribute(indexRebuildScan, context);
+      assertNull(
+        
indexRebuildScan.getAttribute(BaseScannerRegionObserverConstants.CHECK_VERIFY_COLUMN));
+    }
   }
 
 }

Reply via email to