You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "ASF GitHub Bot (Jira)" <ji...@apache.org> on 2026/10/16 15:53:00 UTC
[jira] [Updated] (CALCITE-7863) AggregateReduceFunctionsOnGroupKeysRule fails for constant aggregates on empty input
[ https://issues.apache.org/jira/browse/CALCITE-7863?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
ASF GitHub Bot updated CALCITE-7863:
------------------------------------
Labels: pull-request-available (was: )
> 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)