[feature](Nereids): add rule for matching plan into HyperGraph. (#13805)
This commit is contained in:
@ -33,7 +33,7 @@ import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.processor.post.PlanPostProcessors;
|
||||
import org.apache.doris.nereids.processor.pre.PlanPreprocessors;
|
||||
import org.apache.doris.nereids.properties.PhysicalProperties;
|
||||
import org.apache.doris.nereids.rules.exploration.join.JoinReorderRule;
|
||||
import org.apache.doris.nereids.rules.joinreorder.HyperGraphJoinReorder;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
|
||||
@ -173,7 +173,7 @@ public class NereidsPlanner extends Planner {
|
||||
private void joinReorder() {
|
||||
new RewriteTopDownJob(
|
||||
getRoot(),
|
||||
(new JoinReorderRule()).buildRules(),
|
||||
(new HyperGraphJoinReorder()).buildRules(),
|
||||
cascadesContext.getCurrentJobContext()
|
||||
).execute();
|
||||
}
|
||||
|
||||
@ -36,6 +36,9 @@ public class JoinReorderContext {
|
||||
private boolean hasRightAssociate = false;
|
||||
private boolean hasLeftAssociate = false;
|
||||
|
||||
// mark for whether it has applied HyperGraph.
|
||||
private boolean hasHyperReorder = false;
|
||||
|
||||
public JoinReorderContext() {
|
||||
}
|
||||
|
||||
@ -110,4 +113,12 @@ public class JoinReorderContext {
|
||||
public void setHasCommuteZigZag(boolean hasCommuteZigZag) {
|
||||
this.hasCommuteZigZag = hasCommuteZigZag;
|
||||
}
|
||||
|
||||
public boolean hasHyperReorder() {
|
||||
return hasHyperReorder;
|
||||
}
|
||||
|
||||
public void setHasHyperReorder(boolean hasHyperReorder) {
|
||||
this.hasHyperReorder = hasHyperReorder;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.joinreorder;
|
||||
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.joinreorder.hypergraph.HyperGraph;
|
||||
import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
|
||||
/**
|
||||
* This rule is for Join Reorder (non Cascades Transfrom Join Reorder).
|
||||
*/
|
||||
public class HyperGraphJoinReorder extends OneRewriteRuleFactory {
|
||||
@Override
|
||||
public Rule build() {
|
||||
// TODO: we need a pattern to match a subtree of join and mark the node in this tree ordered
|
||||
return logicalJoin(
|
||||
subTree(LogicalJoin.class, LogicalProject.class),
|
||||
subTree(LogicalJoin.class, LogicalProject.class))
|
||||
.thenApply(ctx -> {
|
||||
LogicalJoin<? extends Plan, ? extends Plan> rootJoin = ctx.root;
|
||||
// TODO: check mark.
|
||||
HyperGraph graph = HyperGraph.fromPlan(rootJoin);
|
||||
System.out.println(graph.toDottyHyperGraph());
|
||||
if (graph.optimize()) {
|
||||
return graph.toPlan();
|
||||
}
|
||||
return null;
|
||||
}).toRule(RuleType.JOIN_REORDER);
|
||||
}
|
||||
}
|
||||
@ -15,26 +15,34 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.exploration.join;
|
||||
package org.apache.doris.nereids.rules.joinreorder;
|
||||
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.exploration.join.hypergraph.HyperGraph;
|
||||
import org.apache.doris.nereids.rules.joinreorder.hypergraph.HyperGraph;
|
||||
import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
|
||||
/**
|
||||
* Join Reorder Rule.
|
||||
* This rule is for Join Reorder (non Cascades Transfrom Join Reorder).
|
||||
*/
|
||||
public class JoinReorderRule extends OneRewriteRuleFactory {
|
||||
public class HyperGraphJoinReorderGroupPlan extends OneRewriteRuleFactory {
|
||||
@Override
|
||||
public Rule build() {
|
||||
// TODO: we need a pattern to match a subtree of join and mark the node in this tree ordered
|
||||
return logicalJoin(group(), group()).thenApply(ctx -> {
|
||||
HyperGraph graph = HyperGraph.fromPlan(ctx.root);
|
||||
if (graph.optimize()) {
|
||||
return graph.toPlan();
|
||||
}
|
||||
return ctx.root;
|
||||
}).toRule(RuleType.JOIN_REORDER);
|
||||
return logicalJoin(
|
||||
subTree(LogicalJoin.class, LogicalProject.class),
|
||||
group())
|
||||
.thenApply(ctx -> {
|
||||
LogicalJoin<? extends Plan, ? extends Plan> rootJoin = ctx.root;
|
||||
HyperGraph graph = HyperGraph.fromPlan(rootJoin);
|
||||
System.out.println(graph.toDottyHyperGraph());
|
||||
if (graph.optimize()) {
|
||||
return graph.toPlan();
|
||||
}
|
||||
return null;
|
||||
}).toRule(RuleType.JOIN_REORDER);
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.exploration.join.hypergraph;
|
||||
package org.apache.doris.nereids.rules.joinreorder.hypergraph;
|
||||
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
|
||||
@ -15,14 +15,16 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.exploration.join.hypergraph;
|
||||
package org.apache.doris.nereids.rules.joinreorder.hypergraph;
|
||||
|
||||
import org.apache.doris.nereids.trees.expressions.EqualTo;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.GroupPlan;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
@ -64,17 +66,31 @@ public class HyperGraph {
|
||||
}
|
||||
|
||||
private void buildGraph(Plan plan) {
|
||||
if (!(plan instanceof LogicalJoin)) {
|
||||
if ((plan instanceof LogicalProject && plan.child(0) instanceof GroupPlan)
|
||||
|| plan instanceof GroupPlan) {
|
||||
nodes.add(new Node(nodes.size(), plan));
|
||||
return;
|
||||
}
|
||||
LogicalJoin<? extends Plan, ? extends Plan> join = (LogicalJoin<? extends Plan, ? extends Plan>) plan;
|
||||
// Now we only support inner join
|
||||
|
||||
LogicalJoin<? extends Plan, ? extends Plan> join;
|
||||
if (plan instanceof LogicalProject) {
|
||||
LogicalProject<? extends Plan> project = (LogicalProject<? extends Plan>) plan;
|
||||
join = (LogicalJoin<? extends Plan, ? extends Plan>) project.child();
|
||||
|
||||
// Handle project
|
||||
// Ignore the projection expression just using for selection column.
|
||||
// TODO: how to handle Alias and complex project expression
|
||||
} else {
|
||||
join = (LogicalJoin<? extends Plan, ? extends Plan>) plan;
|
||||
}
|
||||
|
||||
// Now we only support inner join with Inside-Project
|
||||
// TODO: Other joins can be added according CD-C algorithm
|
||||
if (join.getJoinType() != JoinType.INNER_JOIN) {
|
||||
nodes.add(new Node(nodes.size(), plan));
|
||||
return;
|
||||
}
|
||||
|
||||
buildGraph(join.left());
|
||||
buildGraph(join.right());
|
||||
addEdge(join);
|
||||
@ -83,9 +99,9 @@ public class HyperGraph {
|
||||
private BitSet findNode(Set<Slot> slots) {
|
||||
BitSet bitSet = new BitSet();
|
||||
for (Node node : nodes) {
|
||||
for (Slot slot : node.plan.getOutput()) {
|
||||
for (Slot slot : node.getPlan().getOutput()) {
|
||||
if (slots.contains(slot)) {
|
||||
bitSet.set(node.index);
|
||||
bitSet.set(node.getIndex());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -124,7 +140,7 @@ public class HyperGraph {
|
||||
builder.append(String.format("digraph G { # %d edges\n", edges.size() / 2));
|
||||
List<String> graphvisNodes = new ArrayList<>();
|
||||
for (Node node : nodes) {
|
||||
String nodeName = node.plan.getType().name() + node.index;
|
||||
String nodeName = node.getPlan().getType().name() + node.getIndex();
|
||||
// nodeID is used to identify the node with the same name
|
||||
String nodeID = nodeName;
|
||||
while (graphvisNodes.contains(nodeID)) {
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.exploration.join.hypergraph;
|
||||
package org.apache.doris.nereids.rules.joinreorder.hypergraph;
|
||||
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
|
||||
@ -28,25 +28,57 @@ import java.util.List;
|
||||
* HyperGraph Node.
|
||||
*/
|
||||
class Node {
|
||||
final int index;
|
||||
Plan plan;
|
||||
private final int index;
|
||||
private Plan plan;
|
||||
// We split these into simple edges (only one node on each side) and complex edges (others)
|
||||
// because we can often quickly discard all simple edges by testing the set of interesting nodes
|
||||
// against the “simple_neighborhood” bitmap.
|
||||
List<Edge> complexEdges = Lists.newArrayList();
|
||||
List<Edge> simpleEdges = Lists.newArrayList();
|
||||
private List<Edge> complexEdges = Lists.newArrayList();
|
||||
private List<Edge> simpleEdges = Lists.newArrayList();
|
||||
|
||||
BitSet simpleNeighborhood = new BitSet();
|
||||
private BitSet simpleNeighborhood = new BitSet();
|
||||
|
||||
public Node(int index, Plan plan) {
|
||||
this.plan = plan;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public Plan getPlan() {
|
||||
return plan;
|
||||
}
|
||||
|
||||
public void setPlan(Plan plan) {
|
||||
this.plan = plan;
|
||||
}
|
||||
|
||||
public List<Edge> getComplexEdges() {
|
||||
return complexEdges;
|
||||
}
|
||||
|
||||
public void setComplexEdges(List<Edge> complexEdges) {
|
||||
this.complexEdges = complexEdges;
|
||||
}
|
||||
|
||||
public List<Edge> getSimpleEdges() {
|
||||
return simpleEdges;
|
||||
}
|
||||
|
||||
public void setSimpleEdges(List<Edge> simpleEdges) {
|
||||
this.simpleEdges = simpleEdges;
|
||||
}
|
||||
|
||||
public BitSet getSimpleNeighborhood() {
|
||||
return simpleNeighborhood;
|
||||
}
|
||||
|
||||
public void setSimpleNeighborhood(BitSet simpleNeighborhood) {
|
||||
this.simpleNeighborhood = simpleNeighborhood;
|
||||
}
|
||||
|
||||
public void attachEdge(Edge edge) {
|
||||
if (edge.isSimple()) {
|
||||
simpleEdges.add(edge);
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.exploration.join.hypergraph;
|
||||
package org.apache.doris.nereids.rules.joinreorder.hypergraph;
|
||||
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
@ -26,7 +26,7 @@ import java.util.BitSet;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* The Receiver is used for cached the plan that has been emit and build the new plan
|
||||
* The Receiver is used for cached the plan that has been emitted and build the new plan
|
||||
*/
|
||||
public class Receiver {
|
||||
// limit define the max number of csg-cmp pair in this Receiver
|
||||
@ -60,7 +60,7 @@ public class Receiver {
|
||||
|
||||
public void addPlan(Node node) {
|
||||
BitSet bitSet = new BitSet();
|
||||
bitSet.set(node.index);
|
||||
bitSet.set(node.getIndex());
|
||||
planMap.put(bitSet, node.getPlan());
|
||||
}
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.exploration.join;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class JoinReorderTest {
|
||||
@Test
|
||||
void testHyperGraph() {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.joinreorder;
|
||||
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
|
||||
import org.apache.doris.nereids.util.LogicalPlanBuilder;
|
||||
import org.apache.doris.nereids.util.MemoTestUtils;
|
||||
import org.apache.doris.nereids.util.PlanChecker;
|
||||
import org.apache.doris.nereids.util.PlanConstructor;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class HyperGraphJoinReorderGroupPlanTest {
|
||||
private final LogicalOlapScan scan1 = PlanConstructor.newLogicalOlapScan(0, "t1", 0);
|
||||
private final LogicalOlapScan scan2 = PlanConstructor.newLogicalOlapScan(1, "t2", 0);
|
||||
private final LogicalOlapScan scan3 = PlanConstructor.newLogicalOlapScan(2, "t3", 0);
|
||||
private final LogicalOlapScan scan4 = PlanConstructor.newLogicalOlapScan(3, "t4", 0);
|
||||
private final LogicalOlapScan scan5 = PlanConstructor.newLogicalOlapScan(4, "t5", 0);
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
LogicalPlan plan = new LogicalPlanBuilder(scan1)
|
||||
.hashJoinUsing(scan2, JoinType.INNER_JOIN, Pair.of(0, 1))
|
||||
.hashJoinUsing(scan3, JoinType.INNER_JOIN, Pair.of(0, 1))
|
||||
.hashJoinUsing(scan4, JoinType.INNER_JOIN, Pair.of(0, 1))
|
||||
.hashJoinUsing(scan5, JoinType.INNER_JOIN, Pair.of(0, 1))
|
||||
.build();
|
||||
|
||||
PlanChecker.from(MemoTestUtils.createConnectContext(), plan)
|
||||
.applyTopDown(new HyperGraphJoinReorderGroupPlan())
|
||||
.printlnTree();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.joinreorder;
|
||||
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
|
||||
import org.apache.doris.nereids.util.LogicalPlanBuilder;
|
||||
import org.apache.doris.nereids.util.MemoTestUtils;
|
||||
import org.apache.doris.nereids.util.PlanChecker;
|
||||
import org.apache.doris.nereids.util.PlanConstructor;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class HyperGraphJoinReorderTest {
|
||||
private final LogicalOlapScan scan1 = PlanConstructor.newLogicalOlapScan(0, "t1", 0);
|
||||
private final LogicalOlapScan scan2 = PlanConstructor.newLogicalOlapScan(1, "t2", 0);
|
||||
private final LogicalOlapScan scan3 = PlanConstructor.newLogicalOlapScan(2, "t3", 0);
|
||||
private final LogicalOlapScan scan4 = PlanConstructor.newLogicalOlapScan(3, "t4", 0);
|
||||
private final LogicalOlapScan scan5 = PlanConstructor.newLogicalOlapScan(4, "t5", 0);
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
LogicalPlan plan = new LogicalPlanBuilder(scan1)
|
||||
.hashJoinUsing(scan2, JoinType.INNER_JOIN, Pair.of(0, 1))
|
||||
.hashJoinUsing(scan3, JoinType.INNER_JOIN, Pair.of(0, 1))
|
||||
.hashJoinUsing(
|
||||
new LogicalPlanBuilder(scan4)
|
||||
.hashJoinUsing(scan5, JoinType.INNER_JOIN, Pair.of(0, 1))
|
||||
.build(),
|
||||
JoinType.INNER_JOIN, Pair.of(0, 1)
|
||||
)
|
||||
.build();
|
||||
|
||||
PlanChecker.from(MemoTestUtils.createConnectContext(), plan)
|
||||
.applyTopDown(new HyperGraphJoinReorder())
|
||||
.printlnTree();
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.exploration.join.hypergraph;
|
||||
package org.apache.doris.nereids.rules.joinreorder.hypergraph;
|
||||
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
|
||||
import org.apache.doris.nereids.util.LogicalPlanBuilder;
|
||||
import org.apache.doris.nereids.util.PlanConstructor;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class HyperGraphTest {
|
||||
@ -34,6 +35,7 @@ public class HyperGraphTest {
|
||||
private final LogicalOlapScan scan5 = PlanConstructor.newLogicalOlapScan(4, "t5", 0);
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void testDottyHyperGraph() {
|
||||
LogicalPlan joinCluster = new LogicalPlanBuilder(scan1)
|
||||
.hashJoinUsing(scan2, JoinType.INNER_JOIN, Pair.of(0, 0))
|
||||
@ -41,19 +43,20 @@ public class HyperGraphTest {
|
||||
.hashJoinUsing(scan4, JoinType.INNER_JOIN, Pair.of(0, 0))
|
||||
.hashJoinUsing(scan5, JoinType.INNER_JOIN, Pair.of(0, 0))
|
||||
.build();
|
||||
|
||||
HyperGraph hyperGraph = HyperGraph.fromPlan(joinCluster);
|
||||
String dottyGraph = hyperGraph.toDottyHyperGraph();
|
||||
// This is a star join, which can be transformed to a image by graphviz.
|
||||
assert dottyGraph.equals("digraph G { # 4 edges\n"
|
||||
+ " LOGICAL_OLAP_SCAN0 [label=\"LOGICAL_OLAP_SCAN0\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN1 [label=\"LOGICAL_OLAP_SCAN1\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN2 [label=\"LOGICAL_OLAP_SCAN2\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN3 [label=\"LOGICAL_OLAP_SCAN3\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN4 [label=\"LOGICAL_OLAP_SCAN4\"];\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN1 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN2 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN3 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN4 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "}\n") : dottyGraph;
|
||||
+ " LOGICAL_OLAP_SCAN0 [label=\"LOGICAL_OLAP_SCAN0\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN1 [label=\"LOGICAL_OLAP_SCAN1\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN2 [label=\"LOGICAL_OLAP_SCAN2\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN3 [label=\"LOGICAL_OLAP_SCAN3\"];\n"
|
||||
+ " LOGICAL_OLAP_SCAN4 [label=\"LOGICAL_OLAP_SCAN4\"];\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN1 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN2 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN3 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "LOGICAL_OLAP_SCAN0 -> LOGICAL_OLAP_SCAN4 [label=\"1.0\",arrowhead=none]\n"
|
||||
+ "}\n") : dottyGraph;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user