package org.flywaydb.core.internal.database;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.api.configuration.Configuration;
import org.flywaydb.core.api.logging.Log;
import org.flywaydb.core.api.logging.LogFactory;
import org.flywaydb.core.internal.callback.CallbackExecutor;
import org.flywaydb.core.internal.database.base.Database;
import org.flywaydb.core.internal.database.cockroachdb.CockroachDBDatabase;
import org.flywaydb.core.internal.database.cockroachdb.CockroachDBParser;
import org.flywaydb.core.internal.database.cockroachdb.CockroachDBRetryingStrategy;
import org.flywaydb.core.internal.database.db2.DB2Database;
import org.flywaydb.core.internal.database.db2.DB2Parser;
import org.flywaydb.core.internal.database.derby.DerbyDatabase;
import org.flywaydb.core.internal.database.derby.DerbyParser;
import org.flywaydb.core.internal.database.firebird.FirebirdDatabase;
import org.flywaydb.core.internal.database.firebird.FirebirdParser;
import org.flywaydb.core.internal.database.h2.H2Database;
import org.flywaydb.core.internal.database.h2.H2Parser;
import org.flywaydb.core.internal.database.hsqldb.HSQLDBDatabase;
import org.flywaydb.core.internal.database.hsqldb.HSQLDBParser;
import org.flywaydb.core.internal.database.informix.InformixDatabase;
import org.flywaydb.core.internal.database.informix.InformixParser;
import org.flywaydb.core.internal.database.mysql.MySQLDatabase;
import org.flywaydb.core.internal.database.mysql.MySQLParser;
import org.flywaydb.core.internal.database.oracle.OracleDatabase;
import org.flywaydb.core.internal.database.oracle.OracleParser;
import org.flywaydb.core.internal.database.oracle.OracleSqlScriptExecutor;
import org.flywaydb.core.internal.database.postgresql.PostgreSQLDatabase;
import org.flywaydb.core.internal.database.postgresql.PostgreSQLParser;
import org.flywaydb.core.internal.database.redshift.RedshiftDatabase;
import org.flywaydb.core.internal.database.redshift.RedshiftParser;
import org.flywaydb.core.internal.database.saphana.SAPHANADatabase;
import org.flywaydb.core.internal.database.saphana.SAPHANAParser;
import org.flywaydb.core.internal.database.snowflake.SnowflakeDatabase;
import org.flywaydb.core.internal.database.snowflake.SnowflakeParser;
import org.flywaydb.core.internal.database.sqlite.SQLiteDatabase;
import org.flywaydb.core.internal.database.sqlite.SQLiteParser;
import org.flywaydb.core.internal.database.sqlserver.SQLServerDatabase;
import org.flywaydb.core.internal.database.sqlserver.SQLServerParser;
import org.flywaydb.core.internal.database.sybasease.SybaseASEDatabase;
import org.flywaydb.core.internal.database.sybasease.SybaseASEParser;
import org.flywaydb.core.internal.jdbc.DatabaseType;
import org.flywaydb.core.internal.jdbc.JdbcConnectionFactory;
import org.flywaydb.core.internal.jdbc.JdbcTemplate;
import org.flywaydb.core.internal.parser.ParsingContext;
import org.flywaydb.core.internal.parser.Parser;
import org.flywaydb.core.internal.resource.LoadableResource;
import org.flywaydb.core.internal.resource.ResourceProvider;
import org.flywaydb.core.internal.sqlscript.*;
import java.sql.Connection;
import static org.flywaydb.core.internal.jdbc.DatabaseType.COCKROACHDB;
import static org.flywaydb.core.internal.sqlscript.SqlScriptMetadata.getMetadataResource;
public class DatabaseFactory {
private static final Log LOG = LogFactory.getLog(DatabaseFactory.class);
private DatabaseFactory() {
}
public static Database createDatabase(Configuration configuration, boolean printInfo,
JdbcConnectionFactory jdbcConnectionFactory
) {
OracleDatabase.enableTnsnamesOraSupport();
String databaseProductName = jdbcConnectionFactory.getProductName();
if (printInfo) {
LOG.info("Database: " + jdbcConnectionFactory.getJdbcUrl() + " (" + databaseProductName + ")");
LOG.debug("Driver : " + jdbcConnectionFactory.getDriverInfo());
}
DatabaseType databaseType = jdbcConnectionFactory.getDatabaseType();
Database database = createDatabase(databaseType, configuration, jdbcConnectionFactory
);
String intendedCurrentSchema = configuration.getDefaultSchema();
if (!database.supportsChangingCurrentSchema() && intendedCurrentSchema != null) {
LOG.warn(databaseProductName + " does not support setting the schema for the current session. " +
"Default schema will NOT be changed to " + intendedCurrentSchema + " !");
}
return database;
}
private static Database createDatabase(DatabaseType databaseType, Configuration configuration,
JdbcConnectionFactory jdbcConnectionFactory
) {
switch (databaseType) {
case COCKROACHDB:
return new CockroachDBDatabase(configuration, jdbcConnectionFactory
);
case DB2:
return new DB2Database(configuration, jdbcConnectionFactory
);
case DERBY:
return new DerbyDatabase(configuration, jdbcConnectionFactory
);
case FIREBIRD:
return new FirebirdDatabase(configuration, jdbcConnectionFactory
);
case H2:
return new H2Database(configuration, jdbcConnectionFactory
);
case HSQLDB:
return new HSQLDBDatabase(configuration, jdbcConnectionFactory
);
case INFORMIX:
return new InformixDatabase(configuration, jdbcConnectionFactory
);
case MARIADB:
case MYSQL:
return new MySQLDatabase(configuration, jdbcConnectionFactory
);
case ORACLE:
return new OracleDatabase(configuration, jdbcConnectionFactory
);
case POSTGRESQL:
return new PostgreSQLDatabase(configuration, jdbcConnectionFactory
);
case REDSHIFT:
return new RedshiftDatabase(configuration, jdbcConnectionFactory
);
case SNOWFLAKE:
return new SnowflakeDatabase(configuration, jdbcConnectionFactory
);
case SQLITE:
return new SQLiteDatabase(configuration, jdbcConnectionFactory
);
case SAPHANA:
return new SAPHANADatabase(configuration, jdbcConnectionFactory
);
case SQLSERVER:
return new SQLServerDatabase(configuration, jdbcConnectionFactory
);
case SYBASEASE_JCONNECT:
case SYBASEASE_JTDS:
return new SybaseASEDatabase(configuration, jdbcConnectionFactory
);
default:
throw new FlywayException("Unsupported Database: " + databaseType.name());
}
}
public static SqlScriptFactory createSqlScriptFactory(final JdbcConnectionFactory jdbcConnectionFactory,
final Configuration configuration,
final ParsingContext parsingContext) {
final DatabaseType databaseType = jdbcConnectionFactory.getDatabaseType();
return new SqlScriptFactory() {
@Override
public SqlScript createSqlScript(LoadableResource resource, boolean mixed, ResourceProvider resourceProvider) {
return new ParserSqlScript(createParser(jdbcConnectionFactory, configuration
, parsingContext
), resource, getMetadataResource(resourceProvider, resource), mixed);
}
};
}
private static Parser createParser(JdbcConnectionFactory jdbcConnectionFactory, Configuration configuration
, ParsingContext parsingContext
) {
final DatabaseType databaseType = jdbcConnectionFactory.getDatabaseType();
switch (databaseType) {
case COCKROACHDB:
return new CockroachDBParser(configuration, parsingContext);
case DB2:
return new DB2Parser(configuration, parsingContext);
case DERBY:
return new DerbyParser(configuration, parsingContext);
case FIREBIRD:
return new FirebirdParser(configuration, parsingContext);
case H2:
return new H2Parser(configuration, parsingContext);
case HSQLDB:
return new HSQLDBParser(configuration, parsingContext);
case INFORMIX:
return new InformixParser(configuration, parsingContext);
case MARIADB:
case MYSQL:
return new MySQLParser(configuration, parsingContext);
case ORACLE:
return new OracleParser(configuration
, parsingContext
);
case POSTGRESQL:
return new PostgreSQLParser(configuration, parsingContext);
case REDSHIFT:
return new RedshiftParser(configuration, parsingContext);
case SQLITE:
return new SQLiteParser(configuration, parsingContext);
case SAPHANA:
return new SAPHANAParser(configuration, parsingContext);
case SNOWFLAKE:
return new SnowflakeParser(configuration, parsingContext);
case SQLSERVER:
return new SQLServerParser(configuration, parsingContext);
case SYBASEASE_JCONNECT:
case SYBASEASE_JTDS:
return new SybaseASEParser(configuration, parsingContext);
default:
throw new FlywayException("Unsupported Database: " + databaseType.name());
}
}
public static SqlScriptExecutorFactory createSqlScriptExecutorFactory(
final JdbcConnectionFactory jdbcConnectionFactory
) {
final DatabaseType databaseType = jdbcConnectionFactory.getDatabaseType();
if (DatabaseType.ORACLE == databaseType) {
return new SqlScriptExecutorFactory() {
@Override
public SqlScriptExecutor createSqlScriptExecutor(Connection connection
) {
return new OracleSqlScriptExecutor(new JdbcTemplate(connection, databaseType)
);
}
};
}
return new SqlScriptExecutorFactory() {
@Override
public SqlScriptExecutor createSqlScriptExecutor(Connection connection
) {
return new DefaultSqlScriptExecutor(new JdbcTemplate(connection, databaseType)
);
}
};
}
public static DatabaseExecutionStrategy createExecutionStrategy(Connection connection) {
if (connection == null) {
return new DefaultExecutionStrategy();
}
DatabaseType databaseType = DatabaseType.fromJdbcConnection(connection);
switch (databaseType) {
case COCKROACHDB:
return new CockroachDBRetryingStrategy();
default:
return new DefaultExecutionStrategy();
}
}
}