borinquenkid opened a new pull request, #16735:
URL: https://github.com/apache/grails-core/pull/16735
## Summary
Fixes #16717, and does the first two steps of #16616: one lexical scanner
for the query package, and one reading per HQL query.
Three scanners in `org.grails.orm.hibernate.query` each decided on their own
what to skip: `HqlQueryContext.indexOfTopLevel` and `getCommas` (no `--`
comments, no backquotes in the comma count), `SqlRestriction.scan` (quotes and
comments only), and `SqlProjection.splitColumns` (brackets, dollar quotes, both
comment kinds, but quotes tested before the bracket state). Every recent bug of
this family was a rule mismatch between them: #16597, #16712 and now the second
half of #16717.
`SqlText` now owns the rules once, and reads the text once: when an instance
is created, each character is classified as plain text, quoted text or comment,
and each plain character gets its parenthesis depth, so every later question
walks those two arrays and nothing rescans the string. The rules: string
literals and quoted identifiers with a doubled quote for the quote, `[bracket
identifiers]` with `]]` and dollar-quoted strings in native SQL, line and block
comments, and parentheses when a top-level position is asked for. It offers
`indexOfTopLevel`, `splitTopLevel`, `countTopLevel`, `plainIndexes`,
`unwrapOuterParentheses`, `withoutTrailingComments` and `endsInLineComment`, in
an `HQL` or `SQL` dialect. The three scanners delegate to it; the callers'
specs are unchanged and pass.
**One reading per HQL query.** `HqlQueryContext.prepare` used to read the
same query four times through separate static helpers: normalise it, count its
projections, take its single projection clause, find its root alias, each one
lowercasing and scanning the text again, and `getTarget` normalised the already
normalised text once more. The new `HqlText` is one reading: it lowercases
once, scans once with `SqlText`, finds the `select` and `from` once, and
derives the projection count, the select clause, the root alias, the normalized
form and the result type of that normalized form from those positions, without
reading the normalized text at all. `prepare` creates one `HqlText` and takes
the query text and the target class from it. The static helpers the spec calls
remain as thin entry points over `HqlText`, so `HqlQueryContextSpec` keeps its
64 cases as the safety net, and `HqlTextSpec` shows the one-reading contract on
a table of queries. Two behaviours improve as a side effect:
the HQL projection count now ignores a comma inside a comment or a backquoted
identifier, and the HQL keyword search skips `--` comments, as Copilot noted on
#16719.
The two defects of #16717:
- **A column alias with a space broke the count over the projection.**
`JpaProjectionAdapter` gave a subquery selection a generated alias only when it
had none, so `createCriteria().count { projections { sqlProjection ... } }`,
which counts over the projection as a derived table, rendered `derived1_0(box
width)` and H2 rejected it. Nothing reads a subquery's selections by alias, so
every subquery selection now gets a generated one, and the derived table reads
`derived1_0(col_0)`; the main query keeps the caller's alias for `order` and
results. (A paged `list(max:)` was never affected: its total counts the
entity's ids and leaves the projection out.)
- **An apostrophe inside a bracket identifier swallowed the SQL.**
`splitColumns` tested quotes before the bracket state, so `width as [box's
width], height as total` was one column. Inside brackets only brackets count
now.
`unwrapOuterParentheses` is there for #16719, whose root-query unwrapping
becomes a call to it at the start of `HqlText`'s reading; the union-branch case
of #16712 is a row in `SqlTextSpec` already (left as it is, by design, since
the parentheses do not enclose the whole query).
## Verification
- `HqlTextSpec`: one reading per query gives the projection count, clause,
root alias, normalized form and target for a table of queries, including
comments and a literal with a comma.
- `SqlTextSpec`: one table per capability, with the apostrophe in a bracket,
`]]`, nested subscripts, dollar quotes, both comment kinds with separators
inside, escaped quotes, keywords inside names and literals, a `with` clause,
nested and unbalanced parentheses, the union branches, and `?` placeholders in
every hiding place.
- `SqlProjectionSpec` and `HqlQueryContextSpec` gain the rows the fix adds;
`HibernateCriteriaBuilderSqlProjectionSpec` gains a `count {}` over a
`sqlProjection` aliased `box width`, which fails with the H2 syntax error
before the fix and asserts the generated alias in the captured SQL after it.
- `:grails-data-hibernate7-core:test`, `checkstyleMain`, `codenarcTest`: see
the CI run.
--
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]