[
https://issues.apache.org/jira/browse/CALCITE-7863?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18128452#comment-18128452
]
Zhen Chen commented on CALCITE-7863:
------------------------------------
[~julianhyde] Thanks for your reply! As noted in this rule's Javadoc, the
rewrite currently only supports the MIN, MAX, AVG, and ANY_VALUE aggregate
functions. Under the current logic, aggregate functions with constant
arguments, such as MIN(1), MAX(1), AVG(1), and ANY_VALUE(1), also satisfy the
expression checks. However, based on my current understanding,
{{AggregateMinMaxToLimitRule}} can rewrite {{MIN(1)}} and {{{}MAX(1){}}}, and
it handles the current scenario correctly. I haven't found any similar issues
in the other rules so far.
> 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)