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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]