This is an automated email from the ASF dual-hosted git repository. tjbanghart pushed a commit to branch tjbanghart/CALCITE-5846 in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 6206abec75a5014810bd1511c34a3cf400b54113 Author: TJ Banghart <[email protected]> AuthorDate: Fri Nov 10 15:59:32 2023 -0800 [CALCITE-5846] Preserve filters on non-distinct aggCalls in AggregateExpandWithinDistinctRule --- .../rules/AggregateExpandWithinDistinctRule.java | 7 ++++-- .../org/apache/calcite/test/RelOptRulesTest.java | 20 ++++++++++++++++ .../org/apache/calcite/test/RelOptRulesTest.xml | 27 ++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java index 8d2fa99621..cf5aafca48 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateExpandWithinDistinctRule.java @@ -345,9 +345,12 @@ public class AggregateExpandWithinDistinctRule final Registrar registrar = new Registrar(); Ord.forEach(aggCallList, (c, i) -> { if (c.distinctKeys == null) { + RelBuilder.AggCall aggCall = + b.aggregateCall(c.getAggregation(), b.fields(c.getArgList())); registrar.registerAgg(i, - b.aggregateCall(c.getAggregation(), - b.fields(c.getArgList()))); + c.hasFilter() + ? aggCall.filter(b.field(c.filterArg)) + : aggCall); } else { for (int inputIdx : c.getArgList()) { registrar.register(inputIdx, c.filterArg); diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java index 9b5f3a75b8..eb8b70010d 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -2263,6 +2263,26 @@ class RelOptRulesTest extends RelOptTestBase { sql(sql).withProgram(program).check(); } + /** Test case for + * <a href="https://issues.apache.org/jira/browse/CALCITE-5846">[CALCITE-5846] + * Preserve FILTER clause for non-distinct aggregate calls with + * AggregateExpandWithinDistinctRule</a>. + * + * <p>Tests {@link AggregateExpandWithinDistinctRule} with a non-distinct aggregate with a FILTER + * clause and a distinct aggregate in the same query. */ + @Test void testWithinDistinctPreservesNonDistinctAggFilters() { + final String sql = "SELECT deptno,\n" + + " SUM(sal) FILTER (WHERE sal > 1000),\n" + + " SUM(sal) WITHIN DISTINCT (job)\n" + + "FROM emp\n" + + "GROUP BY deptno"; + HepProgram program = new HepProgramBuilder() + .addRuleInstance(CoreRules.AGGREGATE_REDUCE_FUNCTIONS) + .addRuleInstance(CoreRules.AGGREGATE_EXPAND_WITHIN_DISTINCT) + .build(); + sql(sql).withProgram(program).check(); + } + /** Tests {@link AggregateExpandWithinDistinctRule}. Includes multiple * different filters for the aggregate calls, and all aggregate calls have the * same distinct keys, so there is no need to filter based on diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml index 0bfe265d30..87b2c2fdce 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -16303,6 +16303,33 @@ LogicalProject(DEPTNO=[$0], $f1=[CAST($1):INTEGER NOT NULL], $f2=[$2]) LogicalAggregate(group=[{0, 2}], groups=[[{0, 2}, {0}]], agg#0=[$SUM0($1)], agg#1=[MIN($1)], agg#2=[GROUPING($0, $2)]) LogicalProject(DEPTNO=[$7], SAL=[$5], JOB=[$2]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + </TestCase> + <TestCase name="testWithinDistinctPreservesNonDistinctAggFilters"> + <Resource name="sql"> + <![CDATA[SELECT deptno, + SUM(sal) FILTER (WHERE sal > 1000), + SUM(sal) WITHIN DISTINCT (job) +FROM emp +GROUP BY deptno]]> + </Resource> + <Resource name="planBefore"> + <![CDATA[ +LogicalAggregate(group=[{0}], EXPR$1=[SUM($1) FILTER $2], EXPR$2=[SUM($1) WITHIN DISTINCT ($3)]) + LogicalProject(DEPTNO=[$7], SAL=[$5], $f2=[>($5, 1000)], JOB=[$2]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + <Resource name="planAfter"> + <![CDATA[ +LogicalProject(DEPTNO=[$0], EXPR$1=[CASE(=($2, 0), null:INTEGER, $1)], EXPR$2=[$3]) + LogicalProject(DEPTNO=[$0], $f1=[CAST($1):INTEGER NOT NULL], $f2=[CAST($2):BIGINT NOT NULL], $f3=[$3]) + LogicalAggregate(group=[{0}], agg#0=[MIN($1) FILTER $4], agg#1=[MIN($2) FILTER $4], agg#2=[$SUM0($3) FILTER $5]) + LogicalProject(DEPTNO=[$0], $f2=[$2], $f3=[$3], $f4=[$4], $f7=[=($6, 1)], $f8=[AND(=($6, 0), $THROW_UNLESS(OR(<>($6, 0), =($4, $5)), 'more than one distinct value in agg UNIQUE_VALUE'))]) + LogicalAggregate(group=[{0, 3}], groups=[[{0, 3}, {0}]], agg#0=[$SUM0($1) FILTER $2], agg#1=[COUNT() FILTER $2], agg#2=[MIN($1)], agg#3=[MAX($1)], agg#4=[GROUPING($0, $3)]) + LogicalProject(DEPTNO=[$7], SAL=[$5], $f2=[>($5, 1000)], JOB=[$2]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> </Resource> </TestCase>
