View Javadoc

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              // cannot check
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             // Informix simply omits the null for nullables
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 }