daniellansun commented on PR #3155: URL: https://github.com/apache/groovy/pull/3155#issuecomment-6768283276
Jochen, thanks for the review. I agree with the direction: a mapping that cannot be decided should be rejected or left in memory, not emitted as a guess. The four points are handled as follows. **Mixed-mode rows.** A pushed join is no longer reconstructed from the labels of `alias.*` on the joined result. Each source is probed, the prefix is re-run with those columns named explicitly, and the values are read back by ordinal onto that source's own labels. `e.name.reverse(), d.name.reverse()` therefore keeps both names. Duplicate labels within one source are rejected rather than dropped, because JDBC labels, case folding and quoting are not a stable copy of the table. The ordinal that re-aligns the join is not stored as a column, so a real column named `__ginq_mixed_key` stays readable. **Nulls.** `==` and `!=` against a null literal are still `IS NULL` / `IS NOT NULL`. Every other comparison is null-safe (`IS NOT DISTINCT FROM`, MySQL `<=>`, SQLite `IS`), so `where e.deptId == wanted` matches a null `deptId` when `wanted` is null. `!in` on a list or a constant range keeps null rows (`IS NULL OR` outside the bounds / the list). Comparisons `<` `<=` `>` `>=`, and `AND` / `OR` / `NOT`, stay SQL three-valued logic: a null is not ordered below every value the way Groovy would order it. The user guide now lists each mapping and where the semantics differ. The exact result of a mapped function still depends on the database. **`+` and text methods.** `e.name + suffix` is no longer arithmetic. `+` is concatenation only when the left side is text, or a column stands beside a string literal, and addition only when a number anchors it (`e.salary + 1`) or both sides are numbers. A captured variable is pushed only when its declared type is text or numeric, or it is cast (`(suffix as String)`, `(bonus as int)`). Two columns are not pushed. `length()` and the other text methods are pushed only for a column or a value known to be text. Otherwise strict mode rejects the construct and mixed mode evaluates it in memory. **Dialects.** Whether a function can be rendered is one table, shared by the translator and both renderers. SQLite does not include `FLOOR` or `CEILING`. Strict mode rejects those calls. Mixed mode leaves the clause that uses them in memory and can still push the rest. A function that is only spelled differently, such as `CHAR_LENGTH` as `LENGTH`, is still pushed. Adding another gap is an entry in that table, not a special case in the planner. `ntile` uses integer division, so it does not depend on `FLOOR`. -- 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]
