You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@grails.apache.org by "jamesfredley (via GitHub)" <gi...@apache.org> on 2026/02/20 00:21:08 UTC

[PR] Fix exists() cross-join caused by duplicate CriteriaQuery root [grails-core]

jamesfredley opened a new pull request, #15419:
URL: https://github.com/apache/grails-core/pull/15419

   ## Summary
   
   Fixes #14334
   
   `GormEntity.exists()` was performing a cartesian product (cross-join) against the entire table due to `criteriaQuery.from()` being called twice in `AbstractHibernateGormStaticApi.exists()`.
   
   Reproducer: https://github.com/scottlollman/grails-data-mapping-issue-2071
   
   ## Root Cause
   
   `AbstractHibernateGormStaticApi.exists()` created two query roots:
   
   ```groovy
   Root queryRoot = criteriaQuery.from(persistentEntity.javaClass)          // root 1
   // ...
   criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(...)))     // root 2 (BUG)
   ```
   
   Each call to `criteriaQuery.from()` adds a new root to the query. Two roots on the same table produce a cross-join:
   
   ```sql
   -- Before (cross-join scans entire table)
   select count(generatedAlias0)
   from SomeDomain as generatedAlias1, SomeDomain as generatedAlias0
   where generatedAlias1.id=1L
   
   -- After (single root, simple indexed lookup)
   select count(generatedAlias0)
   from SomeDomain as generatedAlias0
   where generatedAlias0.id=1L
   ```
   
   While the boolean result was technically correct (non-zero = true), the query performed a full table scan for every `exists()` call.
   
   ## Fix
   
   One-line change - reuse the existing `queryRoot` variable instead of calling `criteriaQuery.from()` a second time:
   
   ```groovy
   criteriaQuery.select(criteriaBuilder.count(queryRoot))
   ```
   
   ## Tests
   
   `ExistsCrossJoinSpec` - 4 integration tests using a real `HibernateDatastore` with H2:
   - `exists` returns true for existing entity
   - `exists` returns false for non-existent id
   - `exists` does not produce a cross-join (SQL captured via Hibernate `StatementInspector`, verified no cross-join or comma-join pattern)
   - `exists` with multiple rows returns correct result
   
   Existing `ReadOperationSpec` tests continue to pass.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@grails.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Fix exists() cross-join caused by duplicate CriteriaQuery root [grails-core]

Posted by "jdaugherty (via GitHub)" <gi...@apache.org>.
jdaugherty merged PR #15419:
URL: https://github.com/apache/grails-core/pull/15419


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@grails.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org