This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch merge-hibernate6 in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit fd64783f7e8feb53fde7057bfb72822341fc4f7f Author: Walter Duque de Estrada <[email protected]> AuthorDate: Fri Jun 27 18:02:21 2025 -0500 fix In and NotIn criteria --- .../orm/hibernate/query/PredicateGenerator.java | 123 +++++++++------------ 1 file changed, 55 insertions(+), 68 deletions(-) diff --git a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index f3fe72bcc6..204cf3f3d1 100644 --- a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -1,17 +1,24 @@ package org.grails.orm.hibernate.query; import groovy.util.logging.Slf4j; +import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.From; import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.query.Query; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaInPredicate; +import org.hibernate.query.criteria.JpaJoin; +import org.hibernate.query.criteria.JpaPath; +import org.hibernate.query.sqm.tree.domain.SqmPath; +import org.hibernate.query.sqm.tree.domain.SqmSetJoin; import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -146,74 +153,52 @@ public class PredicateGenerator { return cb.lt(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeLessThanEquals c) { return cb.le(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); - } else if ( - criterion instanceof Query.In c - && Objects.nonNull(c.getSubquery()) - && !c.getSubquery().getProjections().isEmpty() - && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection - ) { - JpaInPredicate in = cb.in(root_.get(c.getProperty())); - Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); - boolean distinct = projection instanceof Query.DistinctPropertyProjection; - Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); - Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - List subCriteria = c.getSubquery().getCriteria(); - JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); - newMap.put("root", from); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); - subquery.select(newMap.getFullyQualifiedPath(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); - return in.value(subquery); - } else if ( - criterion instanceof Query.NotIn c - && Objects.nonNull(c.getSubquery()) - && !c.getSubquery().getProjections().isEmpty() - && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection - ) { - JpaInPredicate in = cb.in(root_.get(c.getProperty())); - Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); - boolean distinct = projection instanceof Query.DistinctPropertyProjection; - Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); - Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - List subCriteria = c.getSubquery().getCriteria(); - JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); - newMap.put("root", from); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); - subquery.select(newMap.getFullyQualifiedPath(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); - return cb.not(in.value(subquery)); - } else if (criterion instanceof Query.In c - && Objects.nonNull(c.getSubquery()) - && !c.getSubquery().getProjections().isEmpty() - && c.getSubquery().getProjections().get(0) instanceof Query.IdProjection - ) { - JpaInPredicate in = cb.in(root_.get("id")); - Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); - Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - List subCriteria = c.getSubquery().getCriteria(); - JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); - newMap.put("root", from); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); - subquery.select(from).where(cb.and(predicates)); - return in.value(subquery); - } else if (criterion instanceof Query.NotIn c - && Objects.nonNull(c.getSubquery()) - && !c.getSubquery().getProjections().isEmpty() - && c.getSubquery().getProjections().get(0) instanceof Query.IdProjection - ) { - JpaInPredicate in = cb.in(root_.get("id")); - Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); - Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - List subCriteria = c.getSubquery().getCriteria(); - JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); - newMap.put("root", from); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); - subquery.select(from).where(cb.and(predicates)); - return cb.not(in.value(subquery)); - } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() - ) { - return cb.in(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValues()); - } else if (criterion instanceof Query.NotIn c - ) { - return cb.not(cb.in(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValue())); + } else if(criterion instanceof Query.In || criterion instanceof Query.NotIn) { + Path path; + QueryableCriteria queryableCriteria; + if (criterion instanceof Query.In in ) { + path = tablesByName.getFullyQualifiedPath(in.getProperty()); + queryableCriteria = in.getSubquery(); + } else { + Query.NotIn notIn = (Query.NotIn) criterion; + path = tablesByName.getFullyQualifiedPath(notIn.getProperty()); + queryableCriteria = notIn.getSubquery(); + } + if (Objects.nonNull(queryableCriteria)) { + Query.Projection projection = !queryableCriteria.getProjections().isEmpty() ? + (Query.Projection )queryableCriteria.getProjections().get(0) : new Query.IdProjection() ; + String subProperty; + JpaInPredicate in; + if (projection instanceof Query.PropertyProjection) { + subProperty = ((Query.PropertyProjection) projection).getPropertyName(); + in =cb.in(path); + } else if (projection instanceof Query.IdProjection) { + subProperty = "id"; + in =cb.in(((SqmPath)path).get(subProperty)); + } else { + throw new IllegalStateException("Unsupported projection type: " + projection); + } + boolean distinct = "id".equals(subProperty) || projection instanceof Query.DistinctPropertyProjection; + + Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); + Root from = subquery.from(queryableCriteria.getPersistentEntity().getJavaClass()); + List subCriteria = queryableCriteria.getCriteria(); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); + newMap.put("root", from); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); + subquery.select( + newMap.getFullyQualifiedPath(subProperty) + ).distinct(distinct).where(cb.and(predicates)); + CriteriaBuilder.In value = in.value(subquery); + if (criterion instanceof Query.In) { + return value; + } + return cb.not(value); + } else if (criterion instanceof Query.In c && !c.getValues().isEmpty()) { + return cb.in(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValues()); + } else if (criterion instanceof Query.NotIn c) { + return cb.not(cb.in(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValue())); + } } else if (criterion instanceof Query.Exists c) { Subquery subquery = criteriaQuery.subquery(Object.class); Root subRoot = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); @@ -291,6 +276,8 @@ public class PredicateGenerator { } + + private static Class getJavaTypeOfInClause(SqmInListPredicate in) { Class javaTypeOfInClause = in.getTestExpression().getExpressible().getExpressibleJavaType().getJavaTypeClass(); return javaTypeOfInClause;
