diff --git a/pom.xml b/pom.xml index 20e190a..5644e4c 100644 --- a/pom.xml +++ b/pom.xml @@ -363,6 +363,24 @@ + + mysql + mysql-connector-java + 8.0.28 + provided + + + org.mariadb.jdbc + mariadb-java-client + 2.7.5 + provided + + + com.microsoft.sqlserver + mssql-jdbc + 10.2.0.jre8 + provided + org.appng appng-testsupport diff --git a/src/main/java/org/appng/application/manager/business/SqlExecutor.java b/src/main/java/org/appng/application/manager/business/SqlExecutor.java index 5f7f392..0e59690 100644 --- a/src/main/java/org/appng/application/manager/business/SqlExecutor.java +++ b/src/main/java/org/appng/application/manager/business/SqlExecutor.java @@ -16,6 +16,7 @@ package org.appng.application.manager.business; import java.sql.ResultSet; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -38,9 +39,7 @@ import org.flywaydb.core.api.configuration.Configuration; import org.flywaydb.core.api.configuration.FluentConfiguration; import org.flywaydb.core.internal.database.hsqldb.HSQLDBParser; -import org.flywaydb.core.internal.database.mysql.MySQLParser; import org.flywaydb.core.internal.database.postgresql.PostgreSQLParser; -import org.flywaydb.core.internal.database.sqlserver.SQLServerParser; import org.flywaydb.core.internal.parser.Parser; import org.flywaydb.core.internal.parser.ParsingContext; import org.flywaydb.core.internal.resource.StringResource; @@ -54,13 +53,16 @@ import org.springframework.jdbc.support.rowset.SqlRowSet; import org.springframework.jdbc.support.rowset.SqlRowSetMetaData; import org.springframework.stereotype.Component; +import org.springframework.util.ClassUtils; import com.google.common.collect.Streams; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Component public class SqlExecutor extends ServiceAware implements DataProvider, ActionProvider { @@ -161,24 +163,41 @@ public static class SqlStatement { public List getQueries(String sql, DatabaseConnection conn) { Configuration configuration = new FluentConfiguration().dataSource(conn.getJdbcUrl(), conn.getUserName(), conn.getPasswordPlain()); - Parser parser = getParser(conn.getType(), configuration); - SqlScript sqlScript = new ParserSqlScript(parser, new StringResource(sql), null, false); - return Streams.stream(sqlScript.getSqlStatements()) - .map(org.flywaydb.core.internal.sqlscript.SqlStatement::getSql).collect(Collectors.toList()); + try { + Parser parser = getParser(conn.getType(), configuration); + SqlScript sqlScript = new ParserSqlScript(parser, new StringResource(sql), null, false); + return Streams.stream(sqlScript.getSqlStatements()) + .map(org.flywaydb.core.internal.sqlscript.SqlStatement::getSql).collect(Collectors.toList()); + } catch (ReflectiveOperationException e) { + log.error("failed creating parser", e); + } + return new ArrayList<>(); } - protected Parser getParser(DatabaseType type, Configuration configuration) { - ParsingContext parsingContext = new ParsingContext(); + protected Parser getParser(DatabaseType type, Configuration configuration) throws ReflectiveOperationException { switch (type) { case MYSQL: - return new MySQLParser(configuration, parsingContext); + if (configuration.getUrl().contains(":mariadb:")) { + return createParser("mysql.mariadb.MariaDBDatabaseType", configuration); + } else { + return createParser("mysql.MySQLDatabaseType", configuration); + } case MSSQL: - return new SQLServerParser(configuration, parsingContext); + return createParser("sqlserver.SQLServerDatabaseType", configuration); case POSTGRESQL: - return new PostgreSQLParser(configuration, parsingContext); + return new PostgreSQLParser(configuration, new ParsingContext()); default: - return new HSQLDBParser(configuration, parsingContext); + return new HSQLDBParser(configuration, new ParsingContext()); + } + } + + private Parser createParser(String className, Configuration configuration) throws ReflectiveOperationException { + String packagePrefix = "org.flywaydb.database."; + if (!ClassUtils.isPresent(packagePrefix + className, getClass().getClassLoader())) { + packagePrefix = "org.flywaydb.core.internal.database."; } + return ((org.flywaydb.core.internal.database.DatabaseType) Class.forName(packagePrefix + className) + .newInstance()).createParser(configuration, null, new ParsingContext()); } } diff --git a/src/test/java/org/appng/application/manager/business/SqlExecutorTest.java b/src/test/java/org/appng/application/manager/business/SqlExecutorTest.java index 4e63206..9e5687a 100644 --- a/src/test/java/org/appng/application/manager/business/SqlExecutorTest.java +++ b/src/test/java/org/appng/application/manager/business/SqlExecutorTest.java @@ -16,6 +16,10 @@ package org.appng.application.manager.business; import org.appng.api.support.CallableAction; +import org.appng.core.domain.DatabaseConnection.DatabaseType; +import org.flywaydb.core.api.configuration.ClassicConfiguration; +import org.flywaydb.core.internal.parser.Parser; +import org.junit.Assert; import org.junit.Test; import org.springframework.test.context.ContextConfiguration; @@ -34,4 +38,21 @@ public void testExecute() throws Exception { validate(callableAction.getAction()); } + @Test + public void testParser() throws ReflectiveOperationException { + assertType("MySQLParser", "jdbc:mysql://localhost", DatabaseType.MYSQL); + assertType("MariaDBParser", "jdbc:mariadb://localhost", DatabaseType.MYSQL); + assertType("SQLServerParser", "jdbc:sqlserver://localhost", DatabaseType.MSSQL); + assertType("PostgreSQLParser", "jdbc:postgresql://localhost", DatabaseType.POSTGRESQL); + assertType("HSQLDBParser", "jdbc:hsqldb:hsql://localhost", DatabaseType.HSQL); + } + + private void assertType(String className, String url, DatabaseType type) throws ReflectiveOperationException { + ClassicConfiguration cfg = new ClassicConfiguration(); + cfg.setDataSource(url, null, null); + Parser parser = new SqlExecutor().getParser(type, cfg); + Assert.assertNotNull(parser); + Assert.assertEquals(className, parser.getClass().getSimpleName()); + } + }