From 4bc262c6bd5991455cb915d168e1027abd2f8239 Mon Sep 17 00:00:00 2001 From: Puneet Behl Date: Tue, 28 Apr 2020 00:17:31 +0530 Subject: [PATCH] Fixes grails/grails-data-mapping#1283 Prevent type conversion when criteria is instanceof org.hibernate.criterion.DetachedCriteria. --- .../query/AbstractHibernateQuery.java | 9 ++-- .../tests/DetachCriteriaSubquerySpec.groovy | 41 +++++++++++++++++-- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index a7cd4f206..dc1f2a605 100644 --- a/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate5/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -164,10 +164,10 @@ else if (criterion instanceof PropertyCriterion) { Object value = pc.getValue(); if (value instanceof QueryableCriteria) { setDetachedCriteriaValue((QueryableCriteria) value, pc); - } - // ignore Size related constraints - else { - doTypeConversionIfNeccessary(getEntity(), pc); + } else { + if (!(value instanceof DetachedCriteria)) { + doTypeConversionIfNeccessary(getEntity(), pc); + } } } if (criterion instanceof DetachedAssociationCriteria) { @@ -266,6 +266,7 @@ protected String getCurrentAlias() { @SuppressWarnings("unchecked") static void doTypeConversionIfNeccessary(PersistentEntity entity, PropertyCriterion pc) { + // ignore Size related constraints if (pc.getClass().getSimpleName().startsWith(SIZE_CONSTRAINT_PREFIX)) { return; } diff --git a/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/DetachCriteriaSubquerySpec.groovy b/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/DetachCriteriaSubquerySpec.groovy index 49d1efe31..813799397 100644 --- a/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/DetachCriteriaSubquerySpec.groovy +++ b/grails-datastore-gorm-hibernate5/src/test/groovy/grails/gorm/tests/DetachCriteriaSubquerySpec.groovy @@ -9,7 +9,7 @@ class DetachCriteriaSubquerySpec extends GormDatastoreSpec { @Override List getDomainClasses() { - return [User, Group, GroupAssignment] + return [User, Group, GroupAssignment, Organisation] } void "test detached associated criteria in subquery"() { @@ -43,6 +43,30 @@ class DetachCriteriaSubquerySpec extends GormDatastoreSpec { result.size() == 1 } + void "test executing detached criteria in sub-query multiple times"() { + + setup: + Organisation orgA = new Organisation(name: "A") + orgA.addToUsers(email: 'user1@a') + orgA.addToUsers(email: 'user2@a') + orgA.addToUsers(email: 'user3@a') + orgA.save(flush: true) + Organisation orgB = new Organisation(name: "B") + orgB.addToUsers(email: 'user1@b') + orgB.addToUsers(email: 'user2@b') + orgB.save(flush: true) + + when: + DetachedCriteria criteria = User.where { + inList('organisation', Organisation.where { name == 'A' || name == 'B' }.id()) + } + List result = criteria.list() + result = criteria.list() + + then: + result.size() == 5 + } + void "test that detached criteria subquery should create implicit alias instead of using this_"() { setup: @@ -74,9 +98,11 @@ class DetachCriteriaSubquerySpec extends GormDatastoreSpec { } private User createUser(String email) { - User user = new User() - user.email = email - user.save(flush: true) + User user = new User(email: email) + Organisation defaultOrg = Organisation.findOrCreateByName("default") + defaultOrg.addToUsers(user) + defaultOrg.save(flush: true) + user } private Group createGroup(String name, User supervisor) { @@ -99,6 +125,7 @@ class DetachCriteriaSubquerySpec extends GormDatastoreSpec { @Entity class User implements HibernateEntity { String email + static belongsTo = [organisation: Organisation] static mapping = { table 'T_USER' } @@ -121,3 +148,9 @@ class GroupAssignment implements HibernateEntity { table 'T_GROUP_ASSIGNMENT' } } + +@Entity +class Organisation implements HibernateEntity { + String name + static hasMany = [users: User] +}