This is an automated email from the ASF dual-hosted git repository.
palashc 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 aa44ae6dcb PHOENIX-7743 : Fix TNFE in IndexTool server side builds for
case sensitive names (#2331)
aa44ae6dcb is described below
commit aa44ae6dcb307ab9fd30f25dae7f58e4203b6d5b
Author: Palash Chauhan <[email protected]>
AuthorDate: Wed Feb 4 14:05:47 2026 -0800
PHOENIX-7743 : Fix TNFE in IndexTool server side builds for case sensitive
names (#2331)
Co-authored-by: Palash Chauhan
<[email protected]>
---
.../PhoenixServerBuildIndexInputFormat.java | 16 ++++-
.../apache/phoenix/mapreduce/index/IndexTool.java | 2 +-
.../org/apache/phoenix/end2end/IndexToolIT.java | 82 ++++++++++++++++++++++
3 files changed, 96 insertions(+), 4 deletions(-)
diff --git
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/PhoenixServerBuildIndexInputFormat.java
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/PhoenixServerBuildIndexInputFormat.java
index ba9abe77ce..5bae99d883 100644
---
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/PhoenixServerBuildIndexInputFormat.java
+++
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/PhoenixServerBuildIndexInputFormat.java
@@ -62,6 +62,7 @@ import org.apache.phoenix.util.ByteUtil;
import org.apache.phoenix.util.EnvironmentEdgeManager;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.ScanUtil;
+import org.apache.phoenix.util.SchemaUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -92,8 +93,9 @@ public class PhoenixServerBuildIndexInputFormat<T extends
DBWritable> extends Ph
public QueryPlan getQueryPlan(PhoenixConnection phoenixConnection, String
oldTableFullName,
String newTableFullName) throws SQLException {
PTable newTable = phoenixConnection.getTableNoCache(newTableFullName);
+ String quotedOldTableName = getQuotedTableNameForSQL(oldTableFullName);
ServerBuildTransformingTableCompiler compiler =
- new ServerBuildTransformingTableCompiler(phoenixConnection,
oldTableFullName);
+ new ServerBuildTransformingTableCompiler(phoenixConnection,
quotedOldTableName);
MutationPlan plan = compiler.compile(newTable);
return plan.getQueryPlan();
}
@@ -104,8 +106,9 @@ public class PhoenixServerBuildIndexInputFormat<T extends
DBWritable> extends Ph
public QueryPlan getQueryPlan(PhoenixConnection phoenixConnection, String
dataTableFullName,
String indexTableFullName) throws SQLException {
PTable indexTable =
phoenixConnection.getTableNoCache(indexTableFullName);
+ String quotedDataTableName = getQuotedTableNameForSQL(dataTableFullName);
ServerBuildIndexCompiler compiler =
- new ServerBuildIndexCompiler(phoenixConnection, dataTableFullName);
+ new ServerBuildIndexCompiler(phoenixConnection, quotedDataTableName);
MutationPlan plan = compiler.compile(indexTable);
return plan.getQueryPlan();
}
@@ -117,7 +120,8 @@ public class PhoenixServerBuildIndexInputFormat<T extends
DBWritable> extends Ph
String indexTableFullName) throws SQLException {
QueryPlan plan;
try (final PhoenixStatement statement = new
PhoenixStatement(phoenixConnection)) {
- String query = "SELECT count(*) FROM " + indexTableFullName;
+ String quotedIndexName = getQuotedTableNameForSQL(indexTableFullName);
+ String query = "SELECT count(*) FROM " + quotedIndexName;
plan = statement.compileQuery(query);
TableRef tableRef = plan.getTableRef();
Scan scan = plan.getContext().getScan();
@@ -139,6 +143,12 @@ public class PhoenixServerBuildIndexInputFormat<T extends
DBWritable> extends Ph
private QueryPlanBuilder queryPlanBuilder;
+ private String getQuotedTableNameForSQL(String normalizedFullTableName) {
+ String schemaName =
SchemaUtil.getSchemaNameFromFullName(normalizedFullTableName);
+ String tableName =
SchemaUtil.getTableNameFromFullName(normalizedFullTableName);
+ return SchemaUtil.getFullTableNameWithQuotes(schemaName, tableName);
+ }
+
@Override
protected QueryPlan getQueryPlan(final JobContext context, final
Configuration configuration)
throws IOException {
diff --git
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
index 2ca544e0ee..6edfc9370c 100644
---
a/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
+++
b/phoenix-core-server/src/main/java/org/apache/phoenix/mapreduce/index/IndexTool.java
@@ -756,7 +756,7 @@ public class IndexTool extends Configured implements Tool {
configuration.setBooleanIfUnset(
PhoenixConfigurationUtil.MAPREDUCE_RANDOMIZE_MAPPER_EXECUTION_ORDER,
true);
- PhoenixConfigurationUtil.setIndexToolDataTableName(configuration,
dataTableWithSchema);
+ PhoenixConfigurationUtil.setIndexToolDataTableName(configuration,
qDataTable);
PhoenixConfigurationUtil.setIndexToolIndexTableName(configuration,
qIndexTable);
PhoenixConfigurationUtil.setIndexToolSourceTable(configuration,
sourceTable);
if (startTime != null) {
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
index d8225e1458..db0ada9832 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
@@ -34,6 +34,8 @@ import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.BEF
import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.BEFORE_REBUILD_UNKNOWN_INDEX_ROW_COUNT;
import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.BEFORE_REBUILD_UNVERIFIED_INDEX_ROW_COUNT;
import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.BEFORE_REBUILD_VALID_INDEX_ROW_COUNT;
+import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.BEFORE_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT;
+import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.BEFORE_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT;
import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.REBUILT_INDEX_ROW_COUNT;
import static
org.apache.phoenix.mapreduce.index.PhoenixIndexToolJobCounters.SCANNED_DATA_ROW_COUNT;
import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
@@ -817,6 +819,86 @@ public class IndexToolIT extends BaseTest {
}
}
+ @Test
+ public void testIndexToDataVerification() throws Exception {
+ testIndexToDataVerificationHelper(false);
+ }
+
+ @Test
+ public void testIndexToDataVerificationCaseSensitive() throws Exception {
+ testIndexToDataVerificationHelper(true);
+ }
+
+ private void testIndexToDataVerificationHelper(boolean caseSensitive) throws
Exception {
+ if (localIndex || transactional || useSnapshot) {
+ return;
+ }
+ String schemaName = caseSensitive ? generateUniqueName().toLowerCase() :
generateUniqueName();
+ String dataTableName =
+ caseSensitive ? generateUniqueName().toLowerCase() :
generateUniqueName();
+ String indexTableName =
+ caseSensitive ? generateUniqueName().toLowerCase() :
generateUniqueName();
+ String sSchemaName = caseSensitive ?
SchemaUtil.getEscapedArgument(schemaName) : schemaName;
+ String sDataTableName =
+ caseSensitive ? SchemaUtil.getEscapedArgument(dataTableName) :
dataTableName;
+ String sIndexTableName =
+ caseSensitive ? SchemaUtil.getEscapedArgument(indexTableName) :
indexTableName;
+ String qDataTableName = caseSensitive
+ ? SchemaUtil.getFullTableNameWithQuotes(schemaName, dataTableName)
+ : SchemaUtil.getTableName(schemaName, dataTableName);
+ String qIndexTableName = caseSensitive
+ ? SchemaUtil.getFullTableNameWithQuotes(schemaName, indexTableName)
+ : SchemaUtil.getTableName(schemaName, indexTableName);
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ if (namespaceMapped) {
+ conn.createStatement().execute("CREATE SCHEMA " + sSchemaName);
+ }
+ conn.createStatement().execute("CREATE TABLE " + qDataTableName
+ + " (ID INTEGER NOT NULL PRIMARY KEY, VAL1 INTEGER, VAL2 INTEGER) " +
tableDDLOptions);
+
+ PreparedStatement dataStmt =
+ conn.prepareStatement("UPSERT INTO " + qDataTableName + "
VALUES(?,?,?)");
+ for (int i = 1; i <= 4; i++) {
+ dataStmt.setInt(1, i);
+ dataStmt.setInt(2, i + 1);
+ dataStmt.setInt(3, i * 2);
+ dataStmt.execute();
+ }
+ conn.commit();
+
+ conn.createStatement()
+ .execute(String.format("CREATE INDEX %s ON %s (VAL1) INCLUDE (VAL2) "
+ indexDDLOptions,
+ sIndexTableName, qDataTableName));
+
+ // Add extra rows directly to the index table
+ PreparedStatement indexStmt =
+ conn.prepareStatement("UPSERT INTO " + qIndexTableName + "
VALUES(?,?,?)");
+ for (int i = 10; i <= 12; i++) {
+ indexStmt.setInt(1, i + 1);
+ indexStmt.setInt(2, i);
+ indexStmt.setInt(3, i * 2);
+ indexStmt.execute();
+ }
+ conn.commit();
+
+ // Run index-to-data verification
+ IndexTool indexTool = runIndexTool(false, sSchemaName, sDataTableName,
sIndexTableName, null,
+ 0, IndexTool.IndexVerifyType.ONLY, "-fi");
+
+ CounterGroup mrJobCounters = getMRJobCounters(indexTool);
+ // Extra index rows should be detected
+ if (mutable) {
+ assertEquals(3, mrJobCounters
+
.findCounter(BEFORE_REPAIR_EXTRA_UNVERIFIED_INDEX_ROW_COUNT.name()).getValue());
+ } else {
+ assertEquals(3, mrJobCounters
+
.findCounter(BEFORE_REPAIR_EXTRA_VERIFIED_INDEX_ROW_COUNT.name()).getValue());
+ }
+ }
+ }
+
public static void assertExplainPlan(boolean localIndex, String
actualExplainPlan,
String dataTableFullName, String indexTableFullName) {
assertExplainPlan(localIndex, actualExplainPlan, dataTableFullName,
indexTableFullName, true);