This is an automated email from the ASF dual-hosted git repository.
jerryshao pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new dba3aafdac [Cherry-pick to branch-1.3] [MINOR] fix(server): Default
JDBC drivers in catalog REST APIs (#13942) (#13966)
dba3aafdac is described below
commit dba3aafdac93ce97162dc76716ee9d595bf129bc
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Oct 21 10:48:20 2026 +0800
[Cherry-pick to branch-1.3] [MINOR] fix(server): Default JDBC drivers in
catalog REST APIs (#13942) (#13966)
**Cherry-pick Information:**
- Original commit: 2b41cab63f8b1a4b0b08fed274bf75bfd5a0ce47
- Target branch: `branch-1.3`
- Status: ✅ Clean cherry-pick (no conflicts)
Co-authored-by: roryqi <[email protected]>
---
.../apache/gravitino/catalog/CatalogManager.java | 5 +-
.../gravitino/catalog/JdbcDriverProperties.java | 94 ++++++++++++++++++++
.../gravitino/catalog/TestCatalogManager.java | 39 +++++++++
.../catalog/TestJdbcDriverProperties.java | 99 ++++++++++++++++++++++
4 files changed, 235 insertions(+), 2 deletions(-)
diff --git
a/core/src/main/java/org/apache/gravitino/catalog/CatalogManager.java
b/core/src/main/java/org/apache/gravitino/catalog/CatalogManager.java
index 599d9fc735..153e8b7002 100644
--- a/core/src/main/java/org/apache/gravitino/catalog/CatalogManager.java
+++ b/core/src/main/java/org/apache/gravitino/catalog/CatalogManager.java
@@ -1604,11 +1604,12 @@ public class CatalogManager implements
CatalogDispatcher, Closeable {
return builder.withAuditInfo(newInfo);
}
- private Map<String, String> buildCatalogConf(String provider, Map<String,
String> properties) {
+ Map<String, String> buildCatalogConf(String provider, Map<String, String>
properties) {
Map<String, String> newProperties =
Optional.ofNullable(properties).orElse(Maps.newHashMap());
// load catalog-related configuration from catalog-specific configuration
file
Map<String, String> catalogSpecificConfig =
loadCatalogSpecificConfig(newProperties, provider);
- return mergeConf(newProperties, catalogSpecificConfig);
+ return JdbcDriverProperties.withDefaultDriver(
+ provider, mergeConf(newProperties, catalogSpecificConfig));
}
private Pair<Map<String, String>, Map<String, String>>
getCatalogAlterProperty(
diff --git
a/core/src/main/java/org/apache/gravitino/catalog/JdbcDriverProperties.java
b/core/src/main/java/org/apache/gravitino/catalog/JdbcDriverProperties.java
new file mode 100644
index 0000000000..1dfa360135
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/catalog/JdbcDriverProperties.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.catalog;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import javax.annotation.Nullable;
+
+/** Adds the known JDBC driver class to catalog properties when the caller
omits it. */
+public final class JdbcDriverProperties {
+
+ private static final String JDBC_DRIVER = "jdbc-driver";
+ private static final Map<String, String> PROVIDER_DRIVERS =
+ ImmutableMap.<String, String>builder()
+ .put("jdbc-clickhouse", "com.clickhouse.jdbc.ClickHouseDriver")
+ .put("jdbc-doris", "com.mysql.cj.jdbc.Driver")
+ .put("jdbc-hologres", "org.postgresql.Driver")
+ .put("jdbc-mysql", "com.mysql.cj.jdbc.Driver")
+ .put("jdbc-postgresql", "org.postgresql.Driver")
+ .put("jdbc-starrocks", "com.mysql.cj.jdbc.Driver")
+ .build();
+
+ private JdbcDriverProperties() {}
+
+ /**
+ * Returns properties with a derived driver, leaving the input map unchanged.
+ *
+ * @param provider catalog provider
+ * @param properties requested catalog properties
+ * @return properties with a driver when one can be inferred
+ */
+ @Nullable
+ public static Map<String, String> withDefaultDriver(
+ @Nullable String provider, @Nullable Map<String, String> properties) {
+ if (provider == null || (properties != null && properties.get(JDBC_DRIVER)
!= null)) {
+ return properties;
+ }
+
+ String driver = PROVIDER_DRIVERS.get(provider.toLowerCase(Locale.ROOT));
+ if ("jdbc-oceanbase".equalsIgnoreCase(provider)) {
+ driver = null;
+ String url = properties == null ? null : properties.get("jdbc-url");
+ if (url != null) {
+ String normalizedUrl = url.trim().toLowerCase(Locale.ROOT);
+ if (normalizedUrl.startsWith("jdbc:oceanbase:")) {
+ driver = "com.oceanbase.jdbc.Driver";
+ } else if (normalizedUrl.startsWith("jdbc:mysql:")) {
+ driver = "com.mysql.cj.jdbc.Driver";
+ }
+ }
+ }
+ if (driver == null && "lakehouse-iceberg".equalsIgnoreCase(provider) &&
properties != null) {
+ if ("jdbc".equalsIgnoreCase(properties.get("catalog-backend"))) {
+ String uri = properties.get("uri");
+ if (uri != null) {
+ String normalizedUri = uri.trim().toLowerCase(Locale.ROOT);
+ if (normalizedUri.startsWith("jdbc:mysql:")) {
+ driver = "com.mysql.cj.jdbc.Driver";
+ } else if (normalizedUri.startsWith("jdbc:postgresql:")) {
+ driver = "org.postgresql.Driver";
+ }
+ }
+ }
+ }
+
+ if (driver == null) {
+ return properties;
+ }
+ Map<String, String> result = new HashMap<>();
+ if (properties != null) {
+ result.putAll(properties);
+ }
+ result.put(JDBC_DRIVER, driver);
+ return result;
+ }
+}
diff --git
a/core/src/test/java/org/apache/gravitino/catalog/TestCatalogManager.java
b/core/src/test/java/org/apache/gravitino/catalog/TestCatalogManager.java
index c3f9aa4a67..d64aff46de 100644
--- a/core/src/test/java/org/apache/gravitino/catalog/TestCatalogManager.java
+++ b/core/src/test/java/org/apache/gravitino/catalog/TestCatalogManager.java
@@ -34,6 +34,9 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
@@ -95,6 +98,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.Mockito;
@@ -159,6 +163,41 @@ public class TestCatalogManager {
}
}
+ @Test
+ void testJdbcDriverDefaultAfterProviderConfigMerge(@TempDir Path
catalogPackage)
+ throws IOException {
+ Path conf = Files.createDirectories(catalogPackage.resolve("conf"));
+ Path configFile = conf.resolve("jdbc-oceanbase.conf");
+ Files.write(configFile,
"jdbc-driver=configured.Driver\n".getBytes(StandardCharsets.UTF_8));
+ Map<String, String> request =
+ ImmutableMap.of(
+ Catalog.PROPERTY_PACKAGE,
+ catalogPackage.toString(),
+ "jdbc-url",
+ "jdbc:oceanbase://localhost:2881/test");
+
+ Assertions.assertEquals(
+ "configured.Driver",
+ catalogManager.buildCatalogConf("jdbc-oceanbase",
request).get("jdbc-driver"));
+
+ Map<String, String> explicit = Maps.newHashMap(request);
+ explicit.put("jdbc-driver", "request.Driver");
+ Assertions.assertEquals(
+ "request.Driver",
+ catalogManager.buildCatalogConf("jdbc-oceanbase",
explicit).get("jdbc-driver"));
+
+ Files.write(
+ configFile,
+
"jdbc-url=jdbc:oceanbase://localhost:2881/test\n".getBytes(StandardCharsets.UTF_8));
+ Assertions.assertEquals(
+ "com.oceanbase.jdbc.Driver",
+ catalogManager
+ .buildCatalogConf(
+ "jdbc-oceanbase",
+ ImmutableMap.of(Catalog.PROPERTY_PACKAGE,
catalogPackage.toString()))
+ .get("jdbc-driver"));
+ }
+
@Test
void testPropertyValidationInAlter() throws IOException {
// key1 is required and immutable and do not have default value, is not
hidden and not reserved
diff --git
a/core/src/test/java/org/apache/gravitino/catalog/TestJdbcDriverProperties.java
b/core/src/test/java/org/apache/gravitino/catalog/TestJdbcDriverProperties.java
new file mode 100644
index 0000000000..5006af718c
--- /dev/null
+++
b/core/src/test/java/org/apache/gravitino/catalog/TestJdbcDriverProperties.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.catalog;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/** Tests catalog JDBC driver defaults. */
+public class TestJdbcDriverProperties {
+
+ @Test
+ void testProviderDefaults() {
+ Map<String, String> drivers =
+ ImmutableMap.<String, String>builder()
+ .put("jdbc-clickhouse", "com.clickhouse.jdbc.ClickHouseDriver")
+ .put("jdbc-doris", "com.mysql.cj.jdbc.Driver")
+ .put("jdbc-hologres", "org.postgresql.Driver")
+ .put("jdbc-mysql", "com.mysql.cj.jdbc.Driver")
+ .put("jdbc-postgresql", "org.postgresql.Driver")
+ .put("jdbc-starrocks", "com.mysql.cj.jdbc.Driver")
+ .build();
+ drivers.forEach(
+ (provider, driver) -> {
+ Map<String, String> input = ImmutableMap.of("key", "value");
+ Map<String, String> result =
JdbcDriverProperties.withDefaultDriver(provider, input);
+ Assertions.assertEquals(driver, result.get("jdbc-driver"));
+ Assertions.assertEquals("value", result.get("key"));
+ Assertions.assertFalse(input.containsKey("jdbc-driver"));
+ });
+ }
+
+ @Test
+ void testIcebergJdbcBackendDefaults() {
+ Map<String, String> postgres =
+ ImmutableMap.of("catalog-backend", "jdbc", "uri",
"jdbc:postgresql://host/db");
+ Assertions.assertEquals(
+ "org.postgresql.Driver",
+ JdbcDriverProperties.withDefaultDriver("lakehouse-iceberg",
postgres).get("jdbc-driver"));
+
+ Map<String, String> mysql =
+ ImmutableMap.of("catalog-backend", "jdbc", "uri",
"jdbc:mysql://host/db");
+ Assertions.assertEquals(
+ "com.mysql.cj.jdbc.Driver",
+ JdbcDriverProperties.withDefaultDriver("lakehouse-iceberg",
mysql).get("jdbc-driver"));
+ }
+
+ @Test
+ void testOceanBaseDriverFollowsJdbcUrl() {
+ Map<String, String> nativeUrl =
+ ImmutableMap.of("jdbc-url", "jdbc:oceanbase://localhost:2881/test");
+ Assertions.assertEquals(
+ "com.oceanbase.jdbc.Driver",
+ JdbcDriverProperties.withDefaultDriver("jdbc-oceanbase",
nativeUrl).get("jdbc-driver"));
+
+ Map<String, String> mysqlUrl = ImmutableMap.of("jdbc-url",
"jdbc:mysql://localhost:2881/test");
+ Assertions.assertEquals(
+ "com.mysql.cj.jdbc.Driver",
+ JdbcDriverProperties.withDefaultDriver("jdbc-oceanbase",
mysqlUrl).get("jdbc-driver"));
+
+ Map<String, String> unknownUrl = ImmutableMap.of("jdbc-url",
"jdbc:unknown://localhost/test");
+ Assertions.assertSame(
+ unknownUrl, JdbcDriverProperties.withDefaultDriver("jdbc-oceanbase",
unknownUrl));
+ }
+
+ @Test
+ void testExplicitAndUnknownDrivers() {
+ Map<String, String> explicit = ImmutableMap.of("jdbc-driver",
"custom.Driver");
+ Assertions.assertSame(explicit,
JdbcDriverProperties.withDefaultDriver("jdbc-mysql", explicit));
+ Map<String, String> unknown =
+ ImmutableMap.of("catalog-backend", "jdbc", "uri",
"jdbc:sqlite::memory:");
+ Assertions.assertSame(
+ unknown, JdbcDriverProperties.withDefaultDriver("lakehouse-iceberg",
unknown));
+ Assertions.assertSame(unknown,
JdbcDriverProperties.withDefaultDriver("hive", unknown));
+ Assertions.assertSame(
+ unknown, JdbcDriverProperties.withDefaultDriver("jdbc-sqlserver",
unknown));
+ Assertions.assertNull(JdbcDriverProperties.withDefaultDriver(null, null));
+ Assertions.assertEquals(
+ "com.mysql.cj.jdbc.Driver",
+ JdbcDriverProperties.withDefaultDriver("JDBC-MySQL",
null).get("jdbc-driver"));
+ }
+}