matrei opened a new pull request, #16505:
URL: https://github.com/apache/grails-core/pull/16505
## Description
The Hibernate 7 guide documents `sqlRestriction` in criteria queries, but
the Hibernate 7 `HibernateCriteriaBuilder` had no such method, so a criteria
query using it failed with a `MissingMethodException`. This adds it, with the
same signatures as on Hibernate 5:
```groovy
Person.createCriteria().list {
sqlRestriction 'char_length({alias}.first_name) < ? and
char_length({alias}.first_name) > ?', [maxValue, minValue]
}
```
- The SQL is added to the `where` clause as written.
- Each `?` is bound as a parameter to the value at the same position. A
mismatch between the number of `?` placeholders and values, or a `null` value,
is rejected with an `IllegalArgumentException` when `sqlRestriction` is called.
- `{alias}` stands for the table alias of the queried class, or of the
association inside an association block such as `pets { ... }`. This matches
Hibernate 5, where Hibernate's `Restrictions.sqlRestriction` replaces it.
### Implementation
The builder adds a `SqlRestriction` criterion, which `PredicateGenerator`
translates to a call of a SQL function, `grails_sql_restriction`, registered
with a `FunctionContributor` like the existing `rlike` function. The function:
- is a predicate function (`SqmFunctionDescriptor.isPredicate()`, Hibernate
7.0), the mechanism Hibernate uses for its own `regexp_like` and `json_exists`.
Hibernate therefore renders it as a condition of its own, not as `(...) =
true`, which databases without boolean expressions would reject.
- takes the SQL as a literal, an identifier column of the queried class (the
first identifier property for a composite identifier) whose table alias
replaces `{alias}`, and the parameters, which replace the `?` placeholders as
in Hibernate's own `sql()` function.
Rendering uses Hibernate's SQL AST types, as every custom function renderer
does. That package is `@Incubating`, so a Hibernate upgrade may need small
changes to `GrailsSqlRestrictionFunction`; the specs below would catch them.
The Hibernate 7 guide now says how the values are bound and documents
`{alias}`, with an example of a join that makes it necessary.
### Tests
- New `HibernateCriteriaBuilderSqlRestrictionSpec` (H2): the generated SQL
is the condition as written with `{alias}` replaced and the values as `?`
(checked with a `StatementInspector`); a condition without values; `{alias}`
with a join that adds a column of the same name and inside an association
block; `not`, `or` and `count`; an entity with a composite identifier, and one
whose composite identifier starts with an association; a subclass mapped to its
own table; placeholder count mismatches and a `null` value.
- New `SqlRestrictionHibernate7Spec` (Testcontainers): the same restrictions
on H2, PostgreSQL 16, MySQL 8.0, MariaDB 10.11 and Oracle Free, including a
paged list's `totalCount`.
- `PredicateGeneratorSpec`: a `SqlRestriction` criterion binds its values
and replaces `{alias}`.
All 3495 tests of `:grails-data-hibernate7-core:test` pass, including the
Testcontainers spec, and so do `checkstyleMain`, `codenarcMain` and the
Hibernate 7 guide build (`:grails-data-hibernate7-docs:asciidoctor`).
--
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]