mrhhsg opened a new pull request, #68503:
URL: https://github.com/apache/doris/pull/68503
### What problem does this PR solve?
Issue Number: None
Related PR: #58200
Problem Summary:
`ntile(1 + 1) OVER (ORDER BY k)` was rejected at analysis time, although
the bucket is a constant expression that folds to `2`:
```
mysql> SELECT ntile(1 + 1) OVER (ORDER BY k) AS bucket
-> FROM (SELECT 1 AS k UNION ALL SELECT 2 UNION ALL SELECT 3) t;
ERROR 1105 (HY000): errCode = 2, detailMessage = The bucket parameter of
NTILE
must be a constant positive integer: ntile((1 + 1))
```
LAG/LEAD (#58200) and NTH_VALUE already accept such expressions, because
their literal checks run after constant folding.
Root cause: `Ntile.checkLegalityBeforeTypeCoercion` runs while the function
is being bound in the analyzer, before `FoldConstant` has turned `1 + 1`
into a literal, and it required the argument to already be a `Literal`.
Every non-literal constant expression therefore failed the check.
Fix: keep the integral-type, LARGEINT and constant checks as they are, then
fold the bucket with `FoldConstantRuleOnFE.evaluateWithoutContext` (the
pattern already used by `Stack`) and require the folded value to be an
integer literal greater than zero. Constant expressions such as `1 + 1`,
`cast(5 - 2 as bigint)` or `abs(-3)` are now accepted, while `0`, `1 - 1`,
`1 - 2`, a NULL result such as `cast('abc' as int)`, a non-constant column
and a LARGEINT bucket are still rejected with the existing error messages.
The backend registers `ntile` only for a non-nullable integer argument and
reads the bucket count from the argument column, so the bucket must still be
a literal when the plan is translated. A `checkLegalityAfterRewrite` is added
that requires a positive integer literal after rewrite (the same approach LAG
and LEAD use). When constant folding is skipped with
`debug_skip_fold_constant=true`, an unfolded expression such as
`cast('3' as int)` is now rejected with the NTILE message instead of failing
in the backend with `Agg Function ntile(int) is not implemented`.
After the fix the query above returns `1, 1, 2`.
### Release note
None
### Check List (For Author)
- Test:
- Unit Test: `NtileBucketTest` covers a literal bucket, foldable
constant expressions, expressions folded to zero/negative/NULL,
non-constant, non-integral and LARGEINT buckets, and the
after-rewrite check for literal and unfolded buckets.
- Regression test: `test_ntile_function` adds `ntile(1 + 1)`,
`ntile(cast(5 - 2 as bigint))`, `ntile(abs(-3))` with generated
output, error cases for `ntile(1 - 1)`, `ntile(1 - 2)` and
`ntile(cast('abc' as int))`, and cases with
`debug_skip_fold_constant=true`.
- Behavior changed: Yes (NTILE now accepts a constant bucket expression
that folds to a positive integer; such queries previously failed)
- Does this need documentation: No
--
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]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]