Zhen Chen created CALCITE-7863:
----------------------------------
Summary: 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
{{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)