package liquibase.sqlgenerator.core; import liquibase.database.Database; import liquibase.database.core.*; import liquibase.exception.DatabaseException; import liquibase.exception.ValidationErrors; import liquibase.sql.Sql; import liquibase.sql.UnparsedSql; import liquibase.sqlgenerator.SqlGeneratorChain; import liquibase.statement.core.DropDefaultValueStatement; import liquibase.structure.core.Column; import liquibase.structure.core.Table; public class DropDefaultValueGenerator extends AbstractSqlGenerator<DropDefaultValueStatement> { @Override public boolean supports(DropDefaultValueStatement statement, Database database) { return !(database instanceof SQLiteDatabase); } @Override public ValidationErrors validate(DropDefaultValueStatement dropDefaultValueStatement, Database database, SqlGeneratorChain sqlGeneratorChain) { ValidationErrors validationErrors = new ValidationErrors(); validationErrors.checkRequiredField("tableName", dropDefaultValueStatement.getTableName()); validationErrors.checkRequiredField("columnName", dropDefaultValueStatement.getColumnName()); if (database instanceof InformixDatabase) { validationErrors.checkRequiredField("columnDataType", dropDefaultValueStatement.getColumnDataType()); } return validationErrors; } @Override public Sql[] generateSql(DropDefaultValueStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { String sql; String escapedTableName = database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName()); if (database instanceof MSSQLDatabase) { boolean sql2005OrLater = true; try { sql2005OrLater = database.getDatabaseMajorVersion() >= 9; } catch (DatabaseException e) { // Assume SQL Server 2005 or later } if (sql2005OrLater) { // SQL Server 2005 or later sql = "DECLARE @sql [nvarchar](MAX)\r\n" + "SELECT @sql = N'ALTER TABLE " + database.escapeStringForDatabase(escapedTableName) + " DROP CONSTRAINT ' + QUOTENAME([df].[name]) " + "FROM [sys].[columns] AS [c] " + "INNER JOIN [sys].[default_constraints] AS [df] " + "ON [df].[object_id] = [c].[default_object_id] " + "WHERE [c].[object_id] = OBJECT_ID(N'" + database.escapeStringForDatabase(escapedTableName) + "') " + "AND [c].[name] = N'" + database.escapeStringForDatabase(statement.getColumnName()) + "'\r\n" + "EXEC sp_executesql @sql"; } else { // SQL Server 2000 sql = "DECLARE @sql [nvarchar](4000)\r\n" + "SELECT @sql = N'ALTER TABLE " + database.escapeStringForDatabase(escapedTableName) + " DROP CONSTRAINT ' + QUOTENAME([df].[name]) " + "FROM [dbo].[syscolumns] AS [c] " + "INNER JOIN [dbo].[sysobjects] AS [df] " + "ON [df].[id] = [c].[cdefault] " + "WHERE [c].[id] = OBJECT_ID(N'" + database.escapeStringForDatabase(escapedTableName) + "') " + "AND [c].[name] = N'" + database.escapeStringForDatabase(statement.getColumnName()) + "'\r\n" + "EXEC sp_executesql @sql"; } } else if (database instanceof MySQLDatabase) { sql = "ALTER TABLE " + escapedTableName + " ALTER " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " DROP DEFAULT"; } else if (database instanceof OracleDatabase) { sql = "ALTER TABLE " + escapedTableName + " MODIFY " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " DEFAULT NULL"; } else if (database instanceof SybaseASADatabase || database instanceof SybaseDatabase) { sql = "ALTER TABLE " + escapedTableName + " REPLACE " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " DEFAULT NULL"; } else if (database instanceof DerbyDatabase) { sql = "ALTER TABLE " + escapedTableName + " ALTER COLUMN " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " WITH DEFAULT NULL"; } else if (database instanceof InformixDatabase) { /* * TODO If dropped from a not null column the not null constraint will be dropped, too. * If the column is "NOT NULL" it has to be added behind the datatype. */ sql = "ALTER TABLE " + escapedTableName + " MODIFY (" + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " " + statement.getColumnDataType() + ")"; } else if (database instanceof DB2Database) { sql = "ALTER TABLE " + escapedTableName + " ALTER COLUMN " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " DROP DEFAULT"; } else { sql = "ALTER TABLE " + escapedTableName + " ALTER COLUMN " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " SET DEFAULT NULL"; } return new Sql[] { new UnparsedSql(sql, getAffectedColumn(statement)) }; } protected Column getAffectedColumn(DropDefaultValueStatement statement) { return new Column().setName(statement.getColumnName()).setRelation(new Table().setName(statement.getTableName()).setSchema(statement.getCatalogName(), statement.getSchemaName())); } }