This is an automated email from the ASF dual-hosted git repository. xiangfu pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push: new 1c61e4cebf Adding rule to skip SINGLE_VALUE agg function (#11383) 1c61e4cebf is described below commit 1c61e4cebf29920677680277d05a562621e8e2d0 Author: Xiang Fu <xiangfu.1...@gmail.com> AuthorDate: Fri Aug 18 16:44:50 2023 -0700 Adding rule to skip SINGLE_VALUE agg function (#11383) --- .../tests/MultiStageEngineIntegrationTest.java | 15 ++++++ .../calcite/rel/rules/PinotQueryRuleSets.java | 1 + .../rules/PinotSingleValueAggregateRemoveRule.java | 59 ++++++++++++++++++++++ .../src/test/resources/queries/AggregatePlans.json | 22 ++++++++ 4 files changed, 97 insertions(+) diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java index e4d149a547..e3dcbdcfe9 100644 --- a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java +++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/MultiStageEngineIntegrationTest.java @@ -101,6 +101,21 @@ public class MultiStageEngineIntegrationTest extends BaseClusterIntegrationTestS super.testHardcodedQueries(); } + @Test + public void testSingleValueQuery() + throws Exception { + String query = "select sum(ActualElapsedTime) from mytable WHERE ActualElapsedTime > " + + "(select avg(ActualElapsedTime) as avg_profit from mytable)"; + JsonNode jsonNode = postQuery(query); + long joinResult = jsonNode.get("resultTable").get("rows").get(0).get(0).asLong(); + + // The query of `SELECT avg(ActualElapsedTime) FROM mytable` is -1412.435033969449 + query = "select sum(ActualElapsedTime) as profit from mytable WHERE ActualElapsedTime > -1412.435033969449"; + jsonNode = postQuery(query); + long expectedResult = jsonNode.get("resultTable").get("rows").get(0).get(0).asLong(); + assertEquals(joinResult, expectedResult); + } + @Test @Override public void testGeneratedQueries() diff --git a/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotQueryRuleSets.java b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotQueryRuleSets.java index 34fe035212..31edc5a58f 100644 --- a/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotQueryRuleSets.java +++ b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotQueryRuleSets.java @@ -124,6 +124,7 @@ public class PinotQueryRuleSets { // copy exchanges down, this must be done after SortExchangeNodeInsertRule PinotSortExchangeCopyRule.SORT_EXCHANGE_COPY, + PinotSingleValueAggregateRemoveRule.INSTANCE, PinotJoinExchangeNodeInsertRule.INSTANCE, PinotAggregateExchangeNodeInsertRule.INSTANCE, PinotWindowExchangeNodeInsertRule.INSTANCE, diff --git a/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotSingleValueAggregateRemoveRule.java b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotSingleValueAggregateRemoveRule.java new file mode 100644 index 0000000000..0fe1cb10b4 --- /dev/null +++ b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotSingleValueAggregateRemoveRule.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.calcite.rel.rules; + +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.hep.HepRelVertex; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.Aggregate; +import org.apache.calcite.rel.core.AggregateCall; +import org.apache.calcite.rel.logical.LogicalAggregate; +import org.apache.calcite.tools.RelBuilderFactory; + + +/** + * SingleValueAggregateRemoveRule that matches an Aggregate function SINGLE_VALUE and remove it + * + */ +public class PinotSingleValueAggregateRemoveRule extends RelOptRule { + public static final PinotSingleValueAggregateRemoveRule INSTANCE = + new PinotSingleValueAggregateRemoveRule(PinotRuleUtils.PINOT_REL_FACTORY); + + public PinotSingleValueAggregateRemoveRule(RelBuilderFactory factory) { + super(operand(LogicalAggregate.class, any()), factory, null); + } + + @Override + public boolean matches(RelOptRuleCall call) { + final Aggregate agg = call.rel(0); + if (agg.getAggCallList().size() != 1) { + return false; + } + final AggregateCall aggCall = agg.getAggCallList().get(0); + return aggCall.getAggregation().getName().equals("SINGLE_VALUE"); + } + + @Override + public void onMatch(RelOptRuleCall call) { + final Aggregate agg = call.rel(0); + final RelNode input = ((HepRelVertex) agg.getInput()).getCurrentRel(); + call.transformTo(input); + } +} diff --git a/pinot-query-planner/src/test/resources/queries/AggregatePlans.json b/pinot-query-planner/src/test/resources/queries/AggregatePlans.json index 78445e79c1..c93e8d6138 100644 --- a/pinot-query-planner/src/test/resources/queries/AggregatePlans.json +++ b/pinot-query-planner/src/test/resources/queries/AggregatePlans.json @@ -1,6 +1,28 @@ { "aggregates_planning_tests": { "queries": [ + { + "description": "Select AVG aggregation for a BIG_DECIMAL column, TODO:(No need to cast in LogicalProject)", + "sql": "EXPLAIN PLAN FOR SELECT AVG(a.col4) as avg FROM a WHERE a.col3 >= (SELECT AVG(a.col4) FROM a)", + "output": [ + "Execution Plan", + "\nLogicalProject(avg=[CAST(/(CASE(=($1, 0), null:DECIMAL(1000, 0), $0), $1)):DECIMAL(1000, 0)])", + "\n LogicalAggregate(group=[{}], agg#0=[$SUM0($0)], agg#1=[COUNT($1)])", + "\n PinotLogicalExchange(distribution=[hash])", + "\n LogicalAggregate(group=[{}], agg#0=[$SUM0($1)], agg#1=[COUNT()])", + "\n LogicalJoin(condition=[>=($0, $2)], joinType=[inner])", + "\n PinotLogicalExchange(distribution=[random])", + "\n LogicalProject(col3=[$2], col4=[$3])", + "\n LogicalTableScan(table=[[a]])", + "\n PinotLogicalExchange(distribution=[broadcast])", + "\n LogicalProject(EXPR$0=[CAST(/(CASE(=($1, 0), null:DECIMAL(1000, 0), $0), $1)):DECIMAL(1000, 0)])", + "\n LogicalAggregate(group=[{}], agg#0=[$SUM0($0)], agg#1=[COUNT($1)])", + "\n PinotLogicalExchange(distribution=[hash])", + "\n LogicalAggregate(group=[{}], agg#0=[$SUM0($3)], agg#1=[COUNT()])", + "\n LogicalTableScan(table=[[a]])", + "\n" + ] + }, { "description": "Select AVG aggregation for a BIG_DECIMAL column, TODO:(No need to cast in LogicalProject)", "sql": "EXPLAIN PLAN FOR SELECT AVG(a.col4) as avg FROM a WHERE a.col3 >= 0 AND a.col2 = 'pink floyd'", --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org