From d26b96e845acbde3c964f4fa20769eaf231f2363 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 06:26:16 +0000 Subject: [PATCH 1/2] Bump org.postgresql:postgresql in /contrib/storage-jdbc Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.4.4 to 42.7.11. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.4.4...REL42.7.11) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-version: 42.7.11 dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- contrib/storage-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/storage-jdbc/pom.xml b/contrib/storage-jdbc/pom.xml index a7c889cd202..d9fb721c4d1 100644 --- a/contrib/storage-jdbc/pom.xml +++ b/contrib/storage-jdbc/pom.xml @@ -34,7 +34,7 @@ 8.4.0 0.3.1 2.2.220 - 42.4.4 + 42.7.11 13.2.1.jre11 1.3.1 From 898a519938298c24a20f483f90567125d1a17b69 Mon Sep 17 00:00:00 2001 From: cgivre Date: Mon, 22 Jun 2026 22:40:14 -0400 Subject: [PATCH 2/2] Keep JDBC schemas at top level with postgresql 42.7+ The PostgreSQL JDBC driver 42.7+ reports the connection's own database as the TABLE_CATALOG for DatabaseMetaData.getSchemas(), whereas 42.4.x reported null. JdbcCatalogSchema used that catalog value to nest schemas under their catalog, so "pg.public" silently became "pg..public". This broke every Postgres storage test ("Schema [pg.public] is not valid") and would have changed the schema paths existing Drill users query. When the driver reports catalogs other than the connection's own (as servers like PostgreSQL do, listing sibling databases a single connection cannot query across), register the connection's own catalog's schemas at the plugin top level rather than nested under the catalog. This restores the pre-42.7 paths without any dialect-specific code. Single-catalog sources such as H2 keep their existing catalog nesting, so "h2.tmp.drill_h2_test" is unaffected. --- .../exec/store/jdbc/JdbcCatalogSchema.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcCatalogSchema.java b/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcCatalogSchema.java index 333544afb31..027e1ff9b68 100644 --- a/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcCatalogSchema.java +++ b/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcCatalogSchema.java @@ -50,11 +50,14 @@ class JdbcCatalogSchema extends AbstractSchema { super(Collections.emptyList(), name); this.schemaMap = new HashMap<>(); String connectionSchemaName = null; + String connectionCatalogName = null; + boolean hasForeignCatalog = false; try (Connection con = source.getConnection(); ResultSet set = con.getMetaData().getCatalogs()) { try { connectionSchemaName = con.getSchema(); + connectionCatalogName = con.getCatalog(); } catch (AbstractMethodError ex) { // DRILL-8227. Some Sybase JDBC drivers still don't implement this method, e.g. JConnect, jTDS. logger.warn( @@ -70,6 +73,10 @@ class JdbcCatalogSchema extends AbstractSchema { continue; } + if (connectionCatalogName == null || !catalogName.equalsIgnoreCase(connectionCatalogName)) { + hasForeignCatalog = true; + } + CapitalizingJdbcSchema schema = new CapitalizingJdbcSchema( getSchemaPath(), catalogName, source, dialect, convention, catalogName, null, caseSensitive); schemaMap.put(schema.getName(), schema); @@ -78,11 +85,20 @@ class JdbcCatalogSchema extends AbstractSchema { logger.warn("Failure while attempting to load JDBC schema.", e); } + // When the driver reports catalogs other than the connection's own, the catalog (database) + // level is not navigable within a single connection (e.g. PostgreSQL, where each connection is + // bound to one database). In that case register the connection's own catalog's schemas at the + // plugin top level (e.g. "pg.public") instead of nested under the catalog ("pg..public"). + // Older drivers achieved this by reporting a null catalog from getSchemas(); some newer ones + // (e.g. PostgreSQL JDBC 42.7+) report the database instead, which would otherwise change the + // schema path. Single-catalog sources such as H2 keep the existing catalog nesting. + String catalogToFlatten = hasForeignCatalog ? connectionCatalogName : null; + // unable to read catalog list. if (schemaMap.isEmpty()) { // try to add a list of schemas to the schema map. - boolean schemasAdded = addSchemas(source, dialect, convention, caseSensitive); + boolean schemasAdded = addSchemas(source, dialect, convention, caseSensitive, catalogToFlatten); if (!schemasAdded) { // there were no schemas, just create a default one (the jdbc system doesn't support catalogs/schemas). @@ -91,7 +107,7 @@ class JdbcCatalogSchema extends AbstractSchema { } } else { // We already have catalogs. Add schemas in this context of their catalogs. - addSchemas(source, dialect, convention, caseSensitive); + addSchemas(source, dialect, convention, caseSensitive, catalogToFlatten); } defaultSchema = determineDefaultSchema(connectionSchemaName); @@ -114,13 +130,20 @@ void setHolder(SchemaPlus plusOfThis) { } } - private boolean addSchemas(DataSource source, SqlDialect dialect, DrillJdbcConvention convention, boolean caseSensitive) { + private boolean addSchemas(DataSource source, SqlDialect dialect, DrillJdbcConvention convention, + boolean caseSensitive, String catalogToFlatten) { boolean added = false; try (Connection con = source.getConnection(); ResultSet set = con.getMetaData().getSchemas()) { while (set.next()) { final String schemaName = set.getString(1); - final String catalogName = set.getString(2); + String catalogName = set.getString(2); + + // Hoist the connection's own catalog's schemas to the plugin top level (see the catalog + // loop above) by dropping the catalog so they are not nested under it. + if (catalogToFlatten != null && catalogToFlatten.equalsIgnoreCase(catalogName)) { + catalogName = null; + } String parentKey = StringUtils.lowerCase(catalogName); CapitalizingJdbcSchema parentSchema = schemaMap.get(parentKey);