borinquenkid opened a new pull request, #16696:
URL: https://github.com/apache/grails-core/pull/16696
Fixes #16563.
Two additive extension points for the Hibernate 7 criteria builder, asked
for by grails-postgresql-extensions' Hibernate 7 port
(gpc/grails-postgresql-extensions#136), which today has to guess which join
GORM made for an alias and smuggle an `order by` through a criterion.
## Resolving property paths in a criterion handler
`PredicateGenerator.CriterionHandler` gains a default five-parameter
`handle(query, root, cb, criterion, context)` that `PredicateGenerator` now
dispatches to; its default delegates to the four-parameter method, so every
existing handler, including closures coerced to the interface, keeps working
unchanged. A handler that needs the context implements the new
`ContextualCriterionHandler` (five-parameter abstract method, so a
five-parameter closure coerces to it). Through
`JpaQueryContext.getFullyQualifiedPath(String)` the handler resolves
`alias.property` or `association.property` to the join GORM created for it, so
a custom criterion and a GORM criterion on the same association restrict the
same row rather than each joining the association again.
## Ordering by an expression
A `Query.Order` subclass can now be converted by a registered
`PredicateGenerator.OrderHandler` (`handle(query, root, cb, order, context)`
returning a JPA `Order`, or `null` to leave the order out).
`JpaCriteriaQueryCreator.assignOrderBy` looks the handler up by the order's
exact class before the property path handling, so the order keeps its place
among the query's orders. `registerOrderHandler`, `orderHandler(type)`,
`clearCustomOrderHandlers` and an `OrderHandlerProvider` ServiceLoader SPI
(`META-INF/services/org.grails.orm.hibernate.query.PredicateGenerator$OrderHandlerProvider`)
mirror the criterion ones; `loadServiceProviders` loads both kinds. A
`Query.Order` subclass already reaches the creator untouched through
`HibernateCriteriaBuilder.order(Query.Order)` → `HibernateQuery.order` →
`DetachedCriteria.order`.
## Tests
- `HibernateCriteriaBuilderDirectSpec`: a contextual handler on
`children.name` next to `children { eq('name', 'Kid') }` finds the parent whose
child matches both, and finds nothing when two children match one criterion
each, which proves the handler used GORM's join and not a second one; an order
handler's order comes before a property order and a `null` return leaves it out.
- `JpaCriteriaQueryCreatorSpec`: the handler's JPA order is first in
`orderList`, the handler receives the query's context, and a `null` return
leaves only the property order.
- `PredicateGeneratorSpec`: a contextual handler receives the very context
passed to `getPredicates`; a four-parameter handler is still called.
- `grails-test-examples/hibernate7/criteria-extension`: `PriceDistanceOrder`
with an `OrderHandlerProvider` discovered through `META-INF/services`, an
`orderByPriceDistance` extension and `ProductSearchService.findNearestPrice`,
with three integration cases (nearest first, position among orders, through the
service); `NumberLikeCriterionHandlerProvider` now resolves its property
through the context.
Locally (JDK 21): the three core specs 98/98, `codenarcMain`/`codenarcTest`
clean on `grails-data-hibernate7-core`, the example app 7 unit + 18 integration
specs green, and the full `:grails-data-hibernate7-core:test` run: 3,821 tests,
3,820 passed, 22 skipped. The one red result is `SqlRestrictionHibernate7Spec >
sqlRestriction works with Oracle`, whose Oracle container was killed 27 s after
starting on its first attempt and passed on the retry the build configures; the
same image starts by hand in 15 s, and the three other Oracle specs passed in
the run, so that is the local Docker environment rather than the change.
## Docs
New section *Extending the Criteria Builder* in the GORM for Hibernate 7
guide (`querying/criteria.adoc`, before *Method Reference*), covering custom
criteria and orders, the context, programmatic and ServiceLoader registration;
What's New entry *Hibernate 7 Criteria Queries Can Be Extended*.
## Base
Built on the Java-to-Groovy rewrite of the module (#16572) so that it lands
in 10.0.x after it without a hand port; to be retargeted to `10.0.x` once
#16572 merges.
## CI on this PR
CI is deliberately not running on this branch yet. It carries one temporary
commit, `CHANGEME FOR ACCEPTANCE: disable PR workflow triggers`, which points
the `pull_request:` trigger of the 13 workflows at a branch that does not
exist, so pushes and rebases start no jobs while the runner pool is under
pressure. We are waiting for #16673, which gates the test jobs through one CI
policy, to land; after that the temporary commit is reverted here and CI runs
before merge. **The absence of checks does not mean the change is untested**:
the results above are from local runs, and the base branch's CI (#16572) covers
the module build.
--
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]