1 | |
package liquibase.sqlgenerator.core; |
2 | |
|
3 | |
import java.util.Iterator; |
4 | |
|
5 | |
import liquibase.database.Database; |
6 | |
import liquibase.database.core.DB2Database; |
7 | |
import liquibase.database.core.InformixDatabase; |
8 | |
import liquibase.database.core.MSSQLDatabase; |
9 | |
import liquibase.database.core.OracleDatabase; |
10 | |
import liquibase.database.core.SQLiteDatabase; |
11 | |
import liquibase.database.core.SybaseASADatabase; |
12 | |
import liquibase.database.core.SybaseDatabase; |
13 | |
import liquibase.exception.ValidationErrors; |
14 | |
import liquibase.logging.LogFactory; |
15 | |
import liquibase.sql.Sql; |
16 | |
import liquibase.sql.UnparsedSql; |
17 | |
import liquibase.sqlgenerator.SqlGeneratorChain; |
18 | |
import liquibase.statement.ForeignKeyConstraint; |
19 | |
import liquibase.statement.UniqueConstraint; |
20 | |
import liquibase.statement.core.CreateTableStatement; |
21 | |
import liquibase.util.StringUtils; |
22 | |
|
23 | 50 | public class CreateTableGenerator extends AbstractSqlGenerator<CreateTableStatement> { |
24 | |
|
25 | |
@Override |
26 | |
public ValidationErrors validate(CreateTableStatement createTableStatement, Database database, |
27 | |
SqlGeneratorChain sqlGeneratorChain) { |
28 | 33 | ValidationErrors validationErrors = new ValidationErrors(); |
29 | 33 | validationErrors.checkRequiredField("tableName", createTableStatement.getTableName()); |
30 | 33 | validationErrors.checkRequiredField("columns", createTableStatement.getColumns()); |
31 | 33 | return validationErrors; |
32 | |
} |
33 | |
|
34 | |
@Override |
35 | |
public Sql[] generateSql(CreateTableStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { |
36 | 2 | StringBuffer buffer = new StringBuffer(); |
37 | 2 | buffer.append("CREATE TABLE ") |
38 | |
.append(database.escapeTableName(statement.getSchemaName(), statement.getTableName())).append(" "); |
39 | 2 | buffer.append("("); |
40 | 2 | Iterator<String> columnIterator = statement.getColumns().iterator(); |
41 | 4 | while (columnIterator.hasNext()) { |
42 | 2 | String column = columnIterator.next(); |
43 | 2 | boolean isAutoIncrement = statement.getAutoIncrementColumns().contains(column); |
44 | |
|
45 | 2 | buffer.append(database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), column)); |
46 | 2 | buffer.append(" ").append(statement.getColumnTypes().get(column)); |
47 | |
|
48 | 2 | if ((database instanceof SQLiteDatabase) && (statement.getPrimaryKeyConstraint() != null) |
49 | |
&& (statement.getPrimaryKeyConstraint().getColumns().size() == 1) |
50 | |
&& (statement.getPrimaryKeyConstraint().getColumns().contains(column)) && isAutoIncrement) { |
51 | 0 | String pkName = StringUtils.trimToNull(statement.getPrimaryKeyConstraint().getConstraintName()); |
52 | 0 | if (pkName == null) { |
53 | 0 | pkName = database.generatePrimaryKeyName(statement.getTableName()); |
54 | |
} |
55 | 0 | if (pkName != null) { |
56 | 0 | buffer.append(" CONSTRAINT "); |
57 | 0 | buffer.append(database.escapeConstraintName(pkName)); |
58 | |
} |
59 | 0 | buffer.append(" PRIMARY KEY AUTOINCREMENT"); |
60 | |
} |
61 | |
|
62 | 2 | if (statement.getDefaultValue(column) != null) { |
63 | 1 | Object defaultValue = statement.getDefaultValue(column); |
64 | 1 | if (database instanceof MSSQLDatabase) { |
65 | 0 | buffer.append(" CONSTRAINT ").append( |
66 | |
((MSSQLDatabase) database).generateDefaultConstraintName(statement.getTableName(), column)); |
67 | |
} |
68 | 1 | buffer.append(" DEFAULT "); |
69 | 1 | buffer.append(statement.getColumnTypes().get(column).convertObjectToString(defaultValue, database)); |
70 | |
} |
71 | |
|
72 | 2 | if (isAutoIncrement && (database.getAutoIncrementClause() != null) |
73 | |
&& (!database.getAutoIncrementClause().equals(""))) { |
74 | 0 | if (database.supportsAutoIncrement()) { |
75 | 0 | buffer.append(" ").append(database.getAutoIncrementClause()).append(" "); |
76 | |
} else { |
77 | 0 | LogFactory.getLogger().warning( |
78 | |
database.getTypeName() + " does not support autoincrement columns as request for " |
79 | |
+ (database.escapeTableName(statement.getSchemaName(), statement.getTableName()))); |
80 | |
} |
81 | |
} |
82 | |
|
83 | 2 | if (statement.getNotNullColumns().contains(column)) { |
84 | 0 | buffer.append(" NOT NULL"); |
85 | |
} else { |
86 | 2 | if (database instanceof SybaseDatabase || database instanceof SybaseASADatabase) { |
87 | 0 | buffer.append(" NULL"); |
88 | |
} |
89 | |
} |
90 | |
|
91 | 2 | if ((database instanceof InformixDatabase) && (statement.getPrimaryKeyConstraint() != null) |
92 | |
&& (statement.getPrimaryKeyConstraint().getColumns().size() == 1) |
93 | |
&& (statement.getPrimaryKeyConstraint().getColumns().contains(column))) { |
94 | 0 | buffer.append(" PRIMARY KEY"); |
95 | |
} |
96 | |
|
97 | 2 | if (columnIterator.hasNext()) { |
98 | 0 | buffer.append(", "); |
99 | |
} |
100 | 2 | } |
101 | |
|
102 | 2 | buffer.append(","); |
103 | |
|
104 | |
|
105 | 2 | if (!((database instanceof SQLiteDatabase) && (statement.getPrimaryKeyConstraint() != null) |
106 | |
&& (statement.getPrimaryKeyConstraint().getColumns().size() == 1) && statement |
107 | |
.getAutoIncrementColumns().contains(statement.getPrimaryKeyConstraint().getColumns().get(0))) |
108 | |
&& |
109 | |
|
110 | |
!((database instanceof InformixDatabase) && (statement.getPrimaryKeyConstraint() != null) && (statement |
111 | |
.getPrimaryKeyConstraint().getColumns().size() == 1))) { |
112 | |
|
113 | |
|
114 | |
|
115 | |
|
116 | 2 | if (statement.getPrimaryKeyConstraint() != null |
117 | |
&& statement.getPrimaryKeyConstraint().getColumns().size() > 0) { |
118 | 0 | if (!(database instanceof InformixDatabase)) { |
119 | 0 | String pkName = StringUtils.trimToNull(statement.getPrimaryKeyConstraint().getConstraintName()); |
120 | 0 | if (pkName == null) { |
121 | |
|
122 | |
|
123 | |
|
124 | 0 | pkName = database.generatePrimaryKeyName(statement.getTableName()); |
125 | |
} |
126 | 0 | if (pkName != null) { |
127 | 0 | buffer.append(" CONSTRAINT "); |
128 | 0 | buffer.append(database.escapeConstraintName(pkName)); |
129 | |
} |
130 | |
} |
131 | 0 | buffer.append(" PRIMARY KEY ("); |
132 | 0 | buffer.append(database.escapeColumnNameList(StringUtils.join(statement.getPrimaryKeyConstraint() |
133 | |
.getColumns(), ", "))); |
134 | 0 | buffer.append(")"); |
135 | |
|
136 | 0 | if (database instanceof OracleDatabase && statement.getPrimaryKeyConstraint().getTablespace() != null) { |
137 | 0 | buffer.append(" USING INDEX TABLESPACE "); |
138 | 0 | buffer.append(statement.getPrimaryKeyConstraint().getTablespace()); |
139 | |
} |
140 | 0 | buffer.append(","); |
141 | |
} |
142 | |
} |
143 | |
|
144 | 2 | for (ForeignKeyConstraint fkConstraint : statement.getForeignKeyConstraints()) { |
145 | 0 | if (!(database instanceof InformixDatabase)) { |
146 | 0 | buffer.append(" CONSTRAINT "); |
147 | 0 | buffer.append(database.escapeConstraintName(fkConstraint.getForeignKeyName())); |
148 | |
} |
149 | 0 | String referencesString = fkConstraint.getReferences(); |
150 | 0 | if (!referencesString.contains(".") && database.getDefaultSchemaName() != null) { |
151 | 0 | referencesString = database.getDefaultSchemaName() + "." + referencesString; |
152 | |
} |
153 | 0 | buffer.append(" FOREIGN KEY (") |
154 | |
.append(database.escapeColumnName(statement.getSchemaName(), statement.getTableName(), |
155 | |
fkConstraint.getColumn())).append(") REFERENCES ").append(referencesString); |
156 | |
|
157 | 0 | if (fkConstraint.isDeleteCascade()) { |
158 | 0 | buffer.append(" ON DELETE CASCADE"); |
159 | |
} |
160 | |
|
161 | 0 | if ((database instanceof InformixDatabase)) { |
162 | 0 | buffer.append(" CONSTRAINT "); |
163 | 0 | buffer.append(database.escapeConstraintName(fkConstraint.getForeignKeyName())); |
164 | |
} |
165 | |
|
166 | 0 | if (fkConstraint.isInitiallyDeferred()) { |
167 | 0 | buffer.append(" INITIALLY DEFERRED"); |
168 | |
} |
169 | 0 | if (fkConstraint.isDeferrable()) { |
170 | 0 | buffer.append(" DEFERRABLE"); |
171 | |
} |
172 | 0 | buffer.append(","); |
173 | 0 | } |
174 | |
|
175 | 2 | for (UniqueConstraint uniqueConstraint : statement.getUniqueConstraints()) { |
176 | 0 | if (uniqueConstraint.getConstraintName() != null && !constraintNameAfterUnique(database)) { |
177 | 0 | buffer.append(" CONSTRAINT "); |
178 | 0 | buffer.append(database.escapeConstraintName(uniqueConstraint.getConstraintName())); |
179 | |
} |
180 | 0 | buffer.append(" UNIQUE ("); |
181 | 0 | buffer.append(database.escapeColumnNameList(StringUtils.join(uniqueConstraint.getColumns(), ", "))); |
182 | 0 | buffer.append(")"); |
183 | 0 | if (uniqueConstraint.getConstraintName() != null && constraintNameAfterUnique(database)) { |
184 | 0 | buffer.append(" CONSTRAINT "); |
185 | 0 | buffer.append(database.escapeConstraintName(uniqueConstraint.getConstraintName())); |
186 | |
} |
187 | 0 | buffer.append(","); |
188 | |
} |
189 | |
|
190 | |
|
191 | |
|
192 | |
|
193 | |
|
194 | |
|
195 | 2 | String sql = buffer.toString().replaceFirst(",\\s*$", "") + ")"; |
196 | |
|
197 | |
|
198 | |
|
199 | |
|
200 | |
|
201 | |
|
202 | |
|
203 | |
|
204 | |
|
205 | |
|
206 | |
|
207 | 2 | if (statement.getTablespace() != null && database.supportsTablespaces()) { |
208 | 0 | if (database instanceof MSSQLDatabase || database instanceof SybaseASADatabase) { |
209 | 0 | sql += " ON " + statement.getTablespace(); |
210 | 0 | } else if (database instanceof DB2Database || database instanceof InformixDatabase) { |
211 | 0 | sql += " IN " + statement.getTablespace(); |
212 | |
} else { |
213 | 0 | sql += " TABLESPACE " + statement.getTablespace(); |
214 | |
} |
215 | |
} |
216 | |
|
217 | 2 | return new Sql[] { new UnparsedSql(sql) }; |
218 | |
} |
219 | |
|
220 | |
private boolean constraintNameAfterUnique(Database database) { |
221 | 0 | return database instanceof InformixDatabase; |
222 | |
} |
223 | |
|
224 | |
} |