Skip to content

Commit 1d4b1fd

Browse files
committed
[CALCITE-7030] Enhance TopologicalOrderIterator to support BOTTOM_UP
1 parent 60e1b72 commit 1d4b1fd

File tree

4 files changed

+80
-36
lines changed

4 files changed

+80
-36
lines changed

core/src/main/java/org/apache/calcite/plan/hep/HepPlanner.java

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
import java.util.ArrayDeque;
5959
import java.util.ArrayList;
6060
import java.util.Collection;
61-
import java.util.Collections;
6261
import java.util.HashMap;
6362
import java.util.HashSet;
6463
import java.util.Iterator;
@@ -467,30 +466,16 @@ private Iterator<HepRelVertex> getGraphIterator(
467466
return DepthFirstIterator.of(graph, start).iterator();
468467

469468
case TOP_DOWN:
470-
assert start == root;
471-
// see above
472-
/*
473-
collectGarbage();
474-
*/
475-
return TopologicalOrderIterator.of(graph).iterator();
476-
477469
case BOTTOM_UP:
478-
default:
479470
assert start == root;
480-
481471
// see above
482472
/*
483473
collectGarbage();
484474
*/
485-
486-
// TODO jvs 4-Apr-2006: enhance TopologicalOrderIterator
487-
// to support reverse walk.
488-
final List<HepRelVertex> list = new ArrayList<>();
489-
for (HepRelVertex vertex : TopologicalOrderIterator.of(graph)) {
490-
list.add(vertex);
491-
}
492-
Collections.reverse(list);
493-
return list.iterator();
475+
return TopologicalOrderIterator.of(graph, programState.matchOrder).iterator();
476+
default:
477+
throw new
478+
UnsupportedOperationException("Unsupported match order: " + programState.matchOrder);
494479
}
495480
}
496481

core/src/main/java/org/apache/calcite/util/graph/DefaultDirectedGraph.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public static <V, E extends DefaultEdge> DefaultDirectedGraph<V, E> create(
6161
return new DefaultDirectedGraph<>(edgeFactory);
6262
}
6363

64+
@Deprecated
6465
public String toStringUnordered() {
6566
return "graph("
6667
+ "vertices: " + vertexMap.keySet()

core/src/main/java/org/apache/calcite/util/graph/TopologicalOrderIterator.java

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package org.apache.calcite.util.graph;
1818

19+
import org.apache.calcite.plan.hep.HepMatchOrder;
20+
1921
import org.checkerframework.checker.initialization.qual.UnderInitialization;
2022
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
2123

@@ -38,10 +40,17 @@ public class TopologicalOrderIterator<V, E extends DefaultEdge>
3840
implements Iterator<V> {
3941
final Map<V, int[]> countMap = new HashMap<>();
4042
final List<V> empties = new ArrayList<>();
43+
final HepMatchOrder hepMatchOrder;
4144
private final DefaultDirectedGraph<V, E> graph;
4245

4346
public TopologicalOrderIterator(DirectedGraph<V, E> graph) {
47+
this(graph, HepMatchOrder.TOP_DOWN);
48+
}
49+
50+
public TopologicalOrderIterator(DirectedGraph<V, E> graph, HepMatchOrder hepMatchOrder) {
51+
assert hepMatchOrder == HepMatchOrder.TOP_DOWN || hepMatchOrder == HepMatchOrder.BOTTOM_UP;
4452
this.graph = (DefaultDirectedGraph<V, E>) graph;
53+
this.hepMatchOrder = hepMatchOrder;
4554
populate(countMap, empties);
4655
}
4756

@@ -50,21 +59,40 @@ public static <V, E extends DefaultEdge> Iterable<V> of(
5059
return () -> new TopologicalOrderIterator<>(graph);
5160
}
5261

62+
public static <V, E extends DefaultEdge> Iterable<V> of(
63+
final DirectedGraph<V, E> graph, HepMatchOrder hepMatchOrder) {
64+
return () -> new TopologicalOrderIterator<>(graph, hepMatchOrder);
65+
}
66+
5367
@RequiresNonNull("graph")
5468
private void populate(
5569
@UnderInitialization TopologicalOrderIterator<V, E> this,
5670
Map<V, int[]> countMap, List<V> empties) {
5771
for (V v : graph.vertexMap.keySet()) {
5872
countMap.put(v, new int[] {0});
5973
}
60-
for (DefaultDirectedGraph.VertexInfo<V, E> info
61-
: graph.vertexMap.values()) {
62-
for (E edge : info.outEdges) {
63-
//noinspection SuspiciousMethodCalls
64-
final int[] ints =
65-
requireNonNull(countMap.get(edge.target),
66-
() -> "no value for " + edge.target);
67-
++ints[0];
74+
if (hepMatchOrder == HepMatchOrder.TOP_DOWN) {
75+
for (DefaultDirectedGraph.VertexInfo<V, E> info
76+
: graph.vertexMap.values()) {
77+
for (E edge : info.outEdges) {
78+
//noinspection SuspiciousMethodCalls
79+
final int[] ints =
80+
requireNonNull(countMap.get(edge.target),
81+
() -> "no value for " + edge.target);
82+
++ints[0];
83+
}
84+
}
85+
}
86+
if (hepMatchOrder == HepMatchOrder.BOTTOM_UP) {
87+
for (DefaultDirectedGraph.VertexInfo<V, E> info
88+
: graph.vertexMap.values()) {
89+
for (E edge : info.outEdges) {
90+
//noinspection SuspiciousMethodCalls
91+
final int[] ints =
92+
requireNonNull(countMap.get(edge.source),
93+
() -> "no value for " + edge.source);
94+
++ints[0];
95+
}
6896
}
6997
}
7098
for (Map.Entry<V, int[]> entry : countMap.entrySet()) {
@@ -84,15 +112,30 @@ private void populate(
84112
DefaultDirectedGraph.VertexInfo<V, E> vertexInfo =
85113
requireNonNull(graph.vertexMap.get(v),
86114
() -> "no vertex " + v);
87-
for (E o : vertexInfo.outEdges) {
88-
//noinspection unchecked
89-
final V target = (V) o.target;
90-
int[] ints =
91-
requireNonNull(countMap.get(target),
92-
() -> "no counts found for target " + target);
93-
if (--ints[0] == 0) {
94-
countMap.remove(target);
95-
empties.add(target);
115+
if (hepMatchOrder == HepMatchOrder.TOP_DOWN) {
116+
for (E o : vertexInfo.outEdges) {
117+
//noinspection unchecked
118+
final V target = (V) o.target;
119+
int[] ints =
120+
requireNonNull(countMap.get(target),
121+
() -> "no counts found for target " + target);
122+
if (--ints[0] == 0) {
123+
countMap.remove(target);
124+
empties.add(target);
125+
}
126+
}
127+
}
128+
if (hepMatchOrder == HepMatchOrder.BOTTOM_UP) {
129+
for (E o : vertexInfo.inEdges) {
130+
//noinspection unchecked
131+
final V source = (V) o.source;
132+
int[] ints =
133+
requireNonNull(countMap.get(source),
134+
() -> "no counts found for source " + source);
135+
if (--ints[0] == 0) {
136+
countMap.remove(source);
137+
empties.add(source);
138+
}
96139
}
97140
}
98141
return v;

core/src/test/java/org/apache/calcite/util/graph/DirectedGraphTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
* limitations under the License.
1616
*/
1717
package org.apache.calcite.util.graph;
18+
import org.apache.calcite.plan.hep.HepMatchOrder;
19+
1820
import com.google.common.collect.ImmutableList;
1921
import com.google.common.collect.ImmutableSet;
2022
import com.google.common.collect.Lists;
@@ -172,6 +174,19 @@ private <V> List<List<V>> paths(DirectedGraph<V, DefaultEdge> g,
172174
assertThat(list, hasToString("[A, B, E, C, F, D]"));
173175
}
174176

177+
/**
178+
* Test case for
179+
* <a href="https://issues.apache.org/jira/browse/CALCITE-7030">[CALCITE-7030]
180+
* Enhance TopologicalOrderIterator to support BOTTOM_UP</a>. */
181+
@Test void testTopologicalOrderWithBottomUpIterator() {
182+
final DefaultDirectedGraph<String, DefaultEdge> graph = createDag();
183+
final List<String> list = new ArrayList<>();
184+
for (String s : TopologicalOrderIterator.of(graph, HepMatchOrder.BOTTOM_UP)) {
185+
list.add(s);
186+
}
187+
assertThat(list, hasToString("[D, F, C, B, E, A]"));
188+
}
189+
175190
private DefaultDirectedGraph<String, DefaultEdge> createDag() {
176191
// D F
177192
// ^ ^

0 commit comments

Comments
 (0)