Coverage Report

Created: 2024-10-13 08:39

/Users/andrewlamb/Software/datafusion/datafusion/common/src/display/graphviz.rs
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
//! Logic related to creating DOT language graphs.
19
20
use std::fmt;
21
22
#[derive(Default)]
23
pub struct GraphvizBuilder {
24
    id_gen: usize,
25
}
26
27
impl GraphvizBuilder {
28
    // Generate next id in graphviz.
29
0
    pub fn next_id(&mut self) -> usize {
30
0
        self.id_gen += 1;
31
0
        self.id_gen
32
0
    }
33
34
    // Write out the start of whole graph.
35
0
    pub fn start_graph(&mut self, f: &mut fmt::Formatter) -> fmt::Result {
36
0
        writeln!(
37
0
            f,
38
0
            r#"
39
0
// Begin DataFusion GraphViz Plan,
40
0
// display it online here: https://dreampuf.github.io/GraphvizOnline
41
0
"#
42
0
        )?;
43
0
        writeln!(f, "digraph {{")
44
0
    }
45
46
0
    pub fn end_graph(&mut self, f: &mut fmt::Formatter) -> fmt::Result {
47
0
        writeln!(f, "}}")?;
48
0
        writeln!(f, "// End DataFusion GraphViz Plan")
49
0
    }
50
51
    // write out the start of the subgraph cluster
52
0
    pub fn start_cluster(&mut self, f: &mut fmt::Formatter, title: &str) -> fmt::Result {
53
0
        writeln!(f, "  subgraph cluster_{}", self.next_id())?;
54
0
        writeln!(f, "  {{")?;
55
0
        writeln!(f, "    graph[label={}]", Self::quoted(title))
56
0
    }
57
58
    // write out the end of the subgraph cluster
59
0
    pub fn end_cluster(&mut self, f: &mut fmt::Formatter) -> fmt::Result {
60
0
        writeln!(f, "  }}")
61
0
    }
62
63
    /// makes a quoted string suitable for inclusion in a graphviz chart
64
0
    pub fn quoted(label: &str) -> String {
65
0
        let label = label.replace('"', "_");
66
0
        format!("\"{label}\"")
67
0
    }
68
69
0
    pub fn add_node(
70
0
        &self,
71
0
        f: &mut fmt::Formatter,
72
0
        id: usize,
73
0
        label: &str,
74
0
        tooltip: Option<&str>,
75
0
    ) -> fmt::Result {
76
0
        if let Some(tooltip) = tooltip {
77
0
            writeln!(
78
0
                f,
79
0
                "    {}[shape=box label={}, tooltip={}]",
80
0
                id,
81
0
                GraphvizBuilder::quoted(label),
82
0
                GraphvizBuilder::quoted(tooltip),
83
0
            )
84
        } else {
85
0
            writeln!(
86
0
                f,
87
0
                "    {}[shape=box label={}]",
88
0
                id,
89
0
                GraphvizBuilder::quoted(label),
90
0
            )
91
        }
92
0
    }
93
94
0
    pub fn add_edge(
95
0
        &self,
96
0
        f: &mut fmt::Formatter,
97
0
        from_id: usize,
98
0
        to_id: usize,
99
0
    ) -> fmt::Result {
100
0
        writeln!(
101
0
            f,
102
0
            "    {from_id} -> {to_id} [arrowhead=none, arrowtail=normal, dir=back]"
103
0
        )
104
0
    }
105
}