This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit c551d5bd43c60241d4ff2fe94fd8af88e6b9c6ac
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Tue Mar 10 21:03:52 2026 -0500

    hibernate 7 ChangedColumnChangeGenerator
---
 .../diff/ChangedColumnChangeGenerator.java         | 133 +++++++++++----------
 .../diff/ChangedColumnChangeGeneratorSpec.groovy   | 127 ++++++++++++++++++++
 2 files changed, 198 insertions(+), 62 deletions(-)

diff --git 
a/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/diff/ChangedColumnChangeGenerator.java
 
b/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/diff/ChangedColumnChangeGenerator.java
index 7508e0edd1..17d5f6f65b 100644
--- 
a/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/diff/ChangedColumnChangeGenerator.java
+++ 
b/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/diff/ChangedColumnChangeGenerator.java
@@ -1,6 +1,27 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
 package liquibase.ext.hibernate.diff;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
 
 import liquibase.change.Change;
 import liquibase.database.Database;
@@ -23,79 +44,67 @@ public class ChangedColumnChangeGenerator extends 
liquibase.diff.output.changelo
 
     @Override
     public int getPriority(Class<? extends DatabaseObject> objectType, 
Database database) {
-        if (Column.class.isAssignableFrom(objectType)) {
-            return PRIORITY_ADDITIONAL;
-        }
-        return PRIORITY_NONE;
+        return Column.class.isAssignableFrom(objectType) ? PRIORITY_ADDITIONAL 
: PRIORITY_NONE;
     }
 
     @Override
-    protected void handleTypeDifferences(
-            Column column,
-            ObjectDifferences differences,
-            DiffOutputControl control,
-            List<Change> changes,
-            Database referenceDatabase,
-            Database comparisonDatabase) {
-        if (referenceDatabase instanceof HibernateDatabase || 
comparisonDatabase instanceof HibernateDatabase) {
-            handleSizeChange(column, differences, control, changes, 
referenceDatabase, comparisonDatabase);
+    protected void handleTypeDifferences(Column column, ObjectDifferences 
differences, DiffOutputControl control, List<Change> changes, Database 
referenceDatabase, Database comparisonDatabase) {
+        if (isHibernateRelated(referenceDatabase, comparisonDatabase)) {
+            handleHibernateTypeDifferences(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<Change> 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);
-        }
+    private void handleHibernateTypeDifferences(Column column, 
ObjectDifferences differences, DiffOutputControl control, List<Change> changes, 
Database refDb, Database compDb) {
+        if (shouldIgnoreSize(column)) return;
+
+        Optional.ofNullable(differences.getDifference("type")).ifPresent(diff 
-> {
+            filterIrrelevantDifferences(differences);
+            super.handleTypeDifferences(column, differences, control, changes, 
refDb, compDb);
+        });
+    }
+
+    private void filterIrrelevantDifferences(ObjectDifferences differences) {
+        new ArrayList<>(differences.getDifferences()).stream()
+                .filter(Predicate.not(this::isMeaningfulDifference))
+                .forEach(diff -> 
differences.removeDifference(diff.getField()));
+    }
+
+    private boolean isMeaningfulDifference(Difference diff) {
+        return diff.getReferenceValue() instanceof DataType refType && 
+               diff.getComparedValue() instanceof DataType compType &&
+               !isSizeEqualOrNull(refType.getColumnSize(), 
compType.getColumnSize());
     }
 
     @Override
-    protected void handleDefaultValueDifferences(
-            Column column,
-            ObjectDifferences differences,
-            DiffOutputControl control,
-            List<Change> 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
+    protected void handleDefaultValueDifferences(Column column, 
ObjectDifferences differences, DiffOutputControl control, List<Change> changes, 
Database referenceDatabase, Database comparisonDatabase) {
+        if (!isHibernateRelated(referenceDatabase, comparisonDatabase)) {
+            super.handleDefaultValueDifferences(column, differences, control, 
changes, referenceDatabase, comparisonDatabase);
+            return;
         }
-        super.handleDefaultValueDifferences(
-                column, differences, control, changes, referenceDatabase, 
comparisonDatabase);
+
+        if (isFunctionDefaultAddingToNull(differences)) return;
+
+        Optional.ofNullable(differences.getDifference("defaultValue"))
+                .ifPresent(d -> super.handleDefaultValueDifferences(column, 
differences, control, changes, referenceDatabase, comparisonDatabase));
+    }
+
+    private boolean shouldIgnoreSize(Column column) {
+        return TYPES_TO_IGNORE_SIZE.stream().anyMatch(type -> 
type.equalsIgnoreCase(column.getType().getTypeName()));
+    }
+
+    private boolean isSizeEqualOrNull(Integer s1, Integer s2) {
+        return s1 == null || s2 == null || s1.equals(s2);
+    }
+
+    private boolean isFunctionDefaultAddingToNull(ObjectDifferences 
differences) {
+        return Optional.ofNullable(differences.getDifference("defaultValue"))
+                .filter(d -> d.getReferenceValue() == null && 
d.getComparedValue() instanceof DatabaseFunction)
+                .isPresent();
+    }
+
+    private boolean isHibernateRelated(Database d1, Database d2) {
+        return d1 instanceof HibernateDatabase || d2 instanceof 
HibernateDatabase;
     }
 }
diff --git 
a/grails-data-hibernate7/dbmigration/src/test/groovy/liquibase/ext/hibernate/diff/ChangedColumnChangeGeneratorSpec.groovy
 
b/grails-data-hibernate7/dbmigration/src/test/groovy/liquibase/ext/hibernate/diff/ChangedColumnChangeGeneratorSpec.groovy
new file mode 100644
index 0000000000..753e1d3d69
--- /dev/null
+++ 
b/grails-data-hibernate7/dbmigration/src/test/groovy/liquibase/ext/hibernate/diff/ChangedColumnChangeGeneratorSpec.groovy
@@ -0,0 +1,127 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+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.core.Column
+import liquibase.structure.core.DataType
+import liquibase.structure.core.Table
+import spock.lang.Specification
+
+class ChangedColumnChangeGeneratorSpec extends Specification {
+
+    ChangedColumnChangeGenerator generator = new ChangedColumnChangeGenerator()
+
+    def "getPriority returns correct priority for Column and others"() {
+        expect:
+        generator.getPriority(Column, Mock(Database)) == 50 // 
PRIORITY_ADDITIONAL
+        generator.getPriority(DataType, Mock(Database)) == -1 // PRIORITY_NONE
+    }
+
+    def "handleTypeDifferences ignores size for TIMESTAMP and TIME for 
HibernateDatabase"() {
+        given:
+        Column column = new Column()
+        column.setType(new DataType(typeName))
+        ObjectDifferences differences = Mock()
+        DiffOutputControl control = Mock()
+        List<Change> changes = []
+        HibernateDatabase hibernateDatabase = Mock()
+
+        when:
+        generator.handleTypeDifferences(column, differences, control, changes, 
hibernateDatabase, hibernateDatabase)
+
+        then:
+        0 * differences.getDifference("type")
+
+        where:
+        typeName << ["TIMESTAMP", "TIME", "timestamp", "time"]
+    }
+
+    def "handleTypeDifferences handles size changes for other types"() {
+        given:
+        Column column = new Column()
+        column.setName("myCol")
+        column.setRelation(new Table(name: "myTable"))
+        column.setType(new DataType("VARCHAR"))
+        ObjectDifferences differences = Mock()
+        DiffOutputControl control = Mock()
+        List<Change> changes = []
+        HibernateDatabase hibernateDatabase = Mock()
+        
+        Difference diff = new Difference("type", new DataType("VARCHAR(10)"), 
new DataType("VARCHAR(20)"))
+        diff.referenceValue.setColumnSize(10)
+        diff.comparedValue.setColumnSize(20)
+
+        when:
+        generator.handleTypeDifferences(column, differences, control, changes, 
hibernateDatabase, hibernateDatabase)
+
+        then:
+        _ * differences.getDifference("type") >> diff
+        1 * differences.getDifferences() >> [diff]
+        0 * differences.removeDifference("type")
+    }
+
+    def "handleTypeDifferences removes difference if size is same"() {
+        given:
+        Column column = new Column()
+        column.setName("myCol")
+        column.setRelation(new Table(name: "myTable"))
+        column.setType(new DataType("VARCHAR"))
+        ObjectDifferences differences = Mock()
+        DiffOutputControl control = Mock()
+        List<Change> changes = []
+        HibernateDatabase hibernateDatabase = Mock()
+        
+        Difference diff = new Difference("type", new DataType("VARCHAR(10)"), 
new DataType("VARCHAR(10)"))
+        diff.referenceValue.setColumnSize(10)
+        diff.comparedValue.setColumnSize(10)
+
+        when:
+        generator.handleTypeDifferences(column, differences, control, changes, 
hibernateDatabase, hibernateDatabase)
+
+        then:
+        _ * differences.getDifference("type") >> diff
+        1 * differences.getDifferences() >> [diff]
+        1 * differences.removeDifference("type")
+    }
+
+    def "handleDefaultValueDifferences ignores null to DatabaseFunction 
changes for HibernateDatabase"() {
+        given:
+        Column column = new Column()
+        ObjectDifferences differences = Mock()
+        DiffOutputControl control = Mock()
+        List<Change> changes = []
+        HibernateDatabase hibernateDatabase = Mock()
+        
+        Difference diff = new Difference("defaultValue", null, new 
DatabaseFunction("now()"))
+
+        when:
+        generator.handleDefaultValueDifferences(column, differences, control, 
changes, hibernateDatabase, hibernateDatabase)
+
+        then:
+        1 * differences.getDifference("defaultValue") >> diff
+        0 * differences.getDifferences()
+    }
+}

Reply via email to