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));
+ }
}
}