diff --git a/plugin/trino-mariadb/pom.xml b/plugin/trino-mariadb/pom.xml index 91974127a001..77d5120ef52e 100644 --- a/plugin/trino-mariadb/pom.xml +++ b/plugin/trino-mariadb/pom.xml @@ -28,6 +28,11 @@ trino-plugin-toolkit + + io.airlift + configuration + + com.google.guava guava @@ -43,6 +48,11 @@ javax.inject + + javax.validation + validation-api + + org.mariadb.jdbc mariadb-java-client diff --git a/plugin/trino-mariadb/src/main/java/io/trino/plugin/mariadb/MariaDbClientModule.java b/plugin/trino-mariadb/src/main/java/io/trino/plugin/mariadb/MariaDbClientModule.java index e6c904c29f7c..4f0df3e3cd63 100644 --- a/plugin/trino-mariadb/src/main/java/io/trino/plugin/mariadb/MariaDbClientModule.java +++ b/plugin/trino-mariadb/src/main/java/io/trino/plugin/mariadb/MariaDbClientModule.java @@ -32,6 +32,7 @@ import java.util.Properties; import static com.google.inject.multibindings.Multibinder.newSetBinder; +import static io.airlift.configuration.ConfigBinder.configBinder; public class MariaDbClientModule implements Module @@ -40,6 +41,7 @@ public class MariaDbClientModule public void configure(Binder binder) { binder.bind(JdbcClient.class).annotatedWith(ForBaseJdbc.class).to(MariaDbClient.class).in(Scopes.SINGLETON); + configBinder(binder).bindConfig(MariaDbJdbcConfig.class); binder.install(new DecimalModule()); newSetBinder(binder, ConnectorTableFunction.class).addBinding().toProvider(Query.class).in(Scopes.SINGLETON); } diff --git a/plugin/trino-mariadb/src/main/java/io/trino/plugin/mariadb/MariaDbJdbcConfig.java b/plugin/trino-mariadb/src/main/java/io/trino/plugin/mariadb/MariaDbJdbcConfig.java new file mode 100644 index 000000000000..42dba88495f2 --- /dev/null +++ b/plugin/trino-mariadb/src/main/java/io/trino/plugin/mariadb/MariaDbJdbcConfig.java @@ -0,0 +1,48 @@ +/* + * Licensed 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 io.trino.plugin.mariadb; + +import io.trino.plugin.jdbc.BaseJdbcConfig; +import org.mariadb.jdbc.Configuration; +import org.mariadb.jdbc.Driver; + +import javax.validation.constraints.AssertTrue; + +import java.sql.SQLException; + +public class MariaDbJdbcConfig + extends BaseJdbcConfig +{ + @AssertTrue(message = "Invalid JDBC URL for MariaDB connector") + public boolean isUrlValid() + { + Driver driver = new Driver(); + return driver.acceptsURL(getConnectionUrl()); + } + + @AssertTrue(message = "Database (catalog) must not be specified in JDBC URL for MariaDB connector") + public boolean isUrlWithoutDatabase() + { + try { + Configuration conf = Configuration.parse(getConnectionUrl()); + if (conf == null) { + return false; + } + return conf.database() == null; + } + catch (SQLException e) { + return false; + } + } +} diff --git a/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestMariaDbJdbcConfig.java b/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestMariaDbJdbcConfig.java new file mode 100644 index 000000000000..f5c4556e0a6d --- /dev/null +++ b/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestMariaDbJdbcConfig.java @@ -0,0 +1,53 @@ +/* + * Licensed 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 io.trino.plugin.mariadb; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +public class TestMariaDbJdbcConfig +{ + @Test + public void testIsUrlValid() + { + assertTrue(isUrlValid("jdbc:mariadb://example.net:3306")); + assertTrue(isUrlValid("jdbc:mariadb://example.net:3306/")); + assertFalse(isUrlValid("jdbc:notmariadb://example.net:3306")); + assertFalse(isUrlValid("jdbc:notmariadb://example.net:3306/")); + } + + private static boolean isUrlValid(String url) + { + MariaDbJdbcConfig config = new MariaDbJdbcConfig(); + config.setConnectionUrl(url); + return config.isUrlValid(); + } + + @Test + public void testIsUrlWithoutDatabase() + { + assertTrue(isUrlWithoutDatabase("jdbc:mariadb://example.net:3306")); + assertTrue(isUrlWithoutDatabase("jdbc:mariadb://example.net:3306/")); + assertFalse(isUrlWithoutDatabase("jdbc:mariadb://example.net:3306/somedatabase")); + } + + private static boolean isUrlWithoutDatabase(String url) + { + MariaDbJdbcConfig config = new MariaDbJdbcConfig(); + config.setConnectionUrl(url); + return config.isUrlWithoutDatabase(); + } +} diff --git a/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestMariaDbPlugin.java b/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestMariaDbPlugin.java index 6985b323c70d..846f8eef1752 100644 --- a/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestMariaDbPlugin.java +++ b/plugin/trino-mariadb/src/test/java/io/trino/plugin/mariadb/TestMariaDbPlugin.java @@ -20,6 +20,7 @@ import org.testng.annotations.Test; import static com.google.common.collect.Iterables.getOnlyElement; +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class TestMariaDbPlugin { @@ -29,5 +30,11 @@ public void testCreateConnector() Plugin plugin = new MariaDbPlugin(); ConnectorFactory factory = getOnlyElement(plugin.getConnectorFactories()); factory.create("test", ImmutableMap.of("connection-url", "jdbc:mariadb://test"), new TestingConnectorContext()).shutdown(); + + assertThatThrownBy(() -> factory.create("test", ImmutableMap.of("connection-url", "test"), new TestingConnectorContext())) + .hasMessageContaining("Invalid JDBC URL for MariaDB connector"); + + assertThatThrownBy(() -> factory.create("test", ImmutableMap.of("connection-url", "jdbc:mariadb://test/abc"), new TestingConnectorContext())) + .hasMessageContaining("Database (catalog) must not be specified in JDBC URL for MariaDB connector"); } }