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

hyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new 979a825  [CALCITE-3227] IndexOutOfBound when checking candidate parent 
match's input ordinal in VolcanoRuleCall
979a825 is described below

commit 979a825fab0757c506363f5df6ed7997674e8726
Author: Botong Huang <[email protected]>
AuthorDate: Sat Aug 3 14:28:46 2019 -0700

    [CALCITE-3227] IndexOutOfBound when checking candidate parent match's input 
ordinal in VolcanoRuleCall
---
 .../calcite/plan/volcano/VolcanoRuleCall.java      |  3 ++
 .../calcite/plan/volcano/VolcanoPlannerTest.java   | 46 ++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git 
a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRuleCall.java 
b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRuleCall.java
index 45f5cfc..aff1eb4 100644
--- a/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRuleCall.java
+++ b/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRuleCall.java
@@ -333,6 +333,9 @@ public class VolcanoRuleCall extends RelOptRuleCall {
         if (ascending && operand.childPolicy != 
RelOptRuleOperandChildPolicy.UNORDERED) {
           // We know that the previous operand was *a* child of its parent,
           // but now check that it is the *correct* child.
+          if (previousOperand.ordinalInParent >= rel.getInputs().size()) {
+            continue;
+          }
           final RelSubset input =
               (RelSubset) rel.getInput(previousOperand.ordinalInParent);
           List<RelNode> inputRels = input.getRelList();
diff --git 
a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java 
b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java
index 781d4b2..47d9e50 100644
--- a/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java
+++ b/core/src/test/java/org/apache/calcite/plan/volcano/VolcanoPlannerTest.java
@@ -18,6 +18,7 @@ package org.apache.calcite.plan.volcano;
 
 import org.apache.calcite.adapter.enumerable.EnumerableConvention;
 import org.apache.calcite.adapter.enumerable.EnumerableRules;
+import org.apache.calcite.adapter.enumerable.EnumerableUnion;
 import org.apache.calcite.plan.Convention;
 import org.apache.calcite.plan.ConventionTraitDef;
 import org.apache.calcite.plan.RelOptCluster;
@@ -159,6 +160,51 @@ public class VolcanoPlannerTest {
   }
 
   /**
+   * A pattern that matches a three input union with third child matching for
+   * a PhysLeafRel node.
+   */
+  static class ThreeInputsUnionRule extends RelOptRule {
+    ThreeInputsUnionRule() {
+      super(
+          operand(EnumerableUnion.class,
+              some(
+                  operand(PhysBiRel.class, any()),
+                  operand(PhysBiRel.class, any()),
+                  operand(PhysLeafRel.class, any()))));
+    }
+
+    public void onMatch(RelOptRuleCall call) {
+    }
+  }
+
+  @Test public void testMultiInputsParentOpMatching() {
+    VolcanoPlanner planner = new VolcanoPlanner();
+    planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
+    RelOptCluster cluster = newCluster(planner);
+
+    // The trigger rule that generates PhysLeafRel from NoneLeafRel
+    planner.addRule(new PhysLeafRule());
+
+    // The rule with third child op matching PhysLeafRel, which should not be
+    // matched at all
+    planner.addRule(new ThreeInputsUnionRule());
+
+    // Construct a union with only two children
+    NoneLeafRel leftRel = new NoneLeafRel(cluster, "b");
+    RelNode leftPhy = planner
+        .changeTraits(leftRel, cluster.traitSetOf(PHYS_CALLING_CONVENTION));
+    PhysLeafRel rightPhy =
+        new PhysLeafRel(cluster, PHYS_CALLING_CONVENTION, "b");
+
+    planner.setRoot(
+        new EnumerableUnion(cluster,
+            cluster.traitSetOf(PHYS_CALLING_CONVENTION),
+            Arrays.asList(leftPhy, rightPhy), false));
+
+    planner.chooseDelegate().findBestExp();
+  }
+
+  /**
    * Tests a rule that is fired once per subset (whereas most rules are fired
    * once per rel in a set or rel in a subset)
    */

Reply via email to