View Javadoc

1   package liquibase.change.core;
2   
3   import liquibase.change.AbstractChange;
4   import liquibase.change.Change;
5   import liquibase.change.ChangeMetaData;
6   import liquibase.change.ColumnConfig;
7   import liquibase.database.Database;
8   import liquibase.database.core.SQLiteDatabase;
9   import liquibase.database.core.SQLiteDatabase.AlterTableVisitor;
10  import liquibase.database.structure.Index;
11  import liquibase.statement.SqlStatement;
12  import liquibase.statement.core.AddUniqueConstraintStatement;
13  import liquibase.util.StringUtils;
14  
15  import java.util.ArrayList;
16  import java.util.List;
17  
18  /**
19   * Adds a unique constraint to an existing column.
20   */
21  public class AddUniqueConstraintChange extends AbstractChange {
22  
23      private String schemaName;
24      private String tableName;
25      private String columnNames;
26      private String constraintName;
27      private String tablespace;
28  
29      private Boolean deferrable;
30      private Boolean initiallyDeferred;
31      private Boolean disabled;
32  
33      public AddUniqueConstraintChange() {
34          super("addUniqueConstraint", "Add Unique Constraint", ChangeMetaData.PRIORITY_DEFAULT);
35      }
36  
37      public String getSchemaName() {
38          return schemaName;
39      }
40  
41      public void setSchemaName(String schemaName) {
42          this.schemaName = StringUtils.trimToNull(schemaName);
43      }
44  
45      public String getTableName() {
46          return tableName;
47      }
48  
49      public void setTableName(String tableName) {
50          this.tableName = tableName;
51      }
52  
53      public String getColumnNames() {
54          return columnNames;
55      }
56  
57      public void setColumnNames(String columnNames) {
58          this.columnNames = columnNames;
59      }
60  
61      public String getConstraintName() {
62          return constraintName;
63      }
64  
65      public void setConstraintName(String constraintName) {
66          this.constraintName = constraintName;
67      }
68  
69      public String getTablespace() {
70          return tablespace;
71      }
72  
73      public void setTablespace(String tablespace) {
74          this.tablespace = tablespace;
75      }
76  
77      public Boolean getDeferrable() {
78          return deferrable;
79      }
80  
81      public void setDeferrable(Boolean deferrable) {
82          this.deferrable = deferrable;
83      }
84  
85      public Boolean getInitiallyDeferred() {
86          return initiallyDeferred;
87      }
88  
89      public void setInitiallyDeferred(Boolean initiallyDeferred) {
90          this.initiallyDeferred = initiallyDeferred;
91      }
92  
93      public Boolean getDisabled() {
94          return disabled;
95      }
96  
97      public void setDisabled(Boolean disabled) {
98          this.disabled = disabled;
99      }
100 
101     public SqlStatement[] generateStatements(Database database) {
102 
103         // todo if (database instanceof SQLiteDatabase) {
104         // // return special statements for SQLite databases
105         // return generateStatementsForSQLiteDatabase(database);
106         // }
107 
108         boolean deferrable = false;
109         if (getDeferrable() != null) {
110             deferrable = getDeferrable();
111         }
112 
113         boolean initiallyDeferred = false;
114         if (getInitiallyDeferred() != null) {
115             initiallyDeferred = getInitiallyDeferred();
116         }
117         boolean disabled = false;
118         if (getDisabled() != null) {
119             disabled = getDisabled();
120         }
121 
122         AddUniqueConstraintStatement statement = new AddUniqueConstraintStatement(
123                 getSchemaName() == null ? database.getDefaultSchemaName() : getSchemaName(), getTableName(),
124                 getColumnNames(), getConstraintName());
125         statement.setTablespace(getTablespace()).setDeferrable(deferrable).setInitiallyDeferred(initiallyDeferred)
126                 .setDisabled(disabled);
127 
128         return new SqlStatement[] { statement };
129     }
130 
131     private SqlStatement[] generateStatementsForSQLiteDatabase(Database database) {
132 
133         // SQLite does not support this ALTER TABLE operation until now.
134         // For more information see: http://www.sqlite.org/omitted.html.
135         // This is a small work around...
136 
137         List<SqlStatement> statements = new ArrayList<SqlStatement>();
138 
139         // define alter table logic
140         AlterTableVisitor rename_alter_visitor = new AlterTableVisitor() {
141             public ColumnConfig[] getColumnsToAdd() {
142                 return new ColumnConfig[0];
143             }
144 
145             public boolean copyThisColumn(ColumnConfig column) {
146                 return true;
147             }
148 
149             public boolean createThisColumn(ColumnConfig column) {
150                 String[] split_columns = getColumnNames().split("[ ]*,[ ]*");
151                 for (String split_column : split_columns) {
152                     if (column.getName().equals(split_column)) {
153                         column.getConstraints().setUnique(true);
154                     }
155                 }
156                 return true;
157             }
158 
159             public boolean createThisIndex(Index index) {
160                 return true;
161             }
162         };
163 
164         try {
165             // alter table
166             statements.addAll(SQLiteDatabase.getAlterTableStatements(rename_alter_visitor, database, getSchemaName(),
167                     getTableName()));
168         } catch (Exception e) {
169             e.printStackTrace();
170         }
171 
172         return statements.toArray(new SqlStatement[statements.size()]);
173     }
174 
175     public String getConfirmationMessage() {
176         return "Unique constraint added to " + getTableName() + "(" + getColumnNames() + ")";
177     }
178 
179     @Override
180     protected Change[] createInverses() {
181         DropUniqueConstraintChange inverse = new DropUniqueConstraintChange();
182         inverse.setSchemaName(getSchemaName());
183         inverse.setTableName(getTableName());
184         inverse.setConstraintName(getConstraintName());
185 
186         return new Change[] { inverse, };
187     }
188 }