From 9252daf6aef69d308db38bb76ac79d55f490d9b4 Mon Sep 17 00:00:00 2001 From: Dan Homola Date: Tue, 19 May 2026 13:33:57 +0200 Subject: [PATCH] Fix double backtick wrapping in setCatalog and setSchema When catalog or schema names were passed already wrapped in backticks, setCatalog/setSchema would produce invalid SQL like SET CATALOG ``name``. Strip existing backticks before wrapping and before storing, so getCatalog/ getSchema always return the bare identifier name. Fixes #1453 Signed-off-by: Dan Homola --- NEXT_CHANGELOG.md | 3 +- .../jdbc/api/impl/DatabricksConnection.java | 20 +++++-- .../api/impl/DatabricksConnectionTest.java | 54 +++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index e7b2d83d4..caacd7814 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -49,7 +49,8 @@ upgrading. These changes do not affect metadata on All-Purpose Clusters. - Fixed `?` characters inside SQL comments, string literals, and quoted identifiers being incorrectly counted as parameter placeholders when `supportManyParameters=1`. `SQLInterpolator` now uses `SqlCommentParser` to locate only real placeholders. Fixes #1331. - Fixed `MetadataOperationTimeout` not being applied when metadata operations use SHOW commands. Operations like `getTables`, `getSchemas`, and `getColumns` now respect the `MetadataOperationTimeout` connection property instead of hanging indefinitely with no timeout. - Reclassify transient server errors to standard SQL states (08S01, 40001) across all Thrift error sites. This ensures UC unavailability and concurrent modification errors surface consistently for better retry handling. Note: Dashboards and branching logic keyed on legacy XXUCC or 42000 must be updated. +- Fixed `setCatalog()` and `setSchema()` producing invalid SQL (e.g. `SET CATALOG ``name``) when the catalog or schema name was passed already wrapped in backticks. Backticks are now stripped before wrapping, and `getCatalog()`/`getSchema()` return the bare identifier name. --- *Note: When making changes, please add your change under the appropriate section -with a brief description.* +with a brief description.* \ No newline at end of file diff --git a/src/main/java/com/databricks/jdbc/api/impl/DatabricksConnection.java b/src/main/java/com/databricks/jdbc/api/impl/DatabricksConnection.java index 691bcc3ff..0c755f3a5 100644 --- a/src/main/java/com/databricks/jdbc/api/impl/DatabricksConnection.java +++ b/src/main/java/com/databricks/jdbc/api/impl/DatabricksConnection.java @@ -465,8 +465,9 @@ public void setCatalog(String catalog) throws SQLException { return; } Statement statement = this.createStatement(); - statement.execute("SET CATALOG `" + catalog + "`"); - this.session.setCatalog(catalog); + String cleanCatalog = stripBackticks(catalog); + statement.execute("SET CATALOG `" + cleanCatalog + "`"); + this.session.setCatalog(cleanCatalog); } @Override @@ -841,8 +842,9 @@ public Struct createStruct(String typeName, Object[] attributes) throws SQLExcep @Override public void setSchema(String schema) throws SQLException { Statement statement = this.createStatement(); - statement.execute("USE SCHEMA `" + schema + "`"); - session.setSchema(schema); + String cleanSchema = stripBackticks(schema); + statement.execute("USE SCHEMA `" + cleanSchema + "`"); + session.setSchema(cleanSchema); } @Override @@ -1066,4 +1068,14 @@ private void closeStatementSafely(Statement statement) { } } } + + private static String stripBackticks(String identifier) { + if (identifier != null + && identifier.startsWith("`") + && identifier.endsWith("`") + && identifier.length() >= 2) { + return identifier.substring(1, identifier.length() - 1); + } + return identifier; + } } diff --git a/src/test/java/com/databricks/jdbc/api/impl/DatabricksConnectionTest.java b/src/test/java/com/databricks/jdbc/api/impl/DatabricksConnectionTest.java index f57a769fa..4828de2d0 100644 --- a/src/test/java/com/databricks/jdbc/api/impl/DatabricksConnectionTest.java +++ b/src/test/java/com/databricks/jdbc/api/impl/DatabricksConnectionTest.java @@ -134,6 +134,60 @@ public void testGetAndSetSchemaAndCatalog() throws SQLException { assertEquals(connection.getSchema(), DEFAULT_SCHEMA); } + @Test + public void testSetCatalogAndSchemaWithPreWrappedBackticks() throws SQLException { + when(databricksClient.createSession( + new Warehouse(WAREHOUSE_ID), CATALOG, SCHEMA, new HashMap<>())) + .thenReturn(IMMUTABLE_SESSION_INFO); + connection = new DatabricksConnection(connectionContext, databricksClient); + connection.open(); + + String backtickWrappedCatalog = "`catalog-with-hyphen`"; + when(databricksClient.executeStatement( + eq("SET CATALOG `catalog-with-hyphen`"), + eq(new Warehouse(WAREHOUSE_ID)), + eq(new HashMap<>()), + eq(StatementType.SQL), + any(), + any(), + any())) + .thenReturn(resultSet); + connection.setCatalog(backtickWrappedCatalog); + assertEquals(connection.getCatalog(), "catalog-with-hyphen"); + + String backtickWrappedSchema = "`schema-with-hyphen`"; + when(databricksClient.executeStatement( + eq("USE SCHEMA `schema-with-hyphen`"), + eq(new Warehouse(WAREHOUSE_ID)), + eq(new HashMap<>()), + eq(StatementType.SQL), + any(), + any(), + any())) + .thenReturn(resultSet); + connection.setSchema(backtickWrappedSchema); + assertEquals(connection.getSchema(), "schema-with-hyphen"); + + verify(databricksClient) + .executeStatement( + eq("SET CATALOG `catalog-with-hyphen`"), + eq(new Warehouse(WAREHOUSE_ID)), + eq(new HashMap<>()), + eq(StatementType.SQL), + any(), + any(), + any()); + verify(databricksClient) + .executeStatement( + eq("USE SCHEMA `schema-with-hyphen`"), + eq(new Warehouse(WAREHOUSE_ID)), + eq(new HashMap<>()), + eq(StatementType.SQL), + any(), + any(), + any()); + } + @Test public void testSetCatalogAndSchemaWithHyphenatedIdentifiers() throws SQLException { when(databricksClient.createSession(