Skip to content

Commit

Permalink
[CALCITE-5832] Avoid cycle in relational nodes.
Browse files Browse the repository at this point in the history
  • Loading branch information
kramerul committed Dec 13, 2023
1 parent a6729b7 commit 5cbd2dd
Showing 1 changed file with 44 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,7 @@

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -1107,13 +1097,17 @@ private boolean fixUpInputs(RelNode rel) {
assert input instanceof RelSubset;
final RelSubset subset = (RelSubset) input;
RelSubset newSubset = canonize(subset);
newInputs.add(newSubset);
if (newSubset != subset) {
if (subset.set != newSubset.set) {
subset.set.parents.remove(rel);
newSubset.set.parents.add(rel);
if (hasCycle(rel,newSubset)) {
newInputs.add(input);
} else {
newInputs.add(newSubset);
if (newSubset != subset) {
if (subset.set != newSubset.set) {
subset.set.parents.remove(rel);
newSubset.set.parents.add(rel);
}
changeCount++;
}
changeCount++;
}
}

Expand All @@ -1122,14 +1116,46 @@ private boolean fixUpInputs(RelNode rel) {
RelNode removed = mapDigestToRel.remove(rel.getRelDigest());
assert removed == rel;
for (int i = 0; i < inputs.size(); i++) {
rel.replaceInput(i, newInputs.get(i));
RelNode newInput = newInputs.get(i);
rel.replaceInput(i, newInput);
}
rel.recomputeDigest();
return true;
}
return false;
}

private boolean hasCycle(RelNode rel, RelNode newInput) {
Stack<Integer> visited = new Stack<>();
visited.push(rel.getId());
return hasCycle(newInput,visited);
}

private boolean hasCycle(RelNode node, Stack<Integer> visited) {
if (node instanceof RelSubset) {
RelSubset subset = (RelSubset) node;
node = subset.getBestOrOriginal();
}
if ( visited.contains(node.getId()) ) {
return true;
}
try {
visited.push(node.getId());
List<RelNode> inputs = node.getInputs();
for (RelNode input : inputs) {
boolean cycle = hasCycle(input, visited);
if ( cycle) {
return true;
}
}
} finally {
visited.pop();
}
return false;
}



private RelSet merge(RelSet set1, RelSet set2) {
assert set1 != set2 : "pre: set1 != set2";

Expand Down

0 comments on commit 5cbd2dd

Please sign in to comment.