Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixed flyway#2028: Unable to clean schema that contains a user-define…
…d function with schemabinding in SQL Server
  • Loading branch information
Axel Fontaine committed Jun 5, 2018
1 parent 83d3c80 commit 3be1c81
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 11 deletions.
Expand Up @@ -15,8 +15,6 @@
*/
package org.flywaydb.core.internal.database;

import org.flywaydb.core.api.logging.Log;
import org.flywaydb.core.api.logging.LogFactory;
import org.flywaydb.core.internal.exception.FlywaySqlException;
import org.flywaydb.core.internal.util.jdbc.JdbcTemplate;
import org.flywaydb.core.internal.util.jdbc.JdbcUtils;
Expand All @@ -30,8 +28,6 @@
* Represents a database schema.
*/
public abstract class Schema<D extends Database> {
private static final Log LOG = LogFactory.getLog(Schema.class);

/**
* The Jdbc Template for communicating with the DB.
*/
Expand Down Expand Up @@ -199,7 +195,7 @@ protected final Type[] allTypes() {
types.add(getType(resultSet.getString("TYPE_NAME")));
}

return types.toArray(new Type[types.size()]);
return types.toArray(new Type[0]);
} catch (SQLException e) {
throw new FlywaySqlException("Unable to retrieve all types in schema " + this, e);
} finally {
Expand Down
Expand Up @@ -15,6 +15,8 @@
*/
package org.flywaydb.core.internal.database.sqlserver;

import org.flywaydb.core.api.logging.Log;
import org.flywaydb.core.api.logging.LogFactory;
import org.flywaydb.core.internal.database.Schema;
import org.flywaydb.core.internal.database.Table;
import org.flywaydb.core.internal.util.jdbc.JdbcTemplate;
Expand All @@ -29,6 +31,8 @@
* SQLServer implementation of Schema.
*/
public class SQLServerSchema extends Schema<SQLServerDatabase> {
private static final Log LOG = LogFactory.getLog(SQLServerSchema.class);

private final String databaseName;

/**
Expand Down Expand Up @@ -204,6 +208,33 @@ protected void doClean() throws SQLException {
jdbcTemplate.execute(statement);
}

// Use a 2-pass approach for cleaning computed columns and functions with SCHEMABINDING due to dependency errors
// Pass 1
for (String statement : cleanComputedColumns(tables)) {
try {
jdbcTemplate.execute(statement);
} catch (SQLException e) {
LOG.debug("Ignoring dependency-related error: " + e.getMessage());
}
}
for (String statement : cleanObjects("FUNCTION",
ObjectType.SCALAR_FUNCTION,
ObjectType.CLR_SCALAR_FUNCTION,
ObjectType.CLR_TABLE_VALUED_FUNCTION,
ObjectType.TABLE_VALUED_FUNCTION,
ObjectType.INLINED_TABLE_FUNCTION)) {
try {
jdbcTemplate.execute(statement);
} catch (SQLException e) {
LOG.debug("Ignoring dependency-related error: " + e.getMessage());
}
}

// Pass 2
for (String statement : cleanComputedColumns(tables)) {
jdbcTemplate.execute(statement);
}

for (String statement : cleanObjects("PROCEDURE",
ObjectType.STORED_PROCEDURE,
ObjectType.CLR_STORED_PROCEDURE)) {
Expand All @@ -214,10 +245,6 @@ protected void doClean() throws SQLException {
jdbcTemplate.execute(statement);
}

for (Table table : allTables()) {
table.drop();
}

for (String statement : cleanObjects("FUNCTION",
ObjectType.SCALAR_FUNCTION,
ObjectType.CLR_SCALAR_FUNCTION,
Expand All @@ -227,6 +254,10 @@ protected void doClean() throws SQLException {
jdbcTemplate.execute(statement);
}

for (Table table : allTables()) {
table.drop();
}

for (String statement : cleanObjects("AGGREGATE", ObjectType.AGGREGATE)) {
jdbcTemplate.execute(statement);
}
Expand Down Expand Up @@ -347,6 +378,26 @@ private List<String> cleanForeignKeys(List<DBObject> tables) throws SQLException
return statements;
}

/**
* Cleans the computed columns in this schema.
*
* @param tables the tables to be cleaned
* @return The drop statements.
* @throws SQLException when the clean statements could not be generated.
*/
private List<String> cleanComputedColumns(List<DBObject> tables) throws SQLException {
List<String> statements = new ArrayList<>();
for (DBObject table : tables) {
String tableName = database.quote(name, table.name);
List<String> columns = jdbcTemplate.queryForStringList(
"SELECT name FROM sys.computed_columns WHERE object_id=OBJECT_ID(N'" + tableName + "')");
for (String column : columns) {
statements.add("ALTER TABLE " + tableName + " DROP COLUMN " + database.quote(column));
}
}
return statements;
}

/**
* Cleans the default constraints in this schema.
*
Expand Down
Expand Up @@ -19,12 +19,13 @@

/**
* Thrown when an attempt was made to migrate an older database version no longer enjoying regular support by its
* vendor and no longer supported by Flyway Open Source and Flyway Pro.
* vendor and no longer supported by Flyway Community Edition and Flyway Pro Edition.
*/
public class FlywayEnterpriseUpgradeRequiredException extends FlywayException {
public FlywayEnterpriseUpgradeRequiredException(String vendor, String database, String version) {
super("Flyway Enterprise or " + database + " upgrade required: " + database + " " + version
+ " is past regular support by " + vendor
+ " and no longer supported by Flyway Open Source or Pro, but still supported by Flyway Enterprise.");
+ " and no longer supported by Flyway Community Edition and Flyway Pro Edition,"
+ " but still supported by Flyway Enterprise Edition.");
}
}

0 comments on commit 3be1c81

Please sign in to comment.