havefunatcode opened a new pull request, #20782:
URL: https://github.com/apache/druid/pull/20782

   Fixes #18010.
   
   ### Description
   
   `APPROX_QUANTILE('m1', 0.99)`, with the column name in single quotes, is 
planned with the string literal as the aggregator input. On master, 
APPROX_QUANTILE and APPROX_QUANTILE_DS return NaN (or throw 
`ClassCastException` when vectorized), and APPROX_QUANTILE_FIXED_BUCKETS fails 
at runtime with `Only serialization version 1 is supported.`
   
   The quantile aggregators declare their first operand as `ANY`, and 
`DefaultOperandTypeChecker` doesn't check `ANY` operands at all. The fix 
follows the approach @FrankChen021 suggested in the issue.
   
   #### Opt-in options in `DefaultOperandTypeChecker`
   
   Over 50 functions use this checker, so the new behavior is opt-in through 
two builder options (also exposed on `OperatorConversions.OperatorBuilder`):
   
   - `operandComplexTypes(int, ColumnType...)`: complex types a NUMERIC operand 
also accepts, e.g. the aggregator's own sketch type.
   - `coercibleOperands(int...)`: marks a NUMERIC operand as also accepting 
STRING input. The checker adds an explicit CAST to DOUBLE, so the conversion 
shows up in the plan.
   
   For a coercible operand, a string literal that can't be parsed as a number 
is rejected before the cast is added, since the cast would turn it into null:
   
   ```
   Function [APPROX_QUANTILE] argument [column] must be numeric, got string 
literal ['m1']. If you meant to refer to a column, use double quotes.
   ```
   
   Numeric strings like `'1.5'`, STRING columns and DATETIME input such as 
`__time` still work. Parsing uses `ExprEval.computeNumber`, the same as at 
runtime, so `'true'` and `'false'` are accepted too.
   
   #### Quantile aggregators
   
   APPROX_QUANTILE, APPROX_QUANTILE_FIXED_BUCKETS, APPROX_QUANTILE_DS, 
DS_QUANTILES_SKETCH, TDIGEST_QUANTILE and TDIGEST_GENERATE_SKETCH now declare 
their first operand as a coercible NUMERIC that also accepts their own sketch 
type. These inputs are now rejected at planning time:
   
   - BOOLEAN and ARRAY
   - complex types other than the aggregator's own sketch
   - a NULL literal (`Illegal use of 'NULL'`, the same as other functions using 
the checker)
   
   The Spectator functions stay on `OperandTypes.ANY`, since their tests expect 
`SPECTATOR_COUNT(null)` to return null.
   
   #### `Aggregations`
   
   `toDruidExpressionForNumericAggregator` also rejects non-numeric string 
literals for aggregators that still declare `ANY`. 
`getArgumentsForSimpleAggregator` skips the check, because COUNT and 
SINGLE_VALUE use it and `COUNT(DISTINCT 'abc')` has to keep working.
   
   `SUM('abc')` and `AVG('abc')` still return null. Calcite coerces the literal 
to a null DECIMAL before Druid sees it. Per the issue, that's left for a 
separate PR. `numeric_agg_string_args.iq` records the current behavior.
   
   #### Release note
   
   APPROX_QUANTILE, APPROX_QUANTILE_FIXED_BUCKETS, APPROX_QUANTILE_DS, 
DS_QUANTILES_SKETCH, TDIGEST_QUANTILE and TDIGEST_GENERATE_SKETCH now check the 
type of their first argument. They fail at planning time with a 400 error if 
the first argument is a string literal that can't be parsed as a number (for 
example a column name in single quotes), a BOOLEAN, an ARRAY, an unrelated 
complex type or a NULL literal. Previously some of these returned NaN or failed 
at runtime.
   
   <hr>
   
   ##### Key changed/added classes in this PR
    * `DefaultOperandTypeChecker`
    * `OperatorConversions`
    * `DruidTypeCoercion`
    * `Calcites`
    * `Aggregations`
    * `QuantileSqlAggregator`, `FixedBucketsHistogramQuantileSqlAggregator`, 
`DoublesSketchApproxQuantileSqlAggregator`, `DoublesSketchObjectSqlAggregator`, 
`TDigestSketchQuantileSqlAggregator`, `TDigestGenerateSketchSqlAggregator`
   
   <hr>
   
   This PR has:
   
   - [x] been self-reviewed.
   - [x] a release note entry in the PR description.
   - [x] added Javadocs for most classes and all non-trivial methods. Linked 
related entities via Javadoc links.
   - [x] added comments explaining the "why" and the intent of the code 
wherever would not be obvious for an unfamiliar reader.
   - [x] added unit tests or modified existing tests to cover new code paths, 
ensuring the threshold for [code 
coverage](https://github.com/apache/druid/blob/master/dev/code-review/code-coverage.md)
 is met.
   


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