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

Reply via email to