diff --git a/plugin/trino-mysql/pom.xml b/plugin/trino-mysql/pom.xml
index 023696684441..91ba1dc50698 100644
--- a/plugin/trino-mysql/pom.xml
+++ b/plugin/trino-mysql/pom.xml
@@ -160,6 +160,20 @@
test
+
+
+ org.mariadb.jdbc
+ mariadb-java-client
+ 2.4.0
+ test
+
+
+
+ org.testcontainers
+ mariadb
+ test
+
+
org.testcontainers
mysql
diff --git a/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClient.java b/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClient.java
index 8cf49e01b0e7..4e5970e6465e 100644
--- a/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClient.java
+++ b/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClient.java
@@ -14,7 +14,7 @@
package io.trino.plugin.mysql;
import com.google.common.collect.ImmutableSet;
-import com.mysql.jdbc.Statement;
+import com.mysql.cj.jdbc.JdbcStatement;
import io.trino.plugin.jdbc.BaseJdbcClient;
import io.trino.plugin.jdbc.BaseJdbcConfig;
import io.trino.plugin.jdbc.ColumnMapping;
@@ -73,8 +73,8 @@
import static com.google.common.base.Verify.verify;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
-import static com.mysql.jdbc.SQLError.SQL_STATE_ER_TABLE_EXISTS_ERROR;
-import static com.mysql.jdbc.SQLError.SQL_STATE_SYNTAX_ERROR;
+import static com.mysql.cj.exceptions.MysqlErrorNumbers.SQL_STATE_ER_TABLE_EXISTS_ERROR;
+import static com.mysql.cj.exceptions.MysqlErrorNumbers.SQL_STATE_SYNTAX_ERROR;
import static io.airlift.slice.Slices.utf8Slice;
import static io.trino.plugin.base.util.JsonTypeUtil.jsonParse;
import static io.trino.plugin.jdbc.DecimalConfig.DecimalMapping.ALLOW_OVERFLOW;
@@ -212,8 +212,8 @@ public PreparedStatement getPreparedStatement(Connection connection, String sql)
throws SQLException
{
PreparedStatement statement = connection.prepareStatement(sql);
- if (statement.isWrapperFor(Statement.class)) {
- statement.unwrap(Statement.class).enableStreamingResults();
+ if (statement.isWrapperFor(JdbcStatement.class)) {
+ statement.unwrap(JdbcStatement.class).enableStreamingResults();
}
return statement;
}
diff --git a/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClientModule.java b/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClientModule.java
index 2f8f3908a835..8cfd1a105808 100644
--- a/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClientModule.java
+++ b/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlClientModule.java
@@ -52,7 +52,6 @@ public static ConnectionFactory createConnectionFactory(BaseJdbcConfig config, C
{
Properties connectionProperties = new Properties();
connectionProperties.setProperty("useInformationSchema", Boolean.toString(mySqlConfig.isDriverUseInformationSchema()));
- connectionProperties.setProperty("nullCatalogMeansCurrent", "false");
connectionProperties.setProperty("useUnicode", "true");
connectionProperties.setProperty("characterEncoding", "utf8");
connectionProperties.setProperty("tinyInt1isBit", "false");
diff --git a/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlJdbcConfig.java b/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlJdbcConfig.java
index fe707ca3f2a8..c4735e135149 100644
--- a/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlJdbcConfig.java
+++ b/plugin/trino-mysql/src/main/java/io/trino/plugin/mysql/MySqlJdbcConfig.java
@@ -13,13 +13,14 @@
*/
package io.trino.plugin.mysql;
-import com.mysql.jdbc.Driver;
+import com.mysql.cj.conf.ConnectionUrlParser;
+import com.mysql.cj.exceptions.CJException;
import io.trino.plugin.jdbc.BaseJdbcConfig;
import javax.validation.constraints.AssertTrue;
-import java.sql.SQLException;
-import java.util.Properties;
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static com.mysql.cj.conf.ConnectionUrlParser.parseConnectionString;
public class MySqlJdbcConfig
extends BaseJdbcConfig
@@ -28,12 +29,11 @@ public class MySqlJdbcConfig
public boolean isUrlValid()
{
try {
- Driver driver = new Driver();
- Properties properties = driver.parseURL(getConnectionUrl(), null);
- return properties != null;
+ parseConnectionString(getConnectionUrl());
+ return true;
}
- catch (SQLException e) {
- throw new RuntimeException(e);
+ catch (CJException ignored) {
+ return false;
}
}
@@ -41,12 +41,11 @@ public boolean isUrlValid()
public boolean isUrlWithoutDatabase()
{
try {
- Driver driver = new Driver();
- Properties properties = driver.parseURL(getConnectionUrl(), null);
- return (properties == null) || (driver.database(properties) == null);
+ ConnectionUrlParser parser = parseConnectionString(getConnectionUrl());
+ return isNullOrEmpty(parser.getPath());
}
- catch (SQLException e) {
- throw new RuntimeException(e);
+ catch (CJException ignored) {
+ return false;
}
}
}
diff --git a/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/MariaDBQueryRunner.java b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/MariaDBQueryRunner.java
new file mode 100644
index 000000000000..3f444a401443
--- /dev/null
+++ b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/MariaDBQueryRunner.java
@@ -0,0 +1,102 @@
+/*
+ * 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.mysql;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import io.airlift.log.Logger;
+import io.airlift.log.Logging;
+import io.trino.Session;
+import io.trino.plugin.tpch.TpchPlugin;
+import io.trino.testing.DistributedQueryRunner;
+import io.trino.testing.QueryRunner;
+import io.trino.tpch.TpchTable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static io.airlift.testing.Closeables.closeAllSuppress;
+import static io.trino.plugin.tpch.TpchMetadata.TINY_SCHEMA_NAME;
+import static io.trino.testing.QueryAssertions.copyTpchTables;
+import static io.trino.testing.TestingSession.testSessionBuilder;
+
+public class MariaDBQueryRunner
+{
+ private MariaDBQueryRunner() {}
+
+ private static final String TPCH_SCHEMA = "tpch";
+
+ public static QueryRunner createMariaDBQueryRunner(TestingMariaDBServer server, TpchTable>... tables)
+ throws Exception
+ {
+ return createMariaDBQueryRunner(server, ImmutableMap.of(), ImmutableMap.of(), ImmutableList.copyOf(tables));
+ }
+
+ public static DistributedQueryRunner createMariaDBQueryRunner(
+ TestingMariaDBServer server,
+ Map extraProperties,
+ Map connectorProperties,
+ Iterable> tables)
+ throws Exception
+ {
+ DistributedQueryRunner queryRunner = DistributedQueryRunner.builder(createSession())
+ .setExtraProperties(extraProperties)
+ .build();
+ try {
+ queryRunner.installPlugin(new TpchPlugin());
+ queryRunner.createCatalog("tpch", "tpch");
+
+ connectorProperties = new HashMap<>(ImmutableMap.copyOf(connectorProperties));
+ connectorProperties.putIfAbsent("connection-url", server.getJdbcUrl());
+ connectorProperties.putIfAbsent("connection-user", server.getUsername());
+ connectorProperties.putIfAbsent("connection-password", server.getPassword());
+ connectorProperties.putIfAbsent("allow-drop-table", "true");
+
+ queryRunner.installPlugin(new MySqlPlugin());
+ queryRunner.createCatalog("mysql", "mysql", connectorProperties);
+
+ copyTpchTables(queryRunner, "tpch", TINY_SCHEMA_NAME, createSession(), tables);
+
+ return queryRunner;
+ }
+ catch (Throwable e) {
+ closeAllSuppress(e, queryRunner);
+ throw e;
+ }
+ }
+
+ private static Session createSession()
+ {
+ return testSessionBuilder()
+ .setCatalog("mysql")
+ .setSchema(TPCH_SCHEMA)
+ .build();
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ Logging.initialize();
+
+ DistributedQueryRunner queryRunner = createMariaDBQueryRunner(
+ new TestingMariaDBServer(),
+ ImmutableMap.of("http-server.http.port", "8080"),
+ ImmutableMap.of(),
+ TpchTable.getTables());
+
+ Logger log = Logger.get(MariaDBQueryRunner.class);
+ log.info("======== SERVER STARTED ========");
+ log.info("\n====\n%s\n====", queryRunner.getCoordinator().getBaseUrl());
+ }
+}
diff --git a/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestMariaDbCompatibilityTest.java b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestMariaDbCompatibilityTest.java
new file mode 100644
index 000000000000..1c72c08d88ad
--- /dev/null
+++ b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestMariaDbCompatibilityTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.mysql;
+
+import com.google.common.collect.ImmutableMap;
+import io.trino.testing.QueryRunner;
+import io.trino.testing.sql.SqlExecutor;
+
+import static io.trino.plugin.mysql.MariaDBQueryRunner.createMariaDBQueryRunner;
+
+public class TestMariaDbCompatibilityTest
+ extends BaseMySqlConnectorTest
+{
+ private TestingMariaDBServer mariaDBServer;
+
+ @Override
+ protected QueryRunner createQueryRunner()
+ throws Exception
+ {
+ mariaDBServer = closeAfterClass(new TestingMariaDBServer());
+ return createMariaDBQueryRunner(mariaDBServer, ImmutableMap.of(), ImmutableMap.of(), REQUIRED_TPCH_TABLES);
+ }
+
+ @Override
+ protected SqlExecutor getMySqlExecutor()
+ {
+ return mariaDBServer::execute;
+ }
+}
diff --git a/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestingMariaDBServer.java b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestingMariaDBServer.java
new file mode 100644
index 000000000000..089ac4015702
--- /dev/null
+++ b/plugin/trino-mysql/src/test/java/io/trino/plugin/mysql/TestingMariaDBServer.java
@@ -0,0 +1,105 @@
+/*
+ * 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.mysql;
+
+import org.testcontainers.containers.MariaDBContainer;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static io.trino.testing.containers.TestContainers.startOrReuse;
+import static java.lang.String.format;
+
+public class TestingMariaDBServer
+ implements AutoCloseable
+{
+ private final MariaDBContainer> container;
+ private final Closeable cleanup;
+
+ public TestingMariaDBServer()
+ {
+ this("mariadb:10.5.4");
+ }
+
+ public TestingMariaDBServer(String dockerImageName)
+ {
+ MariaDBContainer> container = new MariaDBContainer<>(dockerImageName);
+ container = container.withDatabaseName("tpch");
+ this.container = container;
+ configureContainer(container);
+ cleanup = startOrReuse(container);
+ execute(format("GRANT ALL PRIVILEGES ON *.* TO '%s'", container.getUsername()), "root", container.getPassword());
+ }
+
+ protected void configureContainer(MariaDBContainer> container) {}
+
+ public Connection createConnection()
+ throws SQLException
+ {
+ return container.createConnection("");
+ }
+
+ public void execute(String sql)
+ {
+ execute(sql, getUsername(), getPassword());
+ }
+
+ public void execute(String sql, String user, String password)
+ {
+ try (Connection connection = DriverManager.getConnection(getJdbcUrl(), user, password);
+ Statement statement = connection.createStatement()) {
+ statement.execute(sql);
+ }
+ catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getUsername()
+ {
+ return container.getUsername();
+ }
+
+ public String getPassword()
+ {
+ return container.getPassword();
+ }
+
+ public String getDatabaseName()
+ {
+ return container.getDatabaseName();
+ }
+
+ public String getJdbcUrl()
+ {
+ // The connection URL is still using mysql to ensure we test MariaDB compatibility with the MySQL connector
+ return format("jdbc:mysql://%s:%s?useSSL=false&allowPublicKeyRetrieval=true", container.getContainerIpAddress(), container.getMappedPort(3306));
+ }
+
+ @Override
+ public void close()
+ {
+ try {
+ cleanup.close();
+ }
+ catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+}
diff --git a/plugin/trino-raptor-legacy/pom.xml b/plugin/trino-raptor-legacy/pom.xml
index 1f49234104ba..6e65968b9075 100644
--- a/plugin/trino-raptor-legacy/pom.xml
+++ b/plugin/trino-raptor-legacy/pom.xml
@@ -147,6 +147,7 @@
mysql
mysql-connector-java
+ ${dep.mysql5.version}
diff --git a/plugin/trino-resource-group-managers/pom.xml b/plugin/trino-resource-group-managers/pom.xml
index c58afd8abdb6..9f773f549e0e 100644
--- a/plugin/trino-resource-group-managers/pom.xml
+++ b/plugin/trino-resource-group-managers/pom.xml
@@ -102,6 +102,7 @@
mysql
mysql-connector-java
+ ${dep.mysql5.version}
diff --git a/plugin/trino-session-property-managers/pom.xml b/plugin/trino-session-property-managers/pom.xml
index 4fc63dbc07dd..5d6016ef2800 100644
--- a/plugin/trino-session-property-managers/pom.xml
+++ b/plugin/trino-session-property-managers/pom.xml
@@ -102,6 +102,7 @@
mysql
mysql-connector-java
+ ${dep.mysql5.version}
diff --git a/pom.xml b/pom.xml
index 7dc6483edaa0..b1c4fba1ce69 100644
--- a/pom.xml
+++ b/pom.xml
@@ -63,6 +63,7 @@
3.2.7
1.0.25
5.5.2
+ 5.1.48