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 4b7a1796415dfecec49c2f326e7694d7b3904f26
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Tue Mar 3 08:33:01 2026 -0600

    test OrderByClauseBuilder
---
 .../secondpass/CollectionSecondPassBinder.java     |   4 +-
 .../domainbinding/OrderByClauseBuilderSpec.groovy  | 230 ++++++++++-----------
 2 files changed, 113 insertions(+), 121 deletions(-)

diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java
index 9b54553ca5..6b705fa4d8 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java
@@ -186,8 +186,8 @@ public class CollectionSecondPassBinder {
       bindManyToManyElement(manyToMany, collection);
     } else if (property.isBidirectionalOneToManyMap() && 
property.isBidirectional()) {
       bindBidirectionalMapElement(property, collection);
-    } else if (property.isUnidirectionalOneToMany()) {
-      unidirectionalOneToManyBinder.bind((HibernateOneToManyProperty) 
property, collection);
+    } else if (property instanceof HibernateOneToManyProperty 
oneToManyProperty && oneToManyProperty.isUnidirectionalOneToMany()) {
+      unidirectionalOneToManyBinder.bind(oneToManyProperty, collection);
     } else if (property.supportsJoinColumnMapping()) {
       collectionWithJoinTableBinder.bindCollectionWithJoinTable(property, 
mappings, collection);
     }
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/OrderByClauseBuilderSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/OrderByClauseBuilderSpec.groovy
index 603681fe1c..6b27f7746b 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/OrderByClauseBuilderSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/OrderByClauseBuilderSpec.groovy
@@ -1,10 +1,17 @@
 package org.grails.orm.hibernate.cfg.domainbinding
 
-import grails.gorm.annotation.Entity
 import grails.gorm.specs.HibernateGormDatastoreSpec
 import org.grails.datastore.mapping.model.DatastoreConfigurationException
-import org.hibernate.mapping.PersistentClass
+import org.hibernate.mapping.BasicValue
+import org.hibernate.mapping.Column
+import org.hibernate.mapping.Component
+import org.hibernate.mapping.JoinedSubclass
+import org.hibernate.mapping.Property
+import org.hibernate.mapping.RootClass
+import org.hibernate.mapping.SingleTableSubclass
+import org.hibernate.mapping.Table
 import spock.lang.Subject
+import spock.lang.Unroll
 
 import org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder
 
@@ -13,159 +20,144 @@ class OrderByClauseBuilderSpec extends 
HibernateGormDatastoreSpec {
     @Subject
     OrderByClauseBuilder builder = new OrderByClauseBuilder()
 
-    void setupSpec() {
-        manager.addAllDomainClasses([OrderTest, SubOrderTest, 
OrderWithComponent])
+    private RootClass entityClass
+    private RootClass componentEntityClass
+
+    def setup() {
+        def ctx = getGrailsDomainBinder().getMetadataBuildingContext()
+        def table = new Table("test", "order_entity")
+
+        entityClass = new RootClass(ctx)
+        entityClass.setEntityName("OrderEntity")
+        entityClass.setTable(table)
+        entityClass.setIdentifier(basicValue(ctx, table, "id"))
+        entityClass.addProperty(simpleProperty(ctx, table, "name",  "name"))
+        entityClass.addProperty(simpleProperty(ctx, table, "age",   "age"))
+        entityClass.addProperty(simpleProperty(ctx, table, "other", 
"other_column"))
+
+        def compTable = new Table("test", "comp_entity")
+        componentEntityClass = new RootClass(ctx)
+        componentEntityClass.setEntityName("CompEntity")
+        componentEntityClass.setTable(compTable)
+        componentEntityClass.setIdentifier(basicValue(ctx, compTable, "id"))
+
+        def comp = new Component(ctx, compTable, componentEntityClass)
+        comp.addProperty(simpleProperty(ctx, compTable, "c1", "comp_c1"))
+        comp.addProperty(simpleProperty(ctx, compTable, "c2", "comp_c2"))
+        def compProp = new Property()
+        compProp.setName("comp")
+        compProp.setValue(comp)
+        componentEntityClass.addProperty(compProp)
     }
 
-    void "test buildOrderByClause with empty string (default to id)"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
-        when:
-        String result = builder.buildOrderByClause("", pc, "role", "asc")
-
-        then:
-        result == "id asc"
+    void "null hqlOrderBy returns null"() {
+        expect:
+        builder.buildOrderByClause(null, entityClass, "role", "asc") == null
     }
 
-    void "test buildOrderByClause with single property"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
-        when:
-        String result = builder.buildOrderByClause("name", pc, "role", "asc")
-
-        then:
-        result == "name asc"
+    void "empty hqlOrderBy returns identifier column with asc"() {
+        expect:
+        builder.buildOrderByClause("", entityClass, "role", "asc") == "id asc"
     }
 
-    void "test buildOrderByClause with property and explicit order"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
-        when:
-        String result = builder.buildOrderByClause("name desc", pc, "role", 
"asc")
-
-        then:
-        result == "name desc"
+    @Unroll
+    void "single property '#hql' with defaultOrder '#defaultOrder' returns 
'#expected'"() {
+        expect:
+        builder.buildOrderByClause(hql, entityClass, "role", defaultOrder) == 
expected
+
+        where:
+        hql          | defaultOrder | expected
+        "name"       | "asc"        | "name asc"
+        "name"       | "desc"       | "name desc"
+        "name asc"   | "desc"       | "name asc"
+        "name desc"  | "asc"        | "name desc"
+        "name ASC"   | "desc"       | "name asc"
+        "name DESC"  | "asc"        | "name desc"
     }
 
-    void "test buildOrderByClause with multiple properties"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
-        when:
-        String result = builder.buildOrderByClause("name, age desc", pc, 
"role", "asc")
-
-        then:
-        result == "name asc, age desc"
+    void "custom column name is used in order clause"() {
+        expect:
+        builder.buildOrderByClause("other", entityClass, "role", "asc") == 
"other_column asc"
     }
 
-    void "test buildOrderByClause with mapped column name"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
-        when:
-        String result = builder.buildOrderByClause("other", pc, "role", "asc")
-
-        then:
-        result == "other_column asc"
+    void "multiple properties with mixed directions"() {
+        expect:
+        builder.buildOrderByClause("name, age desc", entityClass, "role", 
"asc") == "name asc, age desc"
     }
 
-    void "test buildOrderByClause with null string"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
-        when:
-        String result = builder.buildOrderByClause(null, pc, "role", "asc")
-
-        then:
-        result == null
+    void "component property expands to all its columns"() {
+        expect:
+        builder.buildOrderByClause("comp", componentEntityClass, "role", 
"asc") == "comp_c1 asc, comp_c2 asc"
     }
 
-    void "test buildOrderByClause with non-existent property"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
+    void "non-existent property throws DatastoreConfigurationException"() {
         when:
-        builder.buildOrderByClause("foo", pc, "role", "asc")
+        builder.buildOrderByClause("nonExistent", entityClass, "role", "asc")
 
         then:
-        thrown(DatastoreConfigurationException)
+        def ex = thrown(DatastoreConfigurationException)
+        ex.message.contains("OrderEntity.nonExistent")
     }
 
-    void "test buildOrderByClause with invalid sort clause"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
+    void "double direction token throws DatastoreConfigurationException"() {
         when:
-        // Double ordering keyword should fail
-        builder.buildOrderByClause("name asc desc", pc, "role", "asc")
+        builder.buildOrderByClause("name asc desc", entityClass, "role", "asc")
 
         then:
         thrown(DatastoreConfigurationException)
     }
 
-    void "test buildOrderByClause with different defaultOrder"() {
+    void "inherited property from parent in joined subclass receives table 
prefix"() {
         given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderTest.name)
-
-        when:
-        String result = builder.buildOrderByClause("name", pc, "role", "desc")
-
-        then:
-        result == "name desc"
-    }
+        def ctx  = getGrailsDomainBinder().getMetadataBuildingContext()
+        def subTable = new Table("test", "sub_entity")
+        def sub = new JoinedSubclass(entityClass, ctx)
+        sub.setEntityName("SubEntity")
+        sub.setTable(subTable)
+        sub.addProperty(simpleProperty(ctx, subTable, "extra", "extra_col"))
 
-    void "test buildOrderByClause with multiple columns"() {
-        given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(OrderWithComponent.name)
+        expect: "property from root table gets no prefix when sorting on root 
class"
+        builder.buildOrderByClause("name", entityClass, "role", "asc") == 
"name asc"
 
-        when:
-        String result = builder.buildOrderByClause("comp", pc, "role", "asc")
+        and: "property from root table gets its table prefix when sorting on 
the subclass"
+        builder.buildOrderByClause("name", sub, "role", "asc") == 
"order_entity.name asc"
 
-        then:
-        result == "comp_c1 asc, comp_c2 asc"
+        and: "property from subclass table gets no prefix when sorting on the 
subclass"
+        builder.buildOrderByClause("extra", sub, "role", "asc") == "extra_col 
asc"
     }
 
-    void "test buildOrderByClause with table prefix for inherited property"() {
+    void "single-table subclass property is sorted without table prefix"() {
         given:
-        PersistentClass pc = 
datastore.metadata.getEntityBinding(SubOrderTest.name)
-
-        when:
-        // 'name' is in the base table 'order_test', 'subProperty' is in 
'sub_order_test'
-        String result = builder.buildOrderByClause("name, subProperty", pc, 
"role", "asc")
-
-        then:
-        // In GORM TPH is default, so no table prefix
-        result == "name asc, sub_property asc"
+        def ctx  = getGrailsDomainBinder().getMetadataBuildingContext()
+        
entityClass.setClassName("org.grails.orm.hibernate.cfg.domainbinding.ParentEntity")
+        def sub = new SingleTableSubclass(entityClass, ctx)
+        sub.setEntityName("ChildEntity")
+        
sub.setClassName("org.grails.orm.hibernate.cfg.domainbinding.ChildEntity")
+        sub.addProperty(simpleProperty(ctx, entityClass.getTable(), 
"childProp", "child_prop"))
+
+        expect: "parent property has no prefix on the subclass"
+        builder.buildOrderByClause("name", sub, "role", "asc") == "name asc"
+
+        and: "subclass-own property has no prefix"
+        builder.buildOrderByClause("childProp", sub, "role", "asc") == 
"child_prop asc"
     }
-}
 
-@Entity
-class OrderTest {
-    String name
-    Integer age
-    String other
+    // ---- helpers --------------------------------------------------------
 
-    static mapping = {
-        other column: 'other_column'
+    private static BasicValue basicValue(ctx, Table table, String columnName) {
+        def v = new BasicValue(ctx, table)
+        v.addColumn(new Column(columnName))
+        v
     }
-}
-
-@Entity
-class SubOrderTest extends OrderTest {
-    String subProperty
-}
 
-@Entity
-class OrderWithComponent {
-    Long id
-    TestComponent comp
-    static embedded = ['comp']
+    private static Property simpleProperty(ctx, Table table, String name, 
String columnName) {
+        def prop = new Property()
+        prop.setName(name)
+        prop.setValue(basicValue(ctx, table, columnName))
+        prop
+    }
 }
 
-class TestComponent {
-    String c1
-    String c2
-}
+// Minimal classes needed for mapped-class assignments in the STI test
+class ParentEntity {}
+class ChildEntity extends ParentEntity {}

Reply via email to