-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgraph.go
115 lines (95 loc) · 2.86 KB
/
graph.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package mysql
import (
"bytes"
"os"
"os/exec"
"runtime"
qmodel "github.com/go-qbit/model"
"github.com/tmc/dot"
)
func (s *MySQL) GetGraphSVG() string {
g := dot.NewGraph("Database")
uniqRelations := map[string]map[string]*qmodel.Relation{}
nodes := make(map[string]*dot.Node)
for _, model := range s.models {
n := dot.NewNode(model.GetId())
_ = n.Set("shape", "plaintext")
labelBuf := &bytes.Buffer{}
labelBuf.WriteString(`<<TABLE BORDER="1" CELLBORDER="0"><TR><TD ALIGN="CENTER"><B>`)
labelBuf.WriteString(model.GetId())
labelBuf.WriteString(`</B></TD></TR><HR/>`)
pkFields := map[string]bool{}
for _, name := range model.GetPKFieldsNames() {
pkFields[name] = true
}
for _, name := range model.GetFieldsNames() {
labelBuf.WriteString(`<TR><TD ALIGN="LEFT" PORT="`)
labelBuf.WriteString(name)
labelBuf.WriteString(`">`)
field := model.GetFieldDefinition(name)
if field.IsDerivable() {
labelBuf.WriteString(`<I>- `)
} else if field.IsRequired() || pkFields[name] {
labelBuf.WriteString(`∙ `)
} else {
labelBuf.WriteString(`∘ `)
}
labelBuf.WriteString(`<B>`)
labelBuf.WriteString(field.GetId())
labelBuf.WriteString(`</B>`)
if !field.IsDerivable() {
labelBuf.WriteString(`: `)
labelBuf.WriteString(field.GetStorageType())
}
if pkFields[name] {
labelBuf.WriteString(`<B>(PK)</B>`)
}
if field.IsDerivable() {
labelBuf.WriteString(`</I>`)
}
labelBuf.WriteString(`</TD></TR>`)
}
labelBuf.WriteString(`</TABLE>>`)
_ = n.Set("label", labelBuf.String())
g.AddNode(n)
nodes[model.GetId()] = n
uniqRelations[model.GetId()] = map[string]*qmodel.Relation{}
for _, name := range model.GetRelations() {
if relation := model.GetRelation(name); !relation.IsBack && relation.RelationType != qmodel.RELATION_MANY_TO_MANY {
uniqRelations[model.GetId()][relation.ExtModel.GetId()] = relation
}
}
}
for modelName, modelRelations := range uniqRelations {
model := s.models[modelName]
for _, relation := range modelRelations {
if !relation.IsBack && relation.RelationType != qmodel.RELATION_MANY_TO_MANY {
e := dot.NewEdge(nodes[model.GetId()], nodes[relation.ExtModel.GetId()])
_ = e.Set("tailport", relation.LocalFieldsNames[0])
_ = e.Set("headport", relation.FkFieldsNames[0])
_ = e.Set("labelfontsize", "8")
_ = e.Set("labeldistance", "3")
_ = e.Set("dir", "both")
if relation.IsRequired {
_ = e.Set("arrowtail", "dot")
} else {
_ = e.Set("arrowtail", "odot")
}
g.AddEdge(e)
}
}
}
outBuf := &bytes.Buffer{}
pathToDot := "/usr/bin/dot"
if runtime.GOOS == "darwin" {
pathToDot = "/usr/local/bin/dot"
}
cmd := exec.Command(pathToDot, "-Tsvg")
cmd.Stdin = bytes.NewBuffer([]byte(g.String()))
cmd.Stdout = outBuf
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
return outBuf.String()
}