package liquibase.sqlgenerator.core; import liquibase.database.Database; import liquibase.database.core.*; import liquibase.database.typeconversion.TypeConverter; import liquibase.database.typeconversion.TypeConverterFactory; import liquibase.exception.DatabaseException; import liquibase.exception.ValidationErrors; import liquibase.sql.Sql; import liquibase.sql.UnparsedSql; import liquibase.sqlgenerator.SqlGenerator; import liquibase.sqlgenerator.SqlGeneratorChain; import liquibase.sqlgenerator.SqlGeneratorFactory; import liquibase.statement.core.SetNullableStatement; import liquibase.statement.core.ReorganizeTableStatement; import java.util.ArrayList; import java.util.List; import java.util.Arrays; public class SetNullableGenerator extends AbstractSqlGenerator<SetNullableStatement> { @Override public boolean supports(SetNullableStatement statement, Database database) { return !(database instanceof FirebirdDatabase || database instanceof SQLiteDatabase); } public ValidationErrors validate(SetNullableStatement setNullableStatement, Database database, SqlGeneratorChain sqlGeneratorChain) { ValidationErrors validationErrors = new ValidationErrors(); validationErrors.checkRequiredField("tableName", setNullableStatement.getTableName()); validationErrors.checkRequiredField("columnName", setNullableStatement.getColumnName()); if (database instanceof MSSQLDatabase || database instanceof MySQLDatabase || database instanceof InformixDatabase || database instanceof H2Database) { validationErrors.checkRequiredField("columnDataType", setNullableStatement.getColumnDataType()); } try { if ((database instanceof DB2Database) && (database.getDatabaseMajorVersion() < 9)) { validationErrors.addError("DB2 versions less than 9 do not support modifying null constraints"); } } catch (DatabaseException ignore) { //cannot check } return validationErrors; } public Sql[] generateSql(SetNullableStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { String sql; TypeConverter typeConverter = TypeConverterFactory.getInstance().findTypeConverter(database); String nullableString; if (statement.isNullable()) { nullableString = " NULL"; } else { nullableString = " NOT NULL"; } if (database instanceof OracleDatabase || database instanceof SybaseDatabase || database instanceof SybaseASADatabase) { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " MODIFY " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + nullableString; } else if (database instanceof MSSQLDatabase) { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " ALTER COLUMN " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " " + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString; } else if (database instanceof MySQLDatabase) { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " MODIFY " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " " + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString; } else if (database instanceof DerbyDatabase || database instanceof CacheDatabase) { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " ALTER COLUMN " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + nullableString; } else if (database instanceof HsqlDatabase) { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " ALTER COLUMN " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " SET"+nullableString; } else if (database instanceof H2Database) { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " ALTER COLUMN " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " " + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString; } else if (database instanceof MaxDBDatabase) { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " COLUMN " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + (statement.isNullable() ? " DEFAULT NULL" : " NOT NULL"); } else if (database instanceof InformixDatabase) { // Informix simply omits the null for nullables if (statement.isNullable()) { nullableString = ""; } sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " MODIFY (" + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " " + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString + ")"; } else { sql = "ALTER TABLE " + database.escapeTableName(statement.getSchemaName(), statement.getTableName()) + " ALTER COLUMN " + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + (statement.isNullable() ? " DROP NOT NULL" : " SET NOT NULL"); } List<Sql> returnList = new ArrayList<Sql>(); returnList.add(new UnparsedSql(sql)); if (database instanceof DB2Database) { returnList.addAll(Arrays.asList(SqlGeneratorFactory.getInstance().generateSql(new ReorganizeTableStatement(statement.getSchemaName(), statement.getTableName()), database))); } return returnList.toArray(new Sql[returnList.size()]); } }