mrhhsg commented on code in PR #68488:
URL: https://github.com/apache/doris/pull/68488#discussion_r4101534642


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java:
##########
@@ -67,21 +70,42 @@ private PercentileReservoir(NullableAggregateFunctionParams 
functionParams) {
 
     @Override
     public void checkLegalityBeforeTypeCoercion() {
+        checkLevel();
+    }
+
+    @Override
+    public void checkLegalityAfterRewrite() {
+        checkLevel();
+    }
+
+    /**
+     * The level must be a constant that folds to a literal in [0, 1]. It is 
folded here instead of
+     * waiting for the rewrite phase because a constant expression such as 
0.25 + 0.25 is only a
+     * literal after folding, some plans (INSERT ... VALUES, load column 
mappings) never run the
+     * rewrite phase, and constant folding can be turned off by 
debug_skip_fold_constant.
+     * The level is brought to DOUBLE with the same implicit cast that 
signature coercion applies,
+     * so a level that is not a valid DOUBLE behaves like the coerced 
expression: NULL under the
+     * default non-strict cast and an error under strict cast, for '' as well 
as cast('' as double).
+     */
+    private void checkLevel() {
         Expression levelArgument = getArgument(1);
-        if (!levelArgument.isConstant()) {
+        Expression level = levelArgument.isConstant()
+                ? FoldConstantRuleOnFE.evaluateWithoutContext(

Review Comment:
   Fixed in 0a52f070b84. The root cause was the FE string -> FLOAT/DOUBLE fold, 
so I fixed the fold itself instead of special-casing the level check. 
`StringLikeLiteral.castToFloat/castToDouble` now parse the same grammar as BE's 
`StringParser::string_to_float` (fast_float):
   
   - The NaN payload form `nan(n-char-seq)` (letters, digits, `_`) is accepted, 
case-insensitive and with an optional sign, as in fast_float's `parse_infnan`. 
`cast('nan(foo)' as double)` now folds to NaN, not NULL.
   - `String.trim()` is gone. The regex captures the number between `\s*` runs. 
Java's `\s` is exactly BE's `is_whitespace_ascii` set (space, `\t`, `\n`, `\v`, 
`\f`, `\r`), so a value with another control character, such as `'0.25'` plus a 
`\x01` byte, now fails on FE as it does on BE. That means NULL under non-strict 
cast and an error under strict cast.
   
   `checkLevel()` therefore sees NaN for `'nan(foo)'` and rejects it with 
`level must be in [0, 1], but got NaN` in both cast modes. The level it 
validates is the value BE executes on the skip-fold and DISTINCT paths.
   
   Coverage:
   - `StringLikeLiteralTest` checks both targets, FLOAT and DOUBLE:
     - `nan(foo)`, ` -NaN(ind_1) ` and `+nan()` all become NaN.
     - All six ASCII whitespace characters around `0.25` are skipped.
     - `nan(foo`, `nan(a-b)`, `nan)`, `0.25\u0001`, `\u00010.25`, `1.5d` and 
`0x10` all fail.
   - `PercentileReservoirParameterTest.testNanPayloadStringLevelIsRejected` 
covers `'nan(foo)'` and `cast(' -nan(ind) ' as double)` × 
plain/`_state`/`_combine` × both hooks, under strict and non-strict cast.
   - Regression:
     - `qt_nan_payload_cast` (FE fold) and `qt_skip_fold_nan_payload_cast` (BE 
evaluation) both return `NaN NaN \N`.
     - Plain, DISTINCT and `_state` aggregates with both level forms are 
rejected, with and without `debug_skip_fold_constant`.
   



-- 
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]

Reply via email to