diff --git a/src/main/java/liquibase/ext/hibernate/diff/ChangedColumnChangeGenerator.java b/src/main/java/liquibase/ext/hibernate/diff/ChangedColumnChangeGenerator.java new file mode 100644 index 00000000..dffc5f3c --- /dev/null +++ b/src/main/java/liquibase/ext/hibernate/diff/ChangedColumnChangeGenerator.java @@ -0,0 +1,78 @@ +package liquibase.ext.hibernate.diff; + +import liquibase.change.Change; +import liquibase.database.Database; +import liquibase.diff.Difference; +import liquibase.diff.ObjectDifferences; +import liquibase.diff.output.DiffOutputControl; +import liquibase.ext.hibernate.database.HibernateDatabase; +import liquibase.statement.DatabaseFunction; +import liquibase.structure.DatabaseObject; +import liquibase.structure.core.Column; +import liquibase.structure.core.DataType; + +import java.util.List; + +/** + * Hibernate and database types tend to look different even though they are not. + * The only change that we are handling it size change, and even for this one there are exceptions. + */ +public class ChangedColumnChangeGenerator extends liquibase.diff.output.changelog.core.ChangedColumnChangeGenerator { + + private static final List TYPES_TO_IGNORE_SIZE = List.of("TIMESTAMP"); + + @Override + public int getPriority(Class objectType, Database database) { + if (Column.class.isAssignableFrom(objectType)) { + return PRIORITY_ADDITIONAL; + } + return PRIORITY_NONE; + } + + @Override + protected void handleTypeDifferences(Column column, ObjectDifferences differences, DiffOutputControl control, List changes, Database referenceDatabase, Database comparisonDatabase) { + if (referenceDatabase instanceof HibernateDatabase || comparisonDatabase instanceof HibernateDatabase) { + handleSizeChange(column, differences, control, changes, referenceDatabase, comparisonDatabase); + } else { + super.handleTypeDifferences(column, differences, control, changes, referenceDatabase, comparisonDatabase); + } + } + + private void handleSizeChange(Column column, ObjectDifferences differences, DiffOutputControl control, List changes, Database referenceDatabase, Database comparisonDatabase) { + if (TYPES_TO_IGNORE_SIZE.stream().anyMatch(s -> s.equalsIgnoreCase(column.getType().getTypeName()))) { + return; + } + Difference difference = differences.getDifference("type"); + if (difference != null) { + for (Difference d : differences.getDifferences()) { + if (!(d.getReferenceValue() instanceof DataType)) { + differences.removeDifference(d.getField()); + continue; + } + Integer originalSize = ((DataType) d.getReferenceValue()).getColumnSize(); + Integer newSize = ((DataType) d.getComparedValue()).getColumnSize(); + if (newSize == null || originalSize == null || newSize.equals(originalSize)) { + differences.removeDifference(d.getField()); + } + } + super.handleTypeDifferences(column, differences, control, changes, referenceDatabase, comparisonDatabase); + } + } + + @Override + protected void handleDefaultValueDifferences(Column column, ObjectDifferences differences, DiffOutputControl control, List changes, Database referenceDatabase, Database comparisonDatabase) { + if (referenceDatabase instanceof HibernateDatabase || comparisonDatabase instanceof HibernateDatabase) { + Difference difference = differences.getDifference("defaultValue"); + if (difference != null && difference.getReferenceValue() == null && difference.getComparedValue() instanceof DatabaseFunction) { + //database sometimes adds a function default value, like for timestamp columns + return; + } + difference = differences.getDifference("defaultValue"); + if (difference != null) { + super.handleDefaultValueDifferences(column, differences, control, changes, referenceDatabase, comparisonDatabase); + } + // do nothing, types tend to not match with hibernate + } + super.handleDefaultValueDifferences(column, differences, control, changes, referenceDatabase, comparisonDatabase); + } +} diff --git a/src/main/resources/META-INF/services/liquibase.diff.output.changelog.ChangeGenerator b/src/main/resources/META-INF/services/liquibase.diff.output.changelog.ChangeGenerator index b5d2eb3d..28466d96 100644 --- a/src/main/resources/META-INF/services/liquibase.diff.output.changelog.ChangeGenerator +++ b/src/main/resources/META-INF/services/liquibase.diff.output.changelog.ChangeGenerator @@ -1,3 +1,4 @@ +liquibase.ext.hibernate.diff.ChangedColumnChangeGenerator liquibase.ext.hibernate.diff.ChangedForeignKeyChangeGenerator liquibase.ext.hibernate.diff.ChangedSequenceChangeGenerator liquibase.ext.hibernate.diff.MissingSequenceChangeGenerator