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)
*/