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

apurtell pushed a commit to branch PHOENIX-7562-feature
in repository https://gitbox.apache.org/repos/asf/phoenix.git

commit 1a9709b5736d0f2e78b96a74de3d97d3d789367a
Author: Palash Chauhan <palashc...@gmail.com>
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 
<p.chau...@pchauha-ltmgv47.internal.salesforce.com>
---
 .../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());

Reply via email to