package liquibase.sqlgenerator.core; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import liquibase.database.Database; import liquibase.database.core.InformixDatabase; import liquibase.exception.ValidationErrors; import liquibase.logging.LogFactory; import liquibase.sql.Sql; import liquibase.sql.UnparsedSql; import liquibase.sqlgenerator.SqlGeneratorChain; import liquibase.sqlgenerator.core.AbstractSqlGenerator; import liquibase.statement.AutoIncrementConstraint; import liquibase.statement.ForeignKeyConstraint; import liquibase.statement.UniqueConstraint; import liquibase.statement.core.CreateTableStatement; import liquibase.structure.core.Schema; import liquibase.structure.core.Table; import liquibase.util.StringUtils; /** * An Informix-specific create table statement generator. * * @author islavov */ public class CreateTableGeneratorInformix extends CreateTableGenerator { @Override public boolean supports(CreateTableStatement statement, Database database) { return database instanceof InformixDatabase; } @Override public int getPriority() { return PRIORITY_DATABASE + 1; } @Override public Sql[] generateSql(CreateTableStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { StringBuilder buffer = new StringBuilder(); buffer.append("CREATE TABLE ").append(database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName())).append(" "); buffer.append("("); boolean isSinglePrimaryKeyColumn = statement.getPrimaryKeyConstraint() != null && statement.getPrimaryKeyConstraint().getColumns().size() == 1; boolean isPrimaryKeyAutoIncrement = false; Iterator<String> columnIterator = statement.getColumns().iterator(); List<String> primaryKeyColumns = new LinkedList<String>(); while (columnIterator.hasNext()) { String column = columnIterator.next(); buffer.append(database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), column)); buffer.append(" ").append(statement.getColumnTypes().get(column).toDatabaseDataType(database).toSql()); AutoIncrementConstraint autoIncrementConstraint = null; for (AutoIncrementConstraint currentAutoIncrementConstraint : statement.getAutoIncrementConstraints()) { if (column.equals(currentAutoIncrementConstraint.getColumnName())) { autoIncrementConstraint = currentAutoIncrementConstraint; break; } } boolean isAutoIncrementColumn = autoIncrementConstraint != null; boolean isPrimaryKeyColumn = statement.getPrimaryKeyConstraint() != null && statement.getPrimaryKeyConstraint().getColumns().contains(column); isPrimaryKeyAutoIncrement = isPrimaryKeyAutoIncrement || isPrimaryKeyColumn && isAutoIncrementColumn; if (isPrimaryKeyColumn) { primaryKeyColumns.add(column); } if (statement.getDefaultValue(column) != null) { Object defaultValue = statement.getDefaultValue(column); buffer.append(" DEFAULT "); buffer.append(statement.getColumnTypes().get(column).objectToSql(defaultValue, database)); } if (isAutoIncrementColumn) { // TODO: check if database supports auto increment on non primary key column if (database.supportsAutoIncrement()) { String autoIncrementClause = database.getAutoIncrementClause(autoIncrementConstraint.getStartWith(), autoIncrementConstraint.getIncrementBy()); if (autoIncrementClause.length() > 0) { buffer.append(" ").append(autoIncrementClause); } } else { LogFactory.getLogger().warning(database.getShortName()+" does not support autoincrement columns as requested for "+(database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName()))); } } if (statement.getNotNullColumns().contains(column)) { buffer.append(" NOT NULL"); } if (columnIterator.hasNext()) { buffer.append(", "); } } buffer.append(","); // TODO informixdb // Fix according to: https://liquibase.jira.com/browse/CORE-1775 if (isSinglePrimaryKeyColumn && isPrimaryKeyAutoIncrement) { if (statement.getPrimaryKeyConstraint() != null && statement.getPrimaryKeyConstraint().getColumns().size() > 0) { buffer.append(" PRIMARY KEY ("); buffer.append(StringUtils.join(primaryKeyColumns, ", ")); buffer.append(")"); // Setting up table space for PK's index if it exist buffer.append(","); } } for (ForeignKeyConstraint fkConstraint : statement.getForeignKeyConstraints()) { String referencesString = fkConstraint.getReferences(); if (!referencesString.contains(".") && database.getDefaultSchemaName() != null) { referencesString = database.getDefaultSchemaName()+"."+referencesString; } buffer.append(" FOREIGN KEY (") .append(database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), fkConstraint.getColumn())) .append(") REFERENCES ") .append(referencesString); if (fkConstraint.isDeleteCascade()) { buffer.append(" ON DELETE CASCADE"); } buffer.append(" CONSTRAINT "); buffer.append(database.escapeConstraintName(fkConstraint.getForeignKeyName())); if (fkConstraint.isInitiallyDeferred()) { buffer.append(" INITIALLY DEFERRED"); } if (fkConstraint.isDeferrable()) { buffer.append(" DEFERRABLE"); } buffer.append(","); } for (UniqueConstraint uniqueConstraint : statement.getUniqueConstraints()) { if (uniqueConstraint.getConstraintName() != null && !constraintNameAfterUnique(database)) { buffer.append(" CONSTRAINT "); buffer.append(database.escapeConstraintName(uniqueConstraint.getConstraintName())); } buffer.append(" UNIQUE ("); buffer.append(database.escapeColumnNameList(StringUtils.join(uniqueConstraint.getColumns(), ", "))); buffer.append(")"); if (uniqueConstraint.getConstraintName() != null && constraintNameAfterUnique(database)) { buffer.append(" CONSTRAINT "); buffer.append(database.escapeConstraintName(uniqueConstraint.getConstraintName())); } buffer.append(","); } String sql = buffer.toString().replaceFirst(",\\s*$", "") + ")"; if (statement.getTablespace() != null && database.supportsTablespaces()) { sql += " IN " + statement.getTablespace(); } return new Sql[] { new UnparsedSql(sql, new Table().setName(statement.getTableName()).setSchema(new Schema(statement.getCatalogName(), statement.getSchemaName()))) }; } private boolean constraintNameAfterUnique(Database database) { return true; } }