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

   Fixes #16805
   
   Stacked on #16821 (chain: #16816, #16817, #16818, #16820, #16821). `no ci` 
until the chain reaches 8.0.x.
   
   ## Problem
   
   `deleteAll()` and `updateAll(Map)` on a query run one HQL statement that has 
no `LIMIT`. A query with `max` or `offset` therefore wrote to **every** 
matching row: `Person.where { age > 18 }.max(2).deleteAll()` deleted all of 
them. The HQL builder behind these statements also had gaps:
   
   - a subquery with two criteria produced `... < :p2age > :p3` (no `AND`), 
which does not parse;
   - the position returned for an association criterion was dropped, so a 
parameter after it reused a number;
   - `exists`, `notExists`, a to-one association, an alias and `sqlRestriction` 
were refused.
   
   ## Changes
   
   - `HibernateSession.deleteAll` / `updateAll` throw 
`InvalidDataAccessResourceUsageException` for `max` or `offset` and write 
nothing. `QueryableCriteria` gets `getDefaultMax()` / `getDefaultOffset()` 
(default `null`) for the check.
   - `JpaQueryBuilder`:
     - joins a subquery's criteria with `AND`, and drops `WHERE` when it has 
none;
     - keeps the parameter position after an association criterion;
     - writes `Exists` / `NotExists`;
     - writes a to-one association (block, dotted path, `createAlias` alias) as 
`owner.id IN (SELECT ...)`, since HQL DML cannot join. A to-many association is 
still refused with the same message;
     - `registerHqlRenderer` lets a datastore render a criterion type it adds. 
Hibernate 7 registers `SqlRestrictionHqlRenderer`, which calls the existing 
`grails_sql_restriction` function, so `{alias}` and `?` work.
   - `Query.PropertyNameCriterion.withProperty(String)` copies a criterion onto 
another property, used to split `owner.name`.
   - Two existing specs pinned the old behavior and are updated: 
`JpaQueryBuilderFunctionSpec` expected the missing `AND`, and 
`HibernateCriteriaBuilderSqlRestrictionSpec` expected `sqlRestriction` to be 
refused in a batch operation.
   
   ## Tests
   
   - `BulkWritePaginationGuardSpec` (8): max, offset, both, derived criteria, 
delete by selected ids, and the unpaginated control. Red before the fix (6 
failures).
   - `BulkWriteQueryShapesSpec` (17): subqueries, deferred subquery, exists, 
notExists, to-one block, path, alias, position after an association, 
`sqlRestriction` with `{alias}`, `?` and a quoted literal. Red before the fix 
(9 failures).
   - `JpaQueryBuilderBulkWriteSpec` (13): the exact HQL and parameters, a 
registered renderer, and an unknown criterion.
   - `SqlRestrictionHqlRendererSpec` (7).
   - Full suites pass for `grails-datastore-core`, `grails-datamapping-core`, 
`grails-datamapping-core-test`, `grails-data-hibernate7-core` and 
`grails-data-hibernate5-core`; `codeStyle`, `validateRepositoryConventions` and 
`rat` are clean.
   
   ## Not covered
   
   - PITest on `JpaQueryBuilder` (run with #16819's `mutableProjects`, from 
`grails-datamapping-core-test`): no mutant survives in the methods this PR 
added, except `dot <= 0` in `splitToOnePath`, which is an equivalent mutant (an 
empty head name matches nothing). The older methods of the class keep their 
uncovered mutants (for example `functionOperator`); they are not part of this 
change.
   - A dotted alias path such as `createAlias('owner.address', 'a')` is not 
resolved in a bulk write; it is refused with the property error.
   
   ## Docs
   
   8.0 upgrade guide section 26.14, the CRUD guide note, and the 
`grails-8-upgrade` skill.
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

  • [PR] Hibernate 7: reject max a... borinquenkid (via GitHub) via notifications

Reply via email to