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 a7ffe4f7f6 PHOENIX-7609 : CDC creation fails when data table has case
sensitive name (#2149)
a7ffe4f7f6 is described below
commit a7ffe4f7f6512b0eb7462b43da08a23e27c857ed
Author: Palash Chauhan <[email protected]>
AuthorDate: Thu May 15 19:58:18 2025 -0700
PHOENIX-7609 : CDC creation fails when data table has case sensitive name
(#2149)
Co-authored-by: Palash Chauhan
<[email protected]>
---
.../org/apache/phoenix/compile/QueryCompiler.java | 3 +-
.../apache/phoenix/optimize/QueryOptimizer.java | 2 +-
.../org/apache/phoenix/schema/MetaDataClient.java | 9 ++-
.../main/java/org/apache/phoenix/util/CDCUtil.java | 2 +-
.../apache/phoenix/end2end/CDCDefinitionIT.java | 40 ++++++++++
.../org/apache/phoenix/end2end/CDCQueryIT.java | 92 ++++++++++++++--------
.../phoenix/end2end/index/SingleCellIndexIT.java | 2 +
7 files changed, 112 insertions(+), 38 deletions(-)
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
index efb25cb761..2d9a975ae1 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/compile/QueryCompiler.java
@@ -32,6 +32,7 @@ import
org.apache.phoenix.coprocessorclient.BaseScannerRegionObserverConstants;
import org.apache.phoenix.expression.function.PhoenixRowTimestampFunction;
import org.apache.phoenix.parse.HintNode;
import org.apache.phoenix.parse.NamedTableNode;
+import org.apache.phoenix.parse.TableName;
import org.apache.phoenix.parse.TerminalParseNode;
import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.SortOrder;
@@ -275,7 +276,7 @@ public class QueryCompiler {
TableRef cdcTableRef = dataPlanForCDC.getTableRef();
PTable cdcTable = cdcTableRef.getTable();
NamedTableNode cdcDataTableName = NODE_FACTORY.namedTable(null,
- NODE_FACTORY.table(cdcTable.getSchemaName().getString(),
+ TableName.create(cdcTable.getSchemaName().getString(),
cdcTable.getParentTableName().getString()),
select.getTableSamplingRate());
ColumnResolver dataTableResolver =
FromCompiler.getResolver(cdcDataTableName,
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
index a562b3ebc8..7cb75cad64 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/optimize/QueryOptimizer.java
@@ -227,7 +227,7 @@ public class QueryOptimizer {
PTable table = dataPlan.getTableRef().getTable();
if (table.getType() == PTableType.CDC) {
NamedTableNode indexTableNode = FACTORY.namedTable(null,
- FACTORY.table(table.getSchemaName().getString(),
+ TableName.create(table.getSchemaName().getString(),
CDCUtil.getCDCIndexName(table.getTableName().getString())),
select.getTableSamplingRate());
indexResolver = FromCompiler.getResolver(indexTableNode,
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 726e77ac4a..85fad7b96b 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -1986,11 +1986,14 @@ public class MetaDataClient {
Properties props = connection.getClientInfo();
props.put(INDEX_CREATE_DEFAULT_STATE, "ACTIVE");
+ String escapedDataTableFullName
+ =
SchemaUtil.getFullTableNameWithQuotes(statement.getDataTable().getSchemaName(),
+ statement.getDataTable().getTableName(), true, true);
String
createIndexSql =
"CREATE UNCOVERED INDEX " + (statement.isIfNotExists() ? "IF
NOT EXISTS " : "")
- + CDCUtil.getCDCIndexName(cdcObjName)
- + " ON " + dataTableFullName + " ("
+ + "\"" + CDCUtil.getCDCIndexName(cdcObjName)
+ + "\" ON " + escapedDataTableFullName + " ("
+ PartitionIdFunction.NAME + "(), " +
PhoenixRowTimestampFunction.NAME
+ "()) ASYNC";
List<String> indexProps = new ArrayList<>();
@@ -2041,7 +2044,7 @@ public class MetaDataClient {
tableProps.put(TableProperty.MULTI_TENANT.getPropertyName(),
Boolean.TRUE);
}
CreateTableStatement tableStatement = FACTORY.createTable(
- FACTORY.table(dataTable.getSchemaName().getString(),
cdcObjName),
+ TableName.create(dataTable.getSchemaName().getString(),
cdcObjName),
null, columnDefs, FACTORY.primaryKey(null, pkColumnDefs),
Collections.emptyList(), PTableType.CDC,
statement.isIfNotExists(), null, null,
statement.getBindCount(), null);
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/CDCUtil.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/CDCUtil.java
index 2a89798041..3b3c8b5315 100644
--- a/phoenix-core-client/src/main/java/org/apache/phoenix/util/CDCUtil.java
+++ b/phoenix-core-client/src/main/java/org/apache/phoenix/util/CDCUtil.java
@@ -88,7 +88,7 @@ public class CDCUtil {
}
public static String getCDCIndexName(String cdcName) {
- return CDC_INDEX_PREFIX +
SchemaUtil.getTableNameFromFullName(cdcName.toUpperCase());
+ return CDC_INDEX_PREFIX + SchemaUtil.getTableNameFromFullName(cdcName);
}
public static boolean isCDCIndex(String indexName) {
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCDefinitionIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCDefinitionIT.java
index 2847237c91..bb3263a93f 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCDefinitionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCDefinitionIT.java
@@ -128,6 +128,46 @@ public class CDCDefinitionIT extends CDCBaseIT {
conn.close();
}
+ @Test
+ public void testCreateCaseSensitiveTable() throws Exception {
+ Connection conn = newConnection();
+ String tableName = "\"" + generateUniqueName().toLowerCase() + "\"";
+ conn.createStatement().execute(
+ "CREATE TABLE " + tableName + " ( k INTEGER PRIMARY KEY," + "
v1 INTEGER,"
+ + " v2 DATE) TTL=100");
+ if (forView) {
+ String viewName = "\"" + generateUniqueName().toLowerCase() + "\"";
+ conn.createStatement().execute(
+ "CREATE VIEW " + viewName + " AS SELECT * FROM " +
tableName);
+ tableName = viewName;
+ }
+ String cdcName = "\"" + generateUniqueName().toLowerCase() + "\"";
+ String cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName;
+ conn.createStatement().execute(cdc_sql);
+ conn.createStatement().executeQuery("SELECT * FROM " + cdcName);
+ }
+
+ @Test
+ public void testCreateCaseSensitiveSchemaAndTable() throws Exception {
+ Connection conn = newConnection();
+ String schemaName = "\"" + generateUniqueName().toLowerCase() + "\"";
+ String tableName = SchemaUtil.getTableName(schemaName, "\"" +
generateUniqueName().toLowerCase() + "\"");
+ conn.createStatement().execute(
+ "CREATE TABLE " + tableName + " ( k INTEGER PRIMARY KEY," + "
v1 INTEGER,"
+ + " v2 DATE) TTL=100");
+ if (forView) {
+ String viewName = SchemaUtil.getTableName(schemaName, "\"" +
generateUniqueName().toLowerCase() + "\"");
+ conn.createStatement().execute(
+ "CREATE VIEW " + viewName + " AS SELECT * FROM " +
tableName);
+ tableName = viewName;
+ }
+ String cdcName = "\"" + generateUniqueName().toLowerCase() + "\"";
+ String cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName;
+ conn.createStatement().execute(cdc_sql);
+ String cdcFullName = SchemaUtil.getTableName(schemaName, cdcName);
+ conn.createStatement().executeQuery("SELECT * FROM " + cdcFullName);
+ }
+
@Test
public void testCreateWithSchemaName() throws Exception {
Properties props = new Properties();
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCQueryIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCQueryIT.java
index a1519cc64b..b7e4b2cd59 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCQueryIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CDCQueryIT.java
@@ -97,27 +97,32 @@ public class CDCQueryIT extends CDCBaseIT {
private final boolean multitenant;
private final Integer tableSaltBuckets;
private final boolean withSchemaName;
+ private final boolean caseSensitiveNames;
public CDCQueryIT(Boolean forView,
PTable.QualifierEncodingScheme encodingScheme, boolean
multitenant,
- Integer tableSaltBuckets, boolean withSchemaName) {
+ Integer tableSaltBuckets, boolean withSchemaName,
boolean caseSensitiveNames) {
this.forView = forView;
this.encodingScheme = encodingScheme;
this.multitenant = multitenant;
this.tableSaltBuckets = tableSaltBuckets;
this.withSchemaName = withSchemaName;
+ this.caseSensitiveNames = caseSensitiveNames;
}
@Parameterized.Parameters(name = "forView={0}, encodingScheme={1}, " +
- "multitenant={2}, tableSaltBuckets={3}, withSchemaName={4}")
+ "multitenant={2}, tableSaltBuckets={3}, withSchemaName={4},
caseSensitiveNames={5}")
public static synchronized Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
- { Boolean.FALSE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE },
- { Boolean.FALSE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.TRUE },
- { Boolean.FALSE, NON_ENCODED_QUALIFIERS, Boolean.FALSE, 4,
Boolean.FALSE },
- { Boolean.FALSE, NON_ENCODED_QUALIFIERS, Boolean.TRUE, 2,
Boolean.TRUE },
- { Boolean.FALSE, NON_ENCODED_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE },
- { Boolean.TRUE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE },
+ { Boolean.FALSE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE, Boolean.FALSE },
+ { Boolean.FALSE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.TRUE, Boolean.FALSE },
+ { Boolean.FALSE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE, Boolean.TRUE },
+ { Boolean.FALSE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.TRUE, Boolean.TRUE },
+ { Boolean.FALSE, NON_ENCODED_QUALIFIERS, Boolean.FALSE, 4,
Boolean.FALSE, Boolean.FALSE },
+ { Boolean.FALSE, NON_ENCODED_QUALIFIERS, Boolean.TRUE, 2,
Boolean.TRUE, Boolean.FALSE },
+ { Boolean.FALSE, NON_ENCODED_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE, Boolean.FALSE },
+ { Boolean.TRUE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE, Boolean.FALSE },
+ { Boolean.TRUE, TWO_BYTE_QUALIFIERS, Boolean.FALSE, null,
Boolean.FALSE, Boolean.TRUE },
});
}
@@ -294,8 +299,8 @@ public class CDCQueryIT extends CDCBaseIT {
@Test
public void testSelectCDC() throws Exception {
String cdcName, cdc_sql;
- String schemaName = withSchemaName ? generateUniqueName() : null;
- String tableName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String schemaName = getSchemaName();
+ String tableName = getTableOrViewName(schemaName);
String datatableName = tableName;
try (Connection conn = newConnection()) {
createTable(conn, "CREATE TABLE " + tableName + " ("
@@ -304,12 +309,12 @@ public class CDCQueryIT extends CDCBaseIT {
+ "CONSTRAINT PK PRIMARY KEY " + (multitenant ?
"(TENANT_ID, k) " : "(k)")
+ ")", encodingScheme, multitenant, tableSaltBuckets,
false, null);
if (forView) {
- String viewName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String viewName = getTableOrViewName(schemaName);
createTable(conn, "CREATE VIEW " + viewName + " AS SELECT *
FROM " + tableName,
encodingScheme);
tableName = viewName;
}
- cdcName = generateUniqueName();
+ cdcName = getCDCName();
cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName;
createCDC(conn, cdc_sql, encodingScheme);
}
@@ -423,8 +428,8 @@ public class CDCQueryIT extends CDCBaseIT {
@Test
public void testSelectGeneric() throws Exception {
String cdcName, cdc_sql;
- String schemaName = withSchemaName ? generateUniqueName() : null;
- String tableName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String schemaName = getSchemaName();
+ String tableName = getTableOrViewName(schemaName);
String datatableName = tableName;
Map<String, String> pkColumns = new TreeMap<String, String>() {{
put("K1", "INTEGER");
@@ -447,12 +452,14 @@ public class CDCQueryIT extends CDCBaseIT {
createTable(conn, tableName, pkColumns, dataColumns, multitenant,
encodingScheme,
tableSaltBuckets, false, null);
if (forView) {
- String viewName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String viewName = caseSensitiveNames
+ ? SchemaUtil.getTableName(schemaName,
SchemaUtil.getEscapedArgument(generateUniqueName().toLowerCase()))
+ : SchemaUtil.getTableName(schemaName,
generateUniqueName());
createTable(conn, "CREATE VIEW " + viewName + " AS SELECT *
FROM " + tableName,
encodingScheme);
tableName = viewName;
}
- cdcName = generateUniqueName();
+ cdcName = getCDCName();
cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName + " INCLUDE
(change)";
createCDC(conn, cdc_sql, encodingScheme);
}
@@ -526,8 +533,8 @@ public class CDCQueryIT extends CDCBaseIT {
private void _testSelectCDCImmutable(PTable.ImmutableStorageScheme
immutableStorageScheme)
throws Exception {
String cdcName, cdc_sql;
- String schemaName = withSchemaName ? generateUniqueName() : null;
- String tableName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String schemaName = getSchemaName();
+ String tableName = getTableOrViewName(schemaName);
String datatableName = tableName;
try (Connection conn = newConnection()) {
createTable(conn, "CREATE TABLE " + tableName + " (" +
@@ -536,12 +543,13 @@ public class CDCQueryIT extends CDCBaseIT {
(multitenant ? "(TENANT_ID, k) " : "(k)") + ")",
encodingScheme, multitenant,
tableSaltBuckets, true, immutableStorageScheme);
if (forView) {
- String viewName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String viewName = getTableOrViewName(schemaName);
+
createTable(conn, "CREATE VIEW " + viewName + " AS SELECT *
FROM " + tableName,
encodingScheme);
tableName = viewName;
}
- cdcName = generateUniqueName();
+ cdcName = getCDCName();
cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName;
createCDC(conn, cdc_sql, encodingScheme);
@@ -598,8 +606,8 @@ public class CDCQueryIT extends CDCBaseIT {
@Test
public void testSelectWithTimeRange() throws Exception {
String cdcName, cdc_sql;
- String schemaName = withSchemaName ? generateUniqueName() : null;
- String tableName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String schemaName = getSchemaName();
+ String tableName = getTableOrViewName(schemaName);
String datatableName = tableName;
Map<String, String> pkColumns = new TreeMap<String, String>() {{
put("K1", "INTEGER");
@@ -611,12 +619,12 @@ public class CDCQueryIT extends CDCBaseIT {
createTable(conn, tableName, pkColumns, dataColumns, multitenant,
encodingScheme,
tableSaltBuckets, false, null);
if (forView) {
- String viewName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String viewName = getTableOrViewName(schemaName);
createTable(conn, "CREATE VIEW " + viewName + " AS SELECT *
FROM " + tableName,
encodingScheme);
tableName = viewName;
}
- cdcName = generateUniqueName();
+ cdcName = getCDCName();
cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName + " INCLUDE
(change)";
createCDC(conn, cdc_sql, encodingScheme);
cdcIndexShouldNotBeUsedForDataTableQueries(conn,
tableName,cdcName);
@@ -674,8 +682,8 @@ public class CDCQueryIT extends CDCBaseIT {
@Test
public void testSelectCDCWithDDL() throws Exception {
- String schemaName = withSchemaName ? generateUniqueName() : null;
- String tableName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String schemaName = getSchemaName();
+ String tableName = getTableOrViewName(schemaName);
String datatableName = tableName;
String cdcName, cdc_sql;
try (Connection conn = newConnection()) {
@@ -686,13 +694,13 @@ public class CDCQueryIT extends CDCBaseIT {
(multitenant ? "(TENANT_ID, k) " : "(k)") + ")",
encodingScheme, multitenant,
tableSaltBuckets, false, null);
if (forView) {
- String viewName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String viewName = getTableOrViewName(schemaName);
createTable(conn, "CREATE VIEW " + viewName + " AS SELECT *
FROM " + tableName,
encodingScheme);
tableName = viewName;
}
- cdcName = generateUniqueName();
+ cdcName = getCDCName();
cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName;
createCDC(conn, cdc_sql, encodingScheme);
conn.createStatement().execute("ALTER TABLE " + datatableName + "
DROP COLUMN v0");
@@ -727,8 +735,8 @@ public class CDCQueryIT extends CDCBaseIT {
@Test
public void testSelectCDCFailDataTableUpdate() throws Exception {
- String schemaName = withSchemaName ? generateUniqueName() : null;
- String tableName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String schemaName = getSchemaName();
+ String tableName = getTableOrViewName(schemaName);
String cdcName, cdc_sql;
try (Connection conn = newConnection()) {
createTable(conn, "CREATE TABLE " + tableName + " (" +
@@ -738,12 +746,12 @@ public class CDCQueryIT extends CDCBaseIT {
(multitenant ? "(TENANT_ID, k) " : "(k)") + ")",
encodingScheme, multitenant,
tableSaltBuckets, false, null);
if (forView) {
- String viewName = SchemaUtil.getTableName(schemaName,
generateUniqueName());
+ String viewName = getTableOrViewName(schemaName);
createTable(conn, "CREATE VIEW " + viewName + " AS SELECT *
FROM " + tableName,
encodingScheme);
tableName = viewName;
}
- cdcName = generateUniqueName();
+ cdcName = getCDCName();
cdc_sql = "CREATE CDC " + cdcName + " ON " + tableName;
createCDC(conn, cdc_sql, encodingScheme);
cdcIndexShouldNotBeUsedForDataTableQueries(conn, tableName,
cdcName);
@@ -938,4 +946,24 @@ public class CDCQueryIT extends CDCBaseIT {
}
}
+
+ private String getSchemaName() {
+ return withSchemaName
+ ? caseSensitiveNames
+ ?
SchemaUtil.getEscapedArgument(generateUniqueName().toLowerCase())
+ : generateUniqueName()
+ : null;
+ }
+
+ private String getTableOrViewName(String schemaName) {
+ return caseSensitiveNames
+ ? SchemaUtil.getTableName(schemaName,
SchemaUtil.getEscapedArgument(generateUniqueName().toLowerCase()))
+ : SchemaUtil.getTableName(schemaName, generateUniqueName());
+ }
+
+ private String getCDCName() {
+ return caseSensitiveNames
+ ?
SchemaUtil.getEscapedArgument(generateUniqueName().toLowerCase())
+ : generateUniqueName();
+ }
}
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SingleCellIndexIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SingleCellIndexIT.java
index 2dbbabe76b..8ebd4f36c6 100644
---
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SingleCellIndexIT.java
+++
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/SingleCellIndexIT.java
@@ -498,6 +498,8 @@ public class SingleCellIndexIT extends
ParallelStatsDisabledIT {
}
public static void dumpTable(String tableName) throws Exception {
+ // this method is also used by CDCBaseIT where case sensitive
tableNames are also used
+ tableName = tableName.replaceAll("\"", "");
try (Connection conn = DriverManager.getConnection(getUrl())) {
Table
hTable =
conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(tableName.getBytes());