This is an automated email from the ASF dual-hosted git repository.

rongr 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 86735ce1cc [multistage][bugfix] eliminate multiple exchanges (#11882)
86735ce1cc is described below

commit 86735ce1cc6eca1d988e0c950f313b51b541fa02
Author: Rong Rong <[email protected]>
AuthorDate: Mon Oct 30 08:03:38 2023 -0700

    [multistage][bugfix] eliminate multiple exchanges (#11882)
    
    * [bugfix] eliminate multiple exchanges
    
    ---------
    
    Co-authored-by: Rong Rong <[email protected]>
---
 .../rel/rules/PinotExchangeEliminationRule.java    | 52 ++++++++++++++++++++++
 .../calcite/rel/rules/PinotQueryRuleSets.java      |  5 ++-
 .../src/test/resources/queries/JoinPlans.json      | 21 +++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)

diff --git 
a/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotExchangeEliminationRule.java
 
b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotExchangeEliminationRule.java
new file mode 100644
index 0000000000..308eb83e62
--- /dev/null
+++ 
b/pinot-query-planner/src/main/java/org/apache/calcite/rel/rules/PinotExchangeEliminationRule.java
@@ -0,0 +1,52 @@
+/**
+ * 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 java.util.Collections;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.logical.PinotLogicalExchange;
+import org.apache.calcite.tools.RelBuilderFactory;
+
+
+/**
+ * Special rule for Pinot, this rule eliminates {@link PinotLogicalExchange} 
when {@link RelDistribution} traits
+ * are the same at this exchange node and at the node prior to this exchange 
node.
+ */
+public class PinotExchangeEliminationRule extends RelOptRule {
+  public static final PinotExchangeEliminationRule INSTANCE =
+      new PinotExchangeEliminationRule(PinotRuleUtils.PINOT_REL_FACTORY);
+
+  public PinotExchangeEliminationRule(RelBuilderFactory factory) {
+    super(operand(PinotLogicalExchange.class,
+        some(operand(PinotLogicalExchange.class, some(operand(RelNode.class, 
any()))))), factory, null);
+  }
+
+  @Override
+  public void onMatch(RelOptRuleCall call) {
+    PinotLogicalExchange exchange0 = call.rel(0);
+    PinotLogicalExchange exchange1 = call.rel(1);
+    RelNode input = call.rel(2);
+    // convert the call to skip the exchange.
+    RelNode rel = exchange0.copy(input.getTraitSet(), 
Collections.singletonList(input));
+    call.transformTo(rel);
+  }
+}
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 581fd7e8e5..ff3aca3012 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
@@ -134,6 +134,9 @@ public class PinotQueryRuleSets {
       PinotSetOpExchangeNodeInsertRule.INSTANCE,
 
       // apply dynamic broadcast rule after exchange is inserted/
-      PinotJoinToDynamicBroadcastRule.INSTANCE
+      PinotJoinToDynamicBroadcastRule.INSTANCE,
+
+      // remove exchanges when there's duplicates
+      PinotExchangeEliminationRule.INSTANCE
   );
 }
diff --git a/pinot-query-planner/src/test/resources/queries/JoinPlans.json 
b/pinot-query-planner/src/test/resources/queries/JoinPlans.json
index b3c1504565..6f655ec6e4 100644
--- a/pinot-query-planner/src/test/resources/queries/JoinPlans.json
+++ b/pinot-query-planner/src/test/resources/queries/JoinPlans.json
@@ -421,6 +421,27 @@
           "\n              LogicalTableScan(table=[[b]])",
           "\n"
         ]
+      },
+      {
+        "description": "nexted reused tmp table SEMI JOINs",
+        "sql": "EXPLAIN PLAN FOR WITH tmp1 AS ( SELECT * FROM a WHERE col2 NOT 
IN ('foo', 'bar') ), tmp2 AS ( SELECT * FROM b WHERE col1 IN (SELECT col1 FROM 
tmp1) AND col3 < 100 ) SELECT * FROM tmp2 WHERE col3 IN (SELECT col3 from 
tmp1)",
+        "output": [
+          "Execution Plan",
+          "\nLogicalJoin(condition=[=($2, $8)], joinType=[semi])",
+          "\n  PinotLogicalExchange(distribution=[hash[2]])",
+          "\n    LogicalJoin(condition=[=($0, $7)], joinType=[semi])",
+          "\n      LogicalFilter(condition=[<($2, 100)])",
+          "\n        LogicalTableScan(table=[[b]])",
+          "\n      PinotLogicalExchange(distribution=[broadcast], 
relExchangeType=[PIPELINE_BREAKER])",
+          "\n        LogicalProject(col1=[$0], col2=[$1])",
+          "\n          LogicalFilter(condition=[AND(<>($1, 'bar'), <>($1, 
'foo'))])",
+          "\n            LogicalTableScan(table=[[a]])",
+          "\n  PinotLogicalExchange(distribution=[hash[1]])",
+          "\n    LogicalProject(col2=[$1], col3=[$2])",
+          "\n      LogicalFilter(condition=[AND(<>($1, 'bar'), <>($1, 
'foo'))])",
+          "\n        LogicalTableScan(table=[[a]])",
+          "\n"
+        ]
       }
     ]
   },


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to