This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch 8.0.x-hibernate7 in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit ef7b9cf5b304480a23e75f65c0ffe6c7810a518d Author: Walter Duque de Estrada <[email protected]> AuthorDate: Fri Feb 20 09:09:13 2026 -0600 Implement comprehensive single-level criteria coverage in PredicateGeneratorSpec --- .../orm/hibernate/query/PredicateGenerator.java | 26 +- .../hibernatequery/PredicateGeneratorSpec.groovy | 359 +++++++++++++++++++++ 2 files changed, 372 insertions(+), 13 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 7e11030368..80cf7fdd91 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -49,14 +49,14 @@ public class PredicateGenerator { public Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, From root_, - List<Query.Criterion> criteriaList, JpaFromProvider fromsByProvider, PersistentEntity entity) { + List criteriaList, JpaFromProvider fromsByProvider, PersistentEntity entity) { List<Predicate> list = criteriaList.stream(). - map(criterion -> { + map((Object criterion) -> { if (criterion instanceof Query.Junction junction) { var criterionList = junction.getCriteria(); - var predicates = this.getPredicates(cb, criteriaQuery, root_, criterionList, fromsByProvider, entity); + var predicates = (Predicate[])this.getPredicates(cb, criteriaQuery, root_, (List)criterionList, fromsByProvider, entity); if (junction instanceof Query.Disjunction) { return cb.or(predicates); } else if (junction instanceof Query.Conjunction) { @@ -76,7 +76,7 @@ public class PredicateGenerator { List<Query.Criterion> criterionList = c.getCriteria(); JpaFromProvider childTablesByName = (JpaFromProvider) fromsByProvider.clone(); childTablesByName.put("root", child); - return cb.and(this.getPredicates(cb, criteriaQuery, child, criterionList, childTablesByName, entity)); + return cb.and((Predicate[])this.getPredicates(cb, criteriaQuery, child, (List)criterionList, childTablesByName, entity)); } else if (criterion instanceof Query.PropertyCriterion pc) { var fullyQualifiedPath = fromsByProvider.getFullyQualifiedPath(pc.getProperty()); if (criterion instanceof Query.Equals c) { @@ -122,10 +122,10 @@ public class PredicateGenerator { } else if (criterion instanceof Query.Like c) { return cb.like(fullyQualifiedPath, c.getValue().toString()); } else if (criterion instanceof Query.In c) { - var queryableCriteria = getQueryableCriteriaFromInCriteria(criterion); + var queryableCriteria = getQueryableCriteriaFromInCriteria((Query.Criterion)criterion); if (Objects.nonNull(queryableCriteria)) { - CriteriaBuilder.In value = getQueryableCriteriaValue(cb, criteriaQuery, fromsByProvider, entity, (Query.PropertyNameCriterion) criterion, queryableCriteria); + CriteriaBuilder.In value = getQueryableCriteriaValue(cb, criteriaQuery, fromsByProvider, entity, (Query.PropertyNameCriterion)criterion, queryableCriteria); return value; } else if (!c.getValues().isEmpty()) { boolean areGormEntities = c.getValues().stream().allMatch(GormEntity.class::isInstance); @@ -138,9 +138,9 @@ public class PredicateGenerator { return cb.in(fullyQualifiedPath, c.getValues()); } } else if (criterion instanceof Query.NotIn c) { - var queryableCriteria = getQueryableCriteriaFromInCriteria(criterion); + var queryableCriteria = getQueryableCriteriaFromInCriteria((Query.Criterion)criterion); if (Objects.nonNull(queryableCriteria)) { - CriteriaBuilder.In value = getQueryableCriteriaValue(cb, criteriaQuery, fromsByProvider, entity, (Query.PropertyNameCriterion) criterion, queryableCriteria); + CriteriaBuilder.In value = getQueryableCriteriaValue(cb, criteriaQuery, fromsByProvider, entity, (Query.PropertyNameCriterion)criterion, queryableCriteria); return cb.not(value); } else if (Objects.nonNull(c.getSubquery()) && !c.getSubquery().getProjections().isEmpty() @@ -152,7 +152,7 @@ public class PredicateGenerator { Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); boolean distinct = projection instanceof Query.DistinctPropertyProjection; JpaFromProvider newMap2 = (JpaFromProvider) fromsByProvider.clone(); - Predicate[] predicates2 = this.getPredicates(cb, criteriaQuery, from2, subCriteria2, newMap2, entity); + Predicate[] predicates2 = (Predicate[])this.getPredicates(cb, criteriaQuery, from2, (List)subCriteria2, newMap2, entity); subquery2.select(from2.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates2)); return cb.not(cb.in(fullyQualifiedPath).value(subquery2)); } else if ( Objects.nonNull(c.getSubquery()) @@ -163,7 +163,7 @@ public class PredicateGenerator { Root from2 = subquery2.from(c.getValue().getPersistentEntity().getJavaClass()); List subCriteria2 = c.getValue().getCriteria(); JpaFromProvider newMap2 = (JpaFromProvider) fromsByProvider.clone(); - Predicate[] predicates2 = this.getPredicates(cb, criteriaQuery, from2, subCriteria2, newMap2, entity); + Predicate[] predicates2 = (Predicate[])this.getPredicates(cb, criteriaQuery, from2, (List)subCriteria2, newMap2, entity); subquery2.select(from2).where(cb.and(predicates2)); return cb.not(cb.in(root_.get("id")).value(subquery2)); } else { @@ -176,7 +176,7 @@ public class PredicateGenerator { List subCriteria = c.getValue().getCriteria(); JpaFromProvider newMap = (JpaFromProvider) fromsByProvider.clone(); newMap.put("root", from); - Predicate[] predicates = this.getPredicates(cb, criteriaQuery, from, subCriteria, newMap, entity); + Predicate[] predicates = (Predicate[])this.getPredicates(cb, criteriaQuery, from, (List)subCriteria, newMap, entity); if (c instanceof Query.GreaterThanEqualsAll sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); return cb.greaterThanOrEqualTo(fromsByProvider.getFullyQualifiedPath(sc.getProperty()), subquery); @@ -236,7 +236,7 @@ public class PredicateGenerator { JpaFromProvider newMap = (JpaFromProvider) fromsByProvider.clone(); newMap.put("root", subRoot); - var predicates = this.getPredicates(cb, criteriaQuery, subRoot, c.getSubquery().getCriteria(), newMap, entity); + var predicates = (Predicate[])this.getPredicates(cb, criteriaQuery, subRoot, (List)c.getSubquery().getCriteria(), newMap, entity); var existsPredicate = getExistsPredicate(cb, root_, childPersistentEntity, subRoot); Predicate[] allPredicates = Stream.concat( @@ -255,7 +255,7 @@ public class PredicateGenerator { JpaFromProvider newMap = (JpaFromProvider) fromsByProvider.clone(); newMap.put("root", subRoot); - var predicates = this.getPredicates(cb, criteriaQuery, subRoot, c.getSubquery().getCriteria(), newMap, entity); + var predicates = (Predicate[])this.getPredicates(cb, criteriaQuery, subRoot, (List)c.getSubquery().getCriteria(), newMap, entity); var existsPredicate = getExistsPredicate(cb, root_, childPersistentEntity, subRoot); Predicate[] allPredicates = Stream.concat( diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/PredicateGeneratorSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/PredicateGeneratorSpec.groovy new file mode 100644 index 0000000000..de19560c88 --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/PredicateGeneratorSpec.groovy @@ -0,0 +1,359 @@ +package grails.gorm.specs.hibernatequery + +import grails.gorm.DetachedCriteria +import grails.gorm.specs.HibernateGormDatastoreSpec +import jakarta.persistence.criteria.CriteriaQuery +import jakarta.persistence.criteria.Root +import org.apache.grails.data.testing.tck.domains.Person +import org.apache.grails.data.testing.tck.domains.Pet +import org.apache.grails.data.testing.tck.domains.Face +import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.datastore.mapping.query.Query +import org.grails.orm.hibernate.query.JpaFromProvider +import org.grails.orm.hibernate.query.PredicateGenerator +import org.hibernate.query.criteria.HibernateCriteriaBuilder + +class PredicateGeneratorSpec extends HibernateGormDatastoreSpec { + + PredicateGenerator predicateGenerator + HibernateCriteriaBuilder cb + CriteriaQuery<Person> query + Root<Person> root + JpaFromProvider fromProvider + PersistentEntity personEntity + + def setup() { + predicateGenerator = new PredicateGenerator() + cb = sessionFactory.getCriteriaBuilder() + query = cb.createQuery(Person) + root = query.from(Person) + personEntity = manager.hibernateDatastore.getMappingContext().getPersistentEntity(Person.typeName) + fromProvider = new JpaFromProvider(new DetachedCriteria(Person), query, root) + } + + def setupSpec() { + manager.addAllDomainClasses([Person, Pet, Face]) + } + + def "test getPredicates with Equals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.Equals("firstName", "Bob")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with NotEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.NotEquals("firstName", "Bob")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with IdEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.IdEquals(1L)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with GreaterThan criterion"() { + given: + List<Query.Criterion> criteria = [new Query.GreaterThan("age", 20)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with GreaterThanEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.GreaterThanEquals("age", 20)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with LessThan criterion"() { + given: + List<Query.Criterion> criteria = [new Query.LessThan("age", 20)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with LessThanEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.LessThanEquals("age", 20)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with SizeEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.SizeEquals("pets", 1)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with SizeNotEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.SizeNotEquals("pets", 1)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with SizeGreaterThan criterion"() { + given: + List<Query.Criterion> criteria = [new Query.SizeGreaterThan("pets", 1)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with SizeGreaterThanEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.SizeGreaterThanEquals("pets", 1)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with SizeLessThan criterion"() { + given: + List<Query.Criterion> criteria = [new Query.SizeLessThan("pets", 1)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with SizeLessThanEquals criterion"() { + given: + List<Query.Criterion> criteria = [new Query.SizeLessThanEquals("pets", 1)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with Between criterion"() { + given: + List<Query.Criterion> criteria = [new Query.Between("age", 18, 30)] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with ILike criterion"() { + given: + List<Query.Criterion> criteria = [new Query.ILike("firstName", "B%")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with RLike criterion"() { + given: + List<Query.Criterion> criteria = [new Query.RLike("firstName", "B.*")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with Like criterion"() { + given: + List<Query.Criterion> criteria = [new Query.Like("firstName", "B%")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with In criterion"() { + given: + List<Query.Criterion> criteria = [new Query.In("firstName", ["Bob", "Fred"])] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with NotIn criterion"() { + given: + List<Query.Criterion> criteria = [new Query.NotIn("firstName", new DetachedCriteria(Person).eq("firstName", "Bob").property("firstName"))] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with IsNull criterion"() { + given: + List<Query.Criterion> criteria = [new Query.IsNull("firstName")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with IsNotNull criterion"() { + given: + List<Query.Criterion> criteria = [new Query.IsNotNull("firstName")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with IsEmpty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.IsEmpty("pets")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with IsNotEmpty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.IsNotEmpty("pets")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with EqualsProperty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.EqualsProperty("firstName", "lastName")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with NotEqualsProperty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.NotEqualsProperty("firstName", "lastName")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with LessThanEqualsProperty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.LessThanEqualsProperty("age", "age")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with LessThanProperty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.LessThanProperty("age", "age")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with GreaterThanEqualsProperty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.GreaterThanEqualsProperty("age", "age")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with GreaterThanProperty criterion"() { + given: + List<Query.Criterion> criteria = [new Query.GreaterThanProperty("age", "age")] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with DistinctProjection criterion"() { + given: + def distinct = new Query.DistinctProjection() + def criteriaList = [distinct] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteriaList, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with Conjunction"() { + given: + var conjunction = new Query.Conjunction() + conjunction.add(new Query.Equals("firstName", "Bob")) + conjunction.add(new Query.GreaterThan("age", 20)) + List<Query.Criterion> criteria = [conjunction] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with Disjunction"() { + given: + var disjunction = new Query.Disjunction() + disjunction.add(new Query.Equals("firstName", "Bob")) + disjunction.add(new Query.Equals("firstName", "Fred")) + List<Query.Criterion> criteria = [disjunction] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with Negation"() { + given: + var negation = new Query.Negation() + negation.add(new Query.Equals("firstName", "Bob")) + List<Query.Criterion> criteria = [negation] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + def "test getPredicates with DetachedAssociationCriteria"() { + given: + var association = personEntity.getPropertyByName("pets") + var associationCriteria = new org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria(Pet, association, "pets") + associationCriteria.eq("name", "Lucky") + List criteria = [associationCriteria] + when: + def predicates = predicateGenerator.getPredicates(cb, query, root, (List<Query.Criterion>)criteria, fromProvider, personEntity) + then: + predicates.length == 1 + } + + private jakarta.persistence.criteria.Predicate[] callGetPredicatesUntyped(List criteria) { + return predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity) + } +}
