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
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);