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 d3286ad [CALCITE-3948] RelSubset matching is not properly handled in
VolcanoRuleCall (Botong Huang)
d3286ad is described below
commit d3286ad4725fa97aae35c70f73ab768fabd409d8
Author: botong.huang <[email protected]>
AuthorDate: Sat Apr 18 17:27:34 2020 -0700
[CALCITE-3948] RelSubset matching is not properly handled in
VolcanoRuleCall (Botong Huang)
Close #1935
---
.../org/apache/calcite/plan/volcano/RelSubset.java | 22 +++++++++++++++
.../calcite/plan/volcano/VolcanoRuleCall.java | 31 ++++++++++++++--------
2 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java
b/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java
index a48cd13..eb401d3 100644
--- a/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java
+++ b/core/src/main/java/org/apache/calcite/plan/volcano/RelSubset.java
@@ -37,6 +37,7 @@ import org.apache.calcite.util.Pair;
import org.apache.calcite.util.Util;
import org.apache.calcite.util.trace.CalciteTrace;
+import org.apiguardian.api.API;
import org.slf4j.Logger;
import java.io.PrintWriter;
@@ -53,6 +54,7 @@ import java.util.Queue;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Subset of an equivalence class where all relational expressions have the
@@ -438,6 +440,26 @@ public class RelSubset extends AbstractRelNode {
return list;
}
+ /**
+ * Returns stream of subsets whose traitset satisfies
+ * current subset's traitset.
+ */
+ @API(since = "1.23", status = API.Status.EXPERIMENTAL)
+ public Stream<RelSubset> getSubsetsSatisfyingThis() {
+ return set.subsets.stream()
+ .filter(s -> s.getTraitSet().satisfies(traitSet));
+ }
+
+ /**
+ * Returns stream of subsets whose traitset is satisfied
+ * by current subset's traitset.
+ */
+ @API(since = "1.23", status = API.Status.EXPERIMENTAL)
+ public Stream<RelSubset> getSatisfyingSubsets() {
+ return set.subsets.stream()
+ .filter(s -> traitSet.satisfies(s.getTraitSet()));
+ }
+
//~ Inner Classes ----------------------------------------------------------
/**
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 88d40cf..a099fd8 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
@@ -294,6 +294,7 @@ public class VolcanoRuleCall extends RelOptRuleCall {
final Collection<? extends RelNode> successors;
if (ascending) {
assert previousOperand.getParent() == operand;
+ assert operand.getMatchedClass() != RelSubset.class;
if (previousOperand.getMatchedClass() != RelSubset.class
&& previous instanceof RelSubset) {
throw new RuntimeException("RelSubset should not match with "
@@ -303,15 +304,17 @@ public class VolcanoRuleCall extends RelOptRuleCall {
final RelSubset subset = volcanoPlanner.getSubset(previous);
successors = subset.getParentRels();
} else {
- parentOperand = previousOperand;
- final int parentOrdinal = operand.getParent().ordinalInRule;
- final RelNode parentRel = rels[parentOrdinal];
+ parentOperand = operand.getParent();
+ final RelNode parentRel = rels[parentOperand.ordinalInRule];
final List<RelNode> inputs = parentRel.getInputs();
// if the child is unordered, then add all rels in all input subsets
to the successors list
// because unordered can match child in any ordinal
if (parentOperand.childPolicy ==
RelOptRuleOperandChildPolicy.UNORDERED) {
if (operand.getMatchedClass() == RelSubset.class) {
- successors = inputs;
+ // Find all the sibling subsets that satisfy this subset's traitSet
+ successors = inputs.stream()
+ .flatMap(subset -> ((RelSubset)
subset).getSubsetsSatisfyingThis())
+ .collect(Collectors.toList());
} else {
List<RelNode> allRelsInAllSubsets = new ArrayList<>();
Set<RelNode> duplicates = new HashSet<>();
@@ -337,10 +340,9 @@ public class VolcanoRuleCall extends RelOptRuleCall {
final RelSubset subset =
(RelSubset) inputs.get(operand.ordinalInParent);
if (operand.getMatchedClass() == RelSubset.class) {
- // Find all the sibling subsets that satisfy the traitSet of
current subset.
- successors = subset.set.subsets.stream()
- .filter(s -> s.getTraitSet().satisfies(subset.getTraitSet()))
- .collect(Collectors.toList());
+ // Find all the sibling subsets that satisfy this subset'straitSet
+ successors =
+ subset.getSubsetsSatisfyingThis().collect(Collectors.toList());
} else {
successors = subset.getRelList();
}
@@ -363,9 +365,16 @@ public class VolcanoRuleCall extends RelOptRuleCall {
}
final RelSubset input =
(RelSubset) rel.getInput(previousOperand.ordinalInParent);
- List<RelNode> inputRels = input.getRelList();
- if (!(previous instanceof RelSubset) &&
!inputRels.contains(previous)) {
- continue;
+ if (previousOperand.getMatchedClass() == RelSubset.class) {
+ // The matched subset (previous) should satisfy our input subset
(input)
+ if (input.getSubsetsSatisfyingThis().noneMatch(previous::equals)) {
+ continue;
+ }
+ } else {
+ List<RelNode> inputRels = input.getRelList();
+ if (!inputRels.contains(previous)) {
+ continue;
+ }
}
}