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

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/dev/pr-12503-ce4071f0eacffb95c5c5d650273ab731931c58b5
in repository https://gitbox.apache.org/repos/asf/seatunnel.git

commit ed13548892eba42843cbde62d723c7786e3a1885
Author: hutiefang76 <[email protected]>
AuthorDate: Sun Oct 4 22:59:41 2026 +0000

    [Fix][Connector-V2] Escape DuckDB catalog metadata literals (#12503)
---
 .../jdbc/catalog/duckdb/DuckDBCatalog.java         | 12 +++++++++--
 .../jdbc/catalog/duckdb/DuckDBCatalogTest.java     | 23 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git 
a/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalog.java
 
b/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalog.java
index c3742bdc62..e9652f129d 100644
--- 
a/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalog.java
+++ 
b/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalog.java
@@ -159,7 +159,9 @@ public class DuckDBCatalog extends AbstractJdbcCatalog {
 
     protected String getSelectColumnsSql(TablePath tablePath) {
         return String.format(
-                SELECT_COLUMNS_SQL_TEMPLATE, tablePath.getSchemaName(), 
tablePath.getTableName());
+                SELECT_COLUMNS_SQL_TEMPLATE,
+                escapeSqlLiteral(tablePath.getSchemaName()),
+                escapeSqlLiteral(tablePath.getTableName()));
     }
 
     @Override
@@ -228,7 +230,13 @@ public class DuckDBCatalog extends AbstractJdbcCatalog {
         return String.format(
                 "SELECT table_schema, table_name FROM 
information_schema.tables "
                         + "WHERE table_schema = '%s' AND table_name = '%s'",
-                tablePath.getSchemaName(), tablePath.getTableName());
+                escapeSqlLiteral(tablePath.getSchemaName()),
+                escapeSqlLiteral(tablePath.getTableName()));
+    }
+
+    private String escapeSqlLiteral(String value) {
+        // Preserve the existing String.format behavior for a missing schema.
+        return value == null ? null : value.replace("'", "''");
     }
 
     @Override
diff --git 
a/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalogTest.java
 
b/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalogTest.java
index 49bec53042..90f171603f 100644
--- 
a/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalogTest.java
+++ 
b/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/catalog/duckdb/DuckDBCatalogTest.java
@@ -211,6 +211,29 @@ public class DuckDBCatalogTest {
         Assertions.assertFalse(catalog.tableExists(copyPath));
     }
 
+    @Test
+    @Order(8)
+    public void testMetadataLookupWithApostrophes() throws Exception {
+        TablePath tablePath = TablePath.of(DATABASE_NAME, "odd'schema", 
"odd'table");
+        try (Statement statement = 
catalog.getConnection(jdbcUrl).createStatement()) {
+            statement.execute("CREATE SCHEMA \"odd'schema\"");
+            statement.execute("CREATE TABLE \"odd'schema\".\"odd'table\" (id 
INTEGER)");
+            try {
+                Assertions.assertTrue(catalog.tableExists(tablePath));
+                Assertions.assertFalse(
+                        catalog.tableExists(TablePath.of(DATABASE_NAME, null, 
"odd'table")));
+                CatalogTable table = catalog.getTable(tablePath);
+                Assertions.assertEquals("id", 
table.getTableSchema().getColumns().get(0).getName());
+                Assertions.assertFalse(
+                        catalog.tableExists(
+                                TablePath.of(DATABASE_NAME, "odd'schema", "x' 
OR 1=1 --")));
+            } finally {
+                statement.execute("DROP TABLE \"odd'schema\".\"odd'table\"");
+                statement.execute("DROP SCHEMA \"odd'schema\"");
+            }
+        }
+    }
+
     private void createTestTable(String tableName) throws Exception {
         Connection connection = catalog.getConnection(jdbcUrl);
         try (Statement statement = connection.createStatement()) {

Reply via email to