[ 
https://issues.apache.org/jira/browse/CALCITE-7863?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18128528#comment-18128528
 ] 

Julian Hyde commented on CALCITE-7863:
--------------------------------------

I don't trust the javadoc. It says MIN, MAX, AVG, ANY_VALUE, but CALCITE-7493 
added support for STDDEV_POP etc.

The javadoc also says the rule eliminates "aggregate functions of GROUP BY 
keys" but in {{MIN(1)}}, 1 is not a GROUP BY key. So the javadoc (and the 
rule's name) doesn't adequately cover what the rule is trying to do.

The purpose of the rule seems to be to handle an aggregate function that is 
applied to a non-empty set of values that are all the same, and it leans 
heavily on SqlConstantValueAggFunction to do that.

This case is a major extension in functionality, to handle empty sets. Just 
adding a {{return null}} doesn't seem to be taking it seriously. Can you 
provide a serious fix, please.

> AggregateReduceFunctionsOnGroupKeysRule fails for constant aggregates on 
> empty input
> ------------------------------------------------------------------------------------
>
>                 Key: CALCITE-7863
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7863
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.42.0
>            Reporter: Zhen Chen
>            Assignee: Zhen Chen
>            Priority: Major
>              Labels: pull-request-available
>
> {{AggregateReduceFunctionsOnGroupKeysRule}} incorrectly replaces constant 
> aggregate calls with their arguments when the aggregate has no grouping keys.
> For a global aggregate, an empty input must still produce one row. {{MIN(1)}} 
> and {{MAX(1)}} must return {{NULL}} in that row. Replacing these calls with 
> the constant {{1}} does not preserve this behavior.
> The issue requires explicitly applying this rule. The query returns the 
> correct result with the default planner configuration.
> To reproduce in a Quidem test, enable this rule:
> {code:java}
> !set hep-rules "
> +CoreRules.AGGREGATE_REDUCE_FUNCTIONS_ON_GROUP_KEYS"
>  {code}
> Then execute:
> {code:java}
> SELECT
>     MIN(1) AS min_v,
>     MAX(1) AS max_v
> FROM (VALUES (7)) AS t(x)
> WHERE x < 0; {code}
> *Expected result:* One row containing two {{NULL}} values.
> {code:java}
> +-------+-------+
> | MIN_V | MAX_V |
> +-------+-------+
> |       |       |
> +-------+-------+
> (1 row) {code}
> *Actual behavior before the fix:* Query preparation fails with an 
> {{{}AssertionError{}}}:
>  
> {{java.lang.AssertionError: Cannot add expression of different type to set:
> set type is RecordType(INTEGER MIN_V, INTEGER MAX_V) NOT NULL
> expression type is RecordType(INTEGER NOT NULL MIN_V, INTEGER NOT NULL MAX_V) 
> NOT NULL
> expression is LogicalValues(tuples=[[\{ 1, 1 }]])
> Type mismatch:
> rowtype of original rel: RecordType(INTEGER MIN_V, INTEGER MAX_V) NOT NULL
> rowtype of new rel: RecordType(INTEGER NOT NULL MIN_V, INTEGER NOT NULL 
> MAX_V) NOT NULL
> Difference:
> MIN_V: INTEGER -> INTEGER NOT NULL
> MAX_V: INTEGER -> INTEGER NOT NULL}}
> The rule generates a constant row {{{}(1, 1){}}}. Its non-nullable output 
> types differ from the nullable aggregate output types, so the planner rejects 
> the transformation. The incorrect row is not returned to the user.
> *Cause and proposed fix:*
> The rule checks that an expression references only grouping keys. A literal 
> references no columns, so it passes this check even when the grouping set is 
> empty. The rule then replaces the aggregate call without accounting for 
> empty-input semantics.
> Skip aggregates with no grouping keys in this rule. Add a regression test in 
> {{hep.iq}} that explicitly enables only 
> {{AGGREGATE_REDUCE_FUNCTIONS_ON_GROUP_KEYS}} and verifies both the expected 
> {{NULL}} results and the execution plan.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to