forked from skeema/tengo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
schema.go
134 lines (121 loc) · 4.05 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package tengo
import (
"fmt"
)
// Schema represents a database schema.
type Schema struct {
Name string
CharSet string
Collation string
Tables []*Table
Routines []*Routine
}
// TablesByName returns a mapping of table names to Table struct pointers, for
// all tables in the schema.
func (s *Schema) TablesByName() map[string]*Table {
if s == nil {
return map[string]*Table{}
}
result := make(map[string]*Table, len(s.Tables))
for _, t := range s.Tables {
result[t.Name] = t
}
return result
}
// HasTable returns true if a table with the given name exists in the schema.
func (s *Schema) HasTable(name string) bool {
return s != nil && s.Table(name) != nil
}
// Table returns a table by name.
func (s *Schema) Table(name string) *Table {
if s != nil {
for _, t := range s.Tables {
if t.Name == name {
return t
}
}
}
return nil
}
// ProceduresByName returns a mapping of stored procedure names to Routine
// struct pointers, for all stored procedures in the schema.
func (s *Schema) ProceduresByName() map[string]*Routine {
return s.routinesByNameAndType(ObjectTypeProc)
}
// FunctionsByName returns a mapping of function names to Routine struct
// pointers, for all functions in the schema.
func (s *Schema) FunctionsByName() map[string]*Routine {
return s.routinesByNameAndType(ObjectTypeFunc)
}
func (s *Schema) routinesByNameAndType(ot ObjectType) map[string]*Routine {
if s == nil {
return map[string]*Routine{}
}
result := make(map[string]*Routine, len(s.Routines))
for _, r := range s.Routines {
if r.Type == ot {
result[r.Name] = r
}
}
return result
}
// ObjectDefinitions returns a mapping of ObjectKey (type+name) to an SQL string
// containing the corresponding CREATE statement, for all supported object types
// in the schema.
// Note that the returned map does NOT include an entry for the schema itself.
func (s *Schema) ObjectDefinitions() map[ObjectKey]string {
dict := make(map[ObjectKey]string)
for name, table := range s.TablesByName() {
key := ObjectKey{Type: ObjectTypeTable, Name: name}
dict[key] = table.CreateStatement
}
for name, procedure := range s.ProceduresByName() {
key := ObjectKey{Type: ObjectTypeProc, Name: name}
dict[key] = procedure.CreateStatement
}
for name, function := range s.FunctionsByName() {
key := ObjectKey{Type: ObjectTypeFunc, Name: name}
dict[key] = function.CreateStatement
}
return dict
}
// Diff returns the set of differences between this schema and another schema.
func (s *Schema) Diff(other *Schema) *SchemaDiff {
return NewSchemaDiff(s, other)
}
// DropStatement returns a SQL statement that, if run, would drop this schema.
func (s *Schema) DropStatement() string {
return fmt.Sprintf("DROP DATABASE %s", EscapeIdentifier(s.Name))
}
// CreateStatement returns a SQL statement that, if run, would create this
// schema.
func (s *Schema) CreateStatement() string {
var charSet, collate string
if s.CharSet != "" {
charSet = fmt.Sprintf(" CHARACTER SET %s", s.CharSet)
}
if s.Collation != "" {
collate = fmt.Sprintf(" COLLATE %s", s.Collation)
}
return fmt.Sprintf("CREATE DATABASE %s%s%s", EscapeIdentifier(s.Name), charSet, collate)
}
// AlterStatement returns a SQL statement that, if run, would alter this
// schema's default charset and/or collation to the supplied values.
// If charSet is "" and collation isn't, only the collation will be changed.
// If collation is "" and charSet isn't, the default collation for charSet is
// used automatically.
// If both params are "", or if values equal to the schema's current charSet
// and collation are supplied, an empty string is returned.
func (s *Schema) AlterStatement(charSet, collation string) string {
var charSetClause, collateClause string
if s.CharSet != charSet && charSet != "" {
charSetClause = fmt.Sprintf(" CHARACTER SET %s", charSet)
}
if s.Collation != collation && collation != "" {
collateClause = fmt.Sprintf(" COLLATE %s", collation)
}
if charSetClause == "" && collateClause == "" {
return ""
}
return fmt.Sprintf("ALTER DATABASE %s%s%s", EscapeIdentifier(s.Name), charSetClause, collateClause)
}