forked from hidu/mysql-schema-sync
/
schema.go
116 lines (104 loc) · 2.38 KB
/
schema.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
116
package internal
import (
"bytes"
"fmt"
"strings"
"github.com/elliotchance/orderedmap"
)
// MySchema table schema
type MySchema struct {
Fields *orderedmap.OrderedMap
IndexAll map[string]*DbIndex
ForeignAll map[string]*DbIndex
SchemaRaw string
}
func (mys *MySchema) String() string {
if mys.Fields == nil {
return "nil"
}
var buf bytes.Buffer
buf.WriteString("Fields:\n")
for name, v := range mys.Fields.Keys() {
buf.WriteString(fmt.Sprintf(" %v : %s\n", name, v))
}
buf.WriteString("Index:\n")
for name, idx := range mys.IndexAll {
buf.WriteString(fmt.Sprintf(" %s : %s\n", name, idx.SQL))
}
buf.WriteString("ForeignKey:\n")
for name, idx := range mys.ForeignAll {
buf.WriteString(fmt.Sprintf(" %s : %s\n", name, idx.SQL))
}
return buf.String()
}
// GetFieldNames table names
func (mys *MySchema) GetFieldNames() []string {
var names []string
for _, name := range mys.Fields.Keys() {
names = append(names, name.(string))
}
return names
}
func (mys *MySchema) RelationTables() []string {
tbs := make(map[string]int)
for _, idx := range mys.ForeignAll {
for _, tb := range idx.RelationTables {
tbs[tb] = 1
}
}
var tables []string
for tb := range tbs {
tables = append(tables, tb)
}
return tables
}
// ParseSchema parse table's schema
func ParseSchema(schema string) *MySchema {
schema = strings.TrimSpace(schema)
lines := strings.Split(schema, "\n")
mys := &MySchema{
SchemaRaw: schema,
Fields: orderedmap.NewOrderedMap(),
IndexAll: make(map[string]*DbIndex),
ForeignAll: make(map[string]*DbIndex),
}
for i := 1; i < len(lines)-1; i++ {
line := strings.TrimSpace(lines[i])
if len(line) == 0 {
continue
}
line = strings.TrimRight(line, ",")
if line[0] == '`' {
index := strings.Index(line[1:], "`")
name := line[1 : index+1]
mys.Fields.Set(name, line)
} else {
idx := parseDbIndexLine(line)
if idx == nil {
continue
}
switch idx.IndexType {
case indexTypeForeignKey:
mys.ForeignAll[idx.Name] = idx
default:
mys.IndexAll[idx.Name] = idx
}
}
}
return mys
}
type SchemaDiff struct {
Source *MySchema
Dest *MySchema
Table string
}
func newSchemaDiff(table, source, dest string) *SchemaDiff {
return &SchemaDiff{
Table: table,
Source: ParseSchema(source),
Dest: ParseSchema(dest),
}
}
func (sdiff *SchemaDiff) RelationTables() []string {
return sdiff.Source.RelationTables()
}