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]

Reply via email to