Search in sources :

Example 36 with Column

use of liquibase.structure.core.Column in project liquibase by liquibase.

the class MissingTableChangeGenerator method checkPrimaryKeyOrderMatchesTableOrder.

private boolean checkPrimaryKeyOrderMatchesTableOrder(Table missingTable, List<String> pkColumnList) {
    if (pkColumnList == null) {
        return false;
    }
    int lastTableOrder = -1;
    final List<Column> tableColumnList = missingTable.getColumns();
    for (String pkColumnName : pkColumnList) {
        for (int i = 0; i < tableColumnList.size(); i++) {
            final Column tableColumn = tableColumnList.get(i);
            if (Objects.equals(tableColumn.getName(), pkColumnName)) {
                if (i < lastTableOrder) {
                    return false;
                }
                lastTableOrder = i;
            }
        }
    }
    return true;
}
Also used : Column(liquibase.structure.core.Column) UniqueConstraint(liquibase.structure.core.UniqueConstraint)

Example 37 with Column

use of liquibase.structure.core.Column in project liquibase by liquibase.

the class MissingTableChangeGenerator method fixMissing.

@Override
public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, ChangeGeneratorChain chain) {
    Table missingTable = (Table) missingObject;
    PrimaryKey primaryKey = missingTable.getPrimaryKey();
    List<String> pkColumnList = ((primaryKey != null) ? primaryKey.getColumnNamesAsList() : null);
    Map<Column, UniqueConstraint> singleUniqueConstraints = getSingleColumnUniqueConstraints(missingTable);
    CreateTableChange change = createCreateTableChange();
    change.setTableName(missingTable.getName());
    if (control.getIncludeCatalog()) {
        change.setCatalogName(missingTable.getSchema().getCatalogName());
    }
    if (control.getIncludeSchema()) {
        change.setSchemaName(missingTable.getSchema().getName());
    }
    if (missingTable.getRemarks() != null) {
        change.setRemarks(missingTable.getRemarks());
    }
    if (control.getIncludeTablespace() && (missingTable.getTablespace() != null) && comparisonDatabase.supportsTablespaces()) {
        change.setTablespace(missingTable.getTablespace());
    }
    for (Column column : missingTable.getColumns()) {
        ColumnConfig columnConfig = new ColumnConfig();
        columnConfig.setName(column.getName());
        LiquibaseDataType ldt = DataTypeFactory.getInstance().from(column.getType(), referenceDatabase);
        DatabaseDataType ddt = ldt.toDatabaseDataType(comparisonDatabase);
        String typeString = ddt.toString();
        if (comparisonDatabase instanceof MSSQLDatabase) {
            typeString = comparisonDatabase.unescapeDataTypeString(typeString);
        }
        columnConfig.setType(typeString);
        if (column.isAutoIncrement()) {
            columnConfig.setAutoIncrement(true);
        }
        boolean primaryKeyOrderMatchesTableOrder = checkPrimaryKeyOrderMatchesTableOrder(missingTable, pkColumnList);
        ConstraintsConfig constraintsConfig = null;
        // In MySQL, the primary key must be specified at creation for an autoincrement column
        if ((pkColumnList != null) && primaryKeyOrderMatchesTableOrder && pkColumnList.contains(column.getName())) {
            if ((referenceDatabase instanceof MSSQLDatabase) && (primaryKey.getBackingIndex() != null) && (primaryKey.getBackingIndex().getClustered() != null) && !primaryKey.getBackingIndex().getClustered()) {
            // have to handle PK as a separate statement
            } else if ((referenceDatabase instanceof PostgresDatabase) && (primaryKey.getBackingIndex() != null) && (primaryKey.getBackingIndex().getClustered() != null) && primaryKey.getBackingIndex().getClustered()) {
            // have to handle PK as a separate statement
            } else {
                constraintsConfig = new ConstraintsConfig();
                if (shouldAddPrimarykeyToConstraints(missingObject, control, referenceDatabase, comparisonDatabase)) {
                    constraintsConfig.setPrimaryKey(true);
                    constraintsConfig.setPrimaryKeyTablespace(primaryKey.getTablespace());
                    // MySQL sets some primary key names as PRIMARY which is invalid
                    if ((comparisonDatabase instanceof MySQLDatabase) && "PRIMARY".equals(primaryKey.getName())) {
                        constraintsConfig.setPrimaryKeyName(null);
                    } else {
                        constraintsConfig.setPrimaryKeyName(primaryKey.getName());
                    }
                    control.setAlreadyHandledMissing(primaryKey);
                    control.setAlreadyHandledMissing(primaryKey.getBackingIndex());
                } else {
                    constraintsConfig.setNullable(false);
                }
            }
        }
        if ((column.isNullable() != null) && !column.isNullable()) {
            if (constraintsConfig == null) {
                constraintsConfig = new ConstraintsConfig();
            }
            constraintsConfig.setNullable(false);
            if (!column.getValidateNullable()) {
                constraintsConfig.setValidateNullable(false);
            }
            constraintsConfig.setNotNullConstraintName(column.getAttribute("notNullConstraintName", String.class));
        }
        if (referenceDatabase instanceof MySQLDatabase) {
            UniqueConstraint uniqueConstraint = singleUniqueConstraints.get(column);
            if (uniqueConstraint != null) {
                if (!control.alreadyHandledMissing(uniqueConstraint, referenceDatabase)) {
                    if (constraintsConfig == null) {
                        constraintsConfig = new ConstraintsConfig();
                    }
                    constraintsConfig.setUnique(true);
                    control.setAlreadyHandledMissing(uniqueConstraint);
                    control.setAlreadyHandledMissing(uniqueConstraint.getBackingIndex());
                }
            }
        }
        if (constraintsConfig != null) {
            columnConfig.setConstraints(constraintsConfig);
        }
        setDefaultValue(columnConfig, column, referenceDatabase);
        if (column.getRemarks() != null) {
            columnConfig.setRemarks(column.getRemarks());
        }
        Column.AutoIncrementInformation autoIncrementInfo = column.getAutoIncrementInformation();
        if (autoIncrementInfo != null) {
            BigInteger startWith = autoIncrementInfo.getStartWith();
            BigInteger incrementBy = autoIncrementInfo.getIncrementBy();
            String generationType = autoIncrementInfo.getGenerationType();
            Boolean defaultOnNull = autoIncrementInfo.getDefaultOnNull();
            if ((startWith != null) && !startWith.equals(BigInteger.ONE)) {
                columnConfig.setStartWith(startWith);
            }
            if ((incrementBy != null) && !incrementBy.equals(BigInteger.ONE)) {
                columnConfig.setIncrementBy(incrementBy);
            }
            if (StringUtil.isNotEmpty(generationType)) {
                columnConfig.setGenerationType(generationType);
                if (defaultOnNull != null) {
                    columnConfig.setDefaultOnNull(defaultOnNull);
                }
            }
        }
        // 
        if (column.getComputed() != null) {
            columnConfig.setComputed(column.getComputed());
        }
        change.addColumn(columnConfig);
        control.setAlreadyHandledMissing(column);
    }
    return new Change[] { change };
}
Also used : Table(liquibase.structure.core.Table) ColumnConfig(liquibase.change.ColumnConfig) LiquibaseDataType(liquibase.datatype.LiquibaseDataType) PrimaryKey(liquibase.structure.core.PrimaryKey) UniqueConstraint(liquibase.structure.core.UniqueConstraint) MySQLDatabase(liquibase.database.core.MySQLDatabase) Change(liquibase.change.Change) CreateTableChange(liquibase.change.core.CreateTableChange) PostgresDatabase(liquibase.database.core.PostgresDatabase) DatabaseDataType(liquibase.datatype.DatabaseDataType) Column(liquibase.structure.core.Column) CreateTableChange(liquibase.change.core.CreateTableChange) ConstraintsConfig(liquibase.change.ConstraintsConfig) BigInteger(java.math.BigInteger) MSSQLDatabase(liquibase.database.core.MSSQLDatabase)

Example 38 with Column

use of liquibase.structure.core.Column in project liquibase by liquibase.

the class ChangedIndexChangeGenerator method fixChanged.

@Override
public Change[] fixChanged(DatabaseObject changedObject, ObjectDifferences differences, DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, ChangeGeneratorChain chain) {
    // don't try to recreate indexes that differ in just clustered
    Difference clusteredDiff = differences.getDifference("clustered");
    if (clusteredDiff != null) {
        if ((clusteredDiff.getReferenceValue() == null) || (clusteredDiff.getComparedValue() == null)) {
            differences.removeDifference("clustered");
        }
    }
    for (String field : getIgnoredFields()) {
        differences.removeDifference(field);
    }
    if (!differences.hasDifferences()) {
        return new Change[0];
    }
    Index index = (Index) changedObject;
    if (index.getRelation() != null && index.getRelation() instanceof Table) {
        if ((((Table) index.getRelation()).getPrimaryKey() != null) && DatabaseObjectComparatorFactory.getInstance().isSameObject(((Table) index.getRelation()).getPrimaryKey().getBackingIndex(), changedObject, differences.getSchemaComparisons(), comparisonDatabase)) {
            return ChangeGeneratorFactory.getInstance().fixChanged(((Table) index.getRelation()).getPrimaryKey(), differences, control, referenceDatabase, comparisonDatabase);
        }
        List<UniqueConstraint> uniqueConstraints = ((Table) index.getRelation()).getUniqueConstraints();
        if (uniqueConstraints != null) {
            for (UniqueConstraint constraint : uniqueConstraints) {
                if ((constraint.getBackingIndex() != null) && DatabaseObjectComparatorFactory.getInstance().isSameObject(constraint.getBackingIndex(), changedObject, differences.getSchemaComparisons(), comparisonDatabase)) {
                    return ChangeGeneratorFactory.getInstance().fixChanged(constraint, differences, control, referenceDatabase, comparisonDatabase);
                }
            }
        }
    }
    DropIndexChange dropIndexChange = createDropIndexChange();
    dropIndexChange.setTableName(index.getRelation().getName());
    dropIndexChange.setIndexName(index.getName());
    CreateIndexChange addIndexChange = createCreateIndexChange();
    addIndexChange.setTableName(index.getRelation().getName());
    List<AddColumnConfig> columns = new ArrayList<>();
    for (Column col : index.getColumns()) {
        columns.add(new AddColumnConfig(col));
    }
    addIndexChange.setColumns(columns);
    addIndexChange.setIndexName(index.getName());
    addIndexChange.setUnique(index.isUnique());
    if (control.getIncludeCatalog()) {
        dropIndexChange.setCatalogName(index.getSchema().getCatalogName());
        addIndexChange.setCatalogName(index.getSchema().getCatalogName());
    }
    if (control.getIncludeSchema()) {
        dropIndexChange.setSchemaName(index.getSchema().getName());
        addIndexChange.setSchemaName(index.getSchema().getName());
    }
    Difference columnsDifference = differences.getDifference("columns");
    if (columnsDifference != null) {
        List<Column> referenceColumns = (List<Column>) columnsDifference.getReferenceValue();
        List<Column> comparedColumns = (List<Column>) columnsDifference.getComparedValue();
        StringUtil.StringUtilFormatter<Column> formatter = new StringUtil.StringUtilFormatter<Column>() {

            @Override
            public String toString(Column obj) {
                return obj.toString(false);
            }
        };
        control.setAlreadyHandledChanged(new Index().setRelation(index.getRelation()).setColumns(referenceColumns));
        if (!StringUtil.join(referenceColumns, ",", formatter).equalsIgnoreCase(StringUtil.join(comparedColumns, ",", formatter))) {
            control.setAlreadyHandledChanged(new Index().setRelation(index.getRelation()).setColumns(comparedColumns));
        }
        if ((index.isUnique() != null) && index.isUnique()) {
            control.setAlreadyHandledChanged(new UniqueConstraint().setRelation(index.getRelation()).setColumns(referenceColumns));
            if (!StringUtil.join(referenceColumns, ",", formatter).equalsIgnoreCase(StringUtil.join(comparedColumns, ",", formatter))) {
                control.setAlreadyHandledChanged(new UniqueConstraint().setRelation(index.getRelation()).setColumns(comparedColumns));
            }
        }
    }
    return new Change[] { dropIndexChange, addIndexChange };
}
Also used : DropIndexChange(liquibase.change.core.DropIndexChange) Table(liquibase.structure.core.Table) ArrayList(java.util.ArrayList) UniqueConstraint(liquibase.structure.core.UniqueConstraint) Index(liquibase.structure.core.Index) Difference(liquibase.diff.Difference) DropIndexChange(liquibase.change.core.DropIndexChange) Change(liquibase.change.Change) CreateIndexChange(liquibase.change.core.CreateIndexChange) Column(liquibase.structure.core.Column) AddColumnConfig(liquibase.change.AddColumnConfig) ArrayList(java.util.ArrayList) List(java.util.List) StringUtil(liquibase.util.StringUtil) CreateIndexChange(liquibase.change.core.CreateIndexChange)

Example 39 with Column

use of liquibase.structure.core.Column in project liquibase by liquibase.

the class ColumnComparator method hash.

@Override
public String[] hash(DatabaseObject databaseObject, Database accordingTo, DatabaseObjectComparatorChain chain) {
    Column column = (Column) databaseObject;
    String hash = column.getName();
    if (column.getRelation() != null) {
        hash += ":" + column.getRelation().getName();
    }
    if (BooleanUtil.isTrue(column.getComputed())) {
        hash += ":computed";
    }
    if (BooleanUtil.isTrue(column.getDescending())) {
        hash += ":descending";
    }
    return new String[] { hash.toLowerCase(Locale.US) };
}
Also used : Column(liquibase.structure.core.Column)

Example 40 with Column

use of liquibase.structure.core.Column in project liquibase by liquibase.

the class ColumnComparator method isSameObject.

@Override
public boolean isSameObject(DatabaseObject databaseObject1, DatabaseObject databaseObject2, Database accordingTo, DatabaseObjectComparatorChain chain) {
    if (!((databaseObject1 instanceof Column) && (databaseObject2 instanceof Column))) {
        return false;
    }
    Column thisColumn = (Column) databaseObject1;
    Column otherColumn = (Column) databaseObject2;
    // short circut chain.isSameObject for performance reasons. There can be a lot of columns in a database
    if (!DefaultDatabaseObjectComparator.nameMatches(thisColumn, otherColumn, accordingTo)) {
        return false;
    }
    if (!DatabaseObjectComparatorFactory.getInstance().isSameObject(thisColumn.getRelation(), otherColumn.getRelation(), chain.getSchemaComparisons(), accordingTo)) {
        return false;
    }
    if (BooleanUtil.isTrue(thisColumn.getComputed()) != BooleanUtil.isTrue(otherColumn.getComputed())) {
        return false;
    }
    if (BooleanUtil.isTrue(thisColumn.getDescending()) != BooleanUtil.isTrue(otherColumn.getDescending())) {
        return false;
    }
    return true;
}
Also used : Column(liquibase.structure.core.Column)

Aggregations

Column (liquibase.structure.core.Column)43 Table (liquibase.structure.core.Table)22 Change (liquibase.change.Change)8 SnapshotControl (liquibase.snapshot.SnapshotControl)8 Index (liquibase.structure.core.Index)8 DatabaseSnapshot (liquibase.snapshot.DatabaseSnapshot)7 DatabaseObject (liquibase.structure.DatabaseObject)6 Test (org.junit.Test)6 DatabaseException (liquibase.exception.DatabaseException)5 SqlStatement (liquibase.statement.SqlStatement)5 Schema (liquibase.structure.core.Schema)5 UniqueConstraint (liquibase.structure.core.UniqueConstraint)5 ArrayList (java.util.ArrayList)4 MSSQLDatabase (liquibase.database.core.MSSQLDatabase)4 UnexpectedLiquibaseException (liquibase.exception.UnexpectedLiquibaseException)4 CatalogAndSchema (liquibase.CatalogAndSchema)3 Liquibase (liquibase.Liquibase)3 AbstractIntegrationTest (liquibase.dbtest.AbstractIntegrationTest)3 RawSqlStatement (liquibase.statement.core.RawSqlStatement)3 PrimaryKey (liquibase.structure.core.PrimaryKey)3