datafusion_common/display/
graphviz.rs1use std::fmt;
21
22#[derive(Default)]
23pub struct GraphvizBuilder {
24 id_gen: usize,
25}
26
27impl GraphvizBuilder {
28 pub fn next_id(&mut self) -> usize {
30 self.id_gen += 1;
31 self.id_gen
32 }
33
34 pub fn start_graph(&mut self, f: &mut fmt::Formatter) -> fmt::Result {
36 writeln!(
37 f,
38 r#"
39// Begin DataFusion GraphViz Plan,
40// display it online here: https://dreampuf.github.io/GraphvizOnline
41"#
42 )?;
43 writeln!(f, "digraph {{")
44 }
45
46 pub fn end_graph(&mut self, f: &mut fmt::Formatter) -> fmt::Result {
47 writeln!(f, "}}")?;
48 writeln!(f, "// End DataFusion GraphViz Plan")
49 }
50
51 pub fn start_cluster(&mut self, f: &mut fmt::Formatter, title: &str) -> fmt::Result {
53 writeln!(f, " subgraph cluster_{}", self.next_id())?;
54 writeln!(f, " {{")?;
55 writeln!(f, " graph[label={}]", Self::quoted(title))
56 }
57
58 pub fn end_cluster(&mut self, f: &mut fmt::Formatter) -> fmt::Result {
60 writeln!(f, " }}")
61 }
62
63 pub fn quoted(label: &str) -> String {
65 let label = label.replace('"', "_");
66 format!("\"{label}\"")
67 }
68
69 pub fn add_node(
70 &self,
71 f: &mut fmt::Formatter,
72 id: usize,
73 label: &str,
74 tooltip: Option<&str>,
75 ) -> fmt::Result {
76 if let Some(tooltip) = tooltip {
77 writeln!(
78 f,
79 " {}[shape=box label={}, tooltip={}]",
80 id,
81 GraphvizBuilder::quoted(label),
82 GraphvizBuilder::quoted(tooltip),
83 )
84 } else {
85 writeln!(
86 f,
87 " {}[shape=box label={}]",
88 id,
89 GraphvizBuilder::quoted(label),
90 )
91 }
92 }
93
94 pub fn add_edge(
95 &self,
96 f: &mut fmt::Formatter,
97 from_id: usize,
98 to_id: usize,
99 ) -> fmt::Result {
100 writeln!(
101 f,
102 " {from_id} -> {to_id} [arrowhead=none, arrowtail=normal, dir=back]"
103 )
104 }
105}