1 package liquibase.sqlgenerator.core;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.List;
6
7 import liquibase.database.Database;
8 import liquibase.database.core.CacheDatabase;
9 import liquibase.database.core.DB2Database;
10 import liquibase.database.core.DerbyDatabase;
11 import liquibase.database.core.FirebirdDatabase;
12 import liquibase.database.core.H2Database;
13 import liquibase.database.core.HsqlDatabase;
14 import liquibase.database.core.InformixDatabase;
15 import liquibase.database.core.MSSQLDatabase;
16 import liquibase.database.core.MaxDBDatabase;
17 import liquibase.database.core.MySQLDatabase;
18 import liquibase.database.core.OracleDatabase;
19 import liquibase.database.core.SQLiteDatabase;
20 import liquibase.database.core.SybaseASADatabase;
21 import liquibase.database.core.SybaseDatabase;
22 import liquibase.database.typeconversion.TypeConverter;
23 import liquibase.database.typeconversion.TypeConverterFactory;
24 import liquibase.exception.DatabaseException;
25 import liquibase.exception.ValidationErrors;
26 import liquibase.sql.Sql;
27 import liquibase.sql.UnparsedSql;
28 import liquibase.sqlgenerator.SqlGeneratorChain;
29 import liquibase.sqlgenerator.SqlGeneratorFactory;
30 import liquibase.statement.core.ReorganizeTableStatement;
31 import liquibase.statement.core.SetNullableStatement;
32
33 public class SetNullableGenerator extends AbstractSqlGenerator<SetNullableStatement> {
34
35 @Override
36 public boolean supports(SetNullableStatement statement, Database database) {
37 return !(database instanceof FirebirdDatabase || database instanceof SQLiteDatabase);
38 }
39
40 @Override
41 public ValidationErrors validate(SetNullableStatement setNullableStatement, Database database,
42 SqlGeneratorChain sqlGeneratorChain) {
43 ValidationErrors validationErrors = new ValidationErrors();
44
45 validationErrors.checkRequiredField("tableName", setNullableStatement.getTableName());
46 validationErrors.checkRequiredField("columnName", setNullableStatement.getColumnName());
47
48 if (database instanceof MSSQLDatabase || database instanceof MySQLDatabase
49 || database instanceof InformixDatabase || database instanceof H2Database) {
50 validationErrors.checkRequiredField("columnDataType", setNullableStatement.getColumnDataType());
51 }
52
53 try {
54 if ((database instanceof DB2Database) && (database.getDatabaseMajorVersion() < 9)) {
55 validationErrors.addError("DB2 versions less than 9 do not support modifying null constraints");
56 }
57 } catch (DatabaseException ignore) {
58
59 }
60 return validationErrors;
61 }
62
63 @Override
64 public Sql[] generateSql(SetNullableStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) {
65 String sql;
66
67 TypeConverter typeConverter = TypeConverterFactory.getInstance().findTypeConverter(database);
68
69 String nullableString;
70 if (statement.isNullable()) {
71 nullableString = " NULL";
72 } else {
73 nullableString = " NOT NULL";
74 }
75
76 if (database instanceof OracleDatabase || database instanceof SybaseDatabase
77 || database instanceof SybaseASADatabase) {
78 sql = "ALTER TABLE "
79 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
80 + " MODIFY "
81 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
82 statement.getColumnName()) + nullableString;
83 } else if (database instanceof MSSQLDatabase) {
84 sql = "ALTER TABLE "
85 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
86 + " ALTER COLUMN "
87 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
88 statement.getColumnName()) + " "
89 + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString;
90 } else if (database instanceof MySQLDatabase) {
91 sql = "ALTER TABLE "
92 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
93 + " MODIFY "
94 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
95 statement.getColumnName()) + " "
96 + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString;
97 } else if (database instanceof DerbyDatabase || database instanceof CacheDatabase) {
98 sql = "ALTER TABLE "
99 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
100 + " ALTER COLUMN "
101 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
102 statement.getColumnName()) + nullableString;
103 } else if (database instanceof HsqlDatabase) {
104 sql = "ALTER TABLE "
105 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
106 + " ALTER COLUMN "
107 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
108 statement.getColumnName()) + " SET" + nullableString;
109 } else if (database instanceof H2Database) {
110 sql = "ALTER TABLE "
111 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
112 + " ALTER COLUMN "
113 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
114 statement.getColumnName()) + " "
115 + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString;
116 } else if (database instanceof MaxDBDatabase) {
117 sql = "ALTER TABLE "
118 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
119 + " COLUMN "
120 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
121 statement.getColumnName()) + (statement.isNullable() ? " DEFAULT NULL" : " NOT NULL");
122 } else if (database instanceof InformixDatabase) {
123
124 if (statement.isNullable()) {
125 nullableString = "";
126 }
127 sql = "ALTER TABLE "
128 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
129 + " MODIFY ("
130 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
131 statement.getColumnName()) + " "
132 + typeConverter.getDataType(statement.getColumnDataType(), false) + nullableString + ")";
133 } else {
134 sql = "ALTER TABLE "
135 + database.escapeTableName(statement.getSchemaName(), statement.getTableName())
136 + " ALTER COLUMN "
137 + database.escapeColumnName(statement.getSchemaName(), statement.getTableName(),
138 statement.getColumnName()) + (statement.isNullable() ? " DROP NOT NULL" : " SET NOT NULL");
139 }
140
141 List<Sql> returnList = new ArrayList<Sql>();
142 returnList.add(new UnparsedSql(sql));
143
144 if (database instanceof DB2Database) {
145 returnList.addAll(Arrays.asList(SqlGeneratorFactory.getInstance().generateSql(
146 new ReorganizeTableStatement(statement.getSchemaName(), statement.getTableName()), database)));
147 }
148
149 return returnList.toArray(new Sql[returnList.size()]);
150 }
151 }