/*
* Copyright 2010-2017 Boxfuse GmbH
*
* 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 org.flywaydb.core.internal.dbsupport.enterprisedb;
import org.flywaydb.core.DbCategory;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.FlywayException;
import org.flywaydb.core.api.MigrationInfo;
import org.flywaydb.core.api.MigrationType;
import org.flywaydb.core.api.MigrationVersion;
import org.flywaydb.core.api.resolver.MigrationExecutor;
import org.flywaydb.core.api.resolver.MigrationResolver;
import org.flywaydb.core.api.resolver.ResolvedMigration;
import org.flywaydb.core.internal.util.jdbc.DriverDataSource;
import org.flywaydb.core.internal.util.jdbc.JdbcUtils;
import org.flywaydb.core.migration.MigrationTestCase;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Test to demonstrate the migration functionality using EnterpriseDB.
*/
@SuppressWarnings({"JavaDoc"})
@Category(DbCategory.EnterpriseDB.class)
public class EnterpriseDBMigrationMediumTest extends MigrationTestCase {
@Override
protected DataSource createDataSource(Properties customProperties) throws Exception {
String user = customProperties.getProperty("enterprisedb.user", "flyway");
String password = customProperties.getProperty("enterprisedb.password", "flyway");
String url = customProperties.getProperty("enterprisedb.url", "jdbc:edb://localhost/flyway_db");
return new DriverDataSource(Thread.currentThread().getContextClassLoader(), null, url, user, password, new Properties());
}
@Override
protected String getQuoteLocation() {
return "migration/quote";
}
/**
* Tests migrations containing placeholders.
*/
@Test
public void migrationsWithPlaceholders() throws Exception {
int countUserObjects1 = jdbcTemplate.queryForInt("SELECT count(*) FROM user_objects");
Map<String, String> placeholders = new HashMap<String, String>();
placeholders.put("tableName", "test_user");
flyway.setPlaceholders(placeholders);
flyway.setLocations("migration/dbsupport/enterprisedb/sql/placeholders");
flyway.migrate();
MigrationVersion version = flyway.info().current().getVersion();
assertEquals("1.1", version.toString());
assertEquals("Populate table", flyway.info().current().getDescription());
assertEquals("Mr. T triggered", jdbcTemplate.queryForString("select name from test_user"));
flyway.clean();
int countUserObjects2 = jdbcTemplate.queryForInt("SELECT count(*) FROM user_objects");
assertEquals(countUserObjects1, countUserObjects2);
MigrationInfo[] migrationInfos = flyway.info().applied();
for (MigrationInfo migrationInfo : migrationInfos) {
assertNotNull(migrationInfo.getScript() + " has no checksum", migrationInfo.getChecksum());
}
}
@Test
public void vacuum() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/vacuum");
flyway.setResolvers(new EnterpriseDBMigrationMediumTest.NoTransactionMigrationResolver(new String[][]{
{"2.0", "Vacuum without transaction", "vacuum-notrans", "VACUUM t"}
}));
flyway.migrate();
}
@Test
public void cleanUnknown() throws Exception {
flyway.setSchemas("non-existant");
flyway.clean();
}
private class NoTransactionMigrationResolver implements MigrationResolver {
private final String[][] data;
private NoTransactionMigrationResolver(String[][] data) {
this.data = data;
}
@Override
public Collection<ResolvedMigration> resolveMigrations() {
List<ResolvedMigration> resolvedMigrations = new ArrayList<ResolvedMigration>();
for (String[] migrationData : data) {
resolvedMigrations.add(new EnterpriseDBMigrationMediumTest.NoTransactionResolvedMigration(migrationData));
}
return resolvedMigrations;
}
}
private class NoTransactionResolvedMigration implements ResolvedMigration {
private final String[] data;
private NoTransactionResolvedMigration(String[] data) {
this.data = data;
}
@Override
public MigrationVersion getVersion() {
return MigrationVersion.fromVersion(data[0]);
}
@Override
public String getDescription() {
return data[1];
}
@Override
public String getScript() {
return data[2];
}
@Override
public Integer getChecksum() {
return data[3].hashCode();
}
@Override
public MigrationType getType() {
return MigrationType.CUSTOM;
}
@Override
public String getPhysicalLocation() {
return null;
}
@Override
public MigrationExecutor getExecutor() {
return new EnterpriseDBMigrationMediumTest.NoTransactionMigrationExecutor(data[3]);
}
}
private class NoTransactionMigrationExecutor implements MigrationExecutor {
private final String data;
private NoTransactionMigrationExecutor(String data) {
this.data = data;
}
@Override
public void execute(Connection connection) throws SQLException {
jdbcTemplate.executeStatement(data);
}
@Override
public boolean executeInTransaction() {
return false;
}
}
/**
* Tests clean and migrate for enterprisedb Stored Procedures.
* TODO: Identify why the Oracle tests include a V2__Invalid.sql file
*/
@Test
public void storedProcedure() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/procedure");
flyway.migrate();
assertEquals("Hello", jdbcTemplate.queryForString("SELECT value FROM test_data"));
flyway.clean();
flyway.migrate();
}
/**
* Tests parsing of CREATE PACKAGE.
* TODO: Follow-up on EDB bug to see if the fix allows the complex comments in package body to work
*/
@Test
public void createPackage() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/package");
flyway.migrate();
}
@Test
public void count() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/count");
flyway.migrate();
}
/**
* Tests parsing of object names that contain keywords such as MY_TABLE.
*/
@Test
public void objectNames() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/objectnames");
flyway.migrate();
}
/**
* Tests cleaning up after CREATE MATERIALIZED VIEW.
*/
@Test
public void createMaterializedView() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/materialized");
flyway.migrate();
flyway.clean();
}
/**
* Tests clean and migrate for Views.
*/
@Test
public void view() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/view");
flyway.migrate();
assertEquals(150, jdbcTemplate.queryForInt("SELECT value FROM \"\"\"v\"\"\""));
flyway.clean();
flyway.migrate();
}
/**
* Tests clean and migrate for child tables.
*/
@Test
public void inheritance() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/inheritance");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
/**
* Tests clean and migrate for Domains.
*/
@Test
public void domain() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/domain");
flyway.migrate();
assertEquals("foo", jdbcTemplate.queryForString("SELECT x FROM t"));
flyway.clean();
flyway.migrate();
}
/**
* Tests clean and migrate for Enums.
*/
@Test
public void enumeration() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/enum");
flyway.migrate();
assertEquals("positive", jdbcTemplate.queryForString("SELECT x FROM t"));
flyway.clean();
flyway.migrate();
}
/**
* Tests clean and migrate for Aggregates.
*/
@Test
public void aggregate() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/aggregate");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
/**
* Tests parsing support for $$ string literals.
*/
@Test
public void dollarQuote() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/dollar");
flyway.migrate();
assertEquals(9, jdbcTemplate.queryForInt("select count(*) from dollar"));
}
/**
* Tests parsing support for multiline string literals.
*/
@Test
public void multiLine() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/multiline");
flyway.migrate();
assertEquals(1, jdbcTemplate.queryForInt("select count(*) from address"));
}
/**
* Tests support for COPY FROM STDIN statements generated by pg_dump..
*/
@Test
@Ignore("The EDB JDBC driver doesn't currently support copy operations")
public void copy() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/copy");
flyway.migrate();
assertEquals(6, jdbcTemplate.queryForInt("select count(*) from copy_test"));
}
/**
* Tests support for user defined types.
* TODO: Uncomment the TYPE BODY stanza in the SQL file once the EDB bug is fixed.
*/
@Test
public void type() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/type");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
/**
* Tests support for create function.
*/
@Test
public void function() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/function");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
/**
* Tests support for create trigger. Ensures that a Statement is used instead of a PreparedStatement.
* Also ensures that schema-level triggers are properly cleaned.
*/
@Test
public void trigger() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/trigger");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
/**
* Tests support for clean together with EnterpriseDB Text indexes.
*/
@Test
@Ignore("Beyond the scope of the current iteration")
public void text() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/text");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
/**
* Tests support for clean together with Index Organized Tables.
*/
@Test
public void indexOrganizedTable() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/iot");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
@Test
public void commentEnterpriseDB() throws Exception {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/comment");
assertEquals(3, flyway.migrate());
String statusWithComment = jdbcTemplate.queryForString("select ob.STATUS from user_objects ob where ob.OBJECT_NAME = 'PERSON_WITH_COMMENT' ");
String statusWithoutComment = jdbcTemplate.queryForString("select ob.STATUS from user_objects ob where ob.OBJECT_NAME = 'PERSON_WITHOUT_COMMENT' ");
assertEquals("VALID", statusWithoutComment);
assertEquals("VALID", statusWithComment);
}
/**
* Tests support for clean together with XML Type.
*/
@Test
@Ignore("Beyond the scope of the current iteration")
public void xml() throws FlywayException {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/xml");
flyway.migrate();
flyway.clean();
flyway.migrate();
}
/**
* Tests that the lock on SCHEMA_VERSION is not blocking SQL commands in migrations. This test won't fail if there's
* a too restrictive lock - it would just hang endlessly.
* TODO: Figure out whether the default LOCK MODE is valid
*/
@Test
public void lock() {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/lock");
flyway.migrate();
}
@Test
public void emptySearchPath() {
Flyway flyway1 = new Flyway();
DriverDataSource driverDataSource = (DriverDataSource) dataSource;
flyway1.setDataSource(new DriverDataSource(Thread.currentThread().getContextClassLoader(),
null, driverDataSource.getUrl(), driverDataSource.getUser(), driverDataSource.getPassword(), new Properties()) {
@Override
public Connection getConnection() throws SQLException {
Connection connection = super.getConnection();
Statement statement = null;
try {
statement = connection.createStatement();
statement.execute("SELECT set_config('search_path', '', false)");
} finally {
JdbcUtils.closeStatement(statement);
}
return connection;
}
});
flyway1.setLocations(getBasedir());
flyway1.setSchemas("public");
flyway1.migrate();
}
@Test(expected = FlywayException.class)
public void warning() {
flyway.setLocations("migration/dbsupport/enterprisedb/sql/warning");
flyway.migrate();
// Log should contain "This is a warning"
}
@Ignore("not needed")
@Override
public void upgradeMetadataTableTo40Format() throws Exception {
}
}