-
Notifications
You must be signed in to change notification settings - Fork 44
/
fields.go
167 lines (143 loc) · 3.51 KB
/
fields.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package gendata
import (
"fmt"
"strings"
"github.com/yuin/gopher-lua"
)
var fieldsTmpl = mustParse("fields", "`{{.fname}}` {{.types}} {{.sign}} {{.keys}}")
var fieldVars = []*varWithDefault{
{
"types",
[]string{"int", "varchar", "date", "time", "datetime"},
},
{
"keys",
[]string{"undef", "key"},
},
// to ensure ignore efficient, sign should always be the last
{
"sign",
[]string{"signed"},
},
}
// https://dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html
var canUnSign = map[string]bool{
"tinyint": true,
"smallint": true,
"mediumint": true,
"int": true,
"integer": true,
"bigint": true,
"float": true,
"double": true,
"decimal": true,
}
const enumVals = "('a','b','c','d','e','f','g','h','i','j','k','l'," +
"'m','n','o','p','q','r','s','t','u','v','w','x','y','z')"
var fieldFuncs = map[string]func(text string, fname string, ctx *fieldExec) (target string,
ignore bool, extraStmt *string, err error){
"types": func(text string, fname string, ctx *fieldExec) (string, bool, *string, error) {
index := strings.Index(text, "(")
var tp string
if index != -1 {
tp = text[:index]
} else {
tp = text
}
tp = strings.ToLower(tp)
if canUnSign[tp] {
ctx.canUnSign = true
}
if tp == "set" || tp == "enum" {
text = tp + enumVals
}
return text, false, nil, nil
},
"keys": func(text string, fname string, ctx *fieldExec) (string, bool, *string, error) {
if text == "undef" {
return "", false, nil, nil
}
extraStmt := fmt.Sprintf("key (`%s`)", fname)
return "", false, &extraStmt, nil
},
// "signed" is sign, other is "unsigned"
"sign": func(text string, fname string, ctx *fieldExec) (string, bool, *string, error) {
if ctx.canUnSign {
if text == "signed" {
return "", false, nil, nil
}
ctx.unsign = true
return "unsigned", false, nil, nil
} else if text != "signed" {
return "", true, nil, nil
}
return "", false, nil, nil
},
}
type Fields struct {
*options
}
func newFields(l *lua.LState) (*Fields, error) {
o, err := newOptions(fieldsTmpl, l, "fields", fieldVars)
if err != nil {
return nil, err
}
return &Fields{o}, nil
}
func (f *Fields) gen() ([]string, []*fieldExec, error) {
fnamePrefix := "col"
m := make(map[string]string)
stmts := make([]string, 0, f.numbers)
extraStmts := make([]string, 0)
fieldExecs := make([]*fieldExec, 0, f.numbers)
err := f.traverse(func(cur []string) error {
fExec := &fieldExec{}
fname := fnamePrefix + "_" + strings.Join(cur, "_")
extraNum := 0
for i := range cur {
field := f.fields[i]
if field == "types" {
fExec.tp = strings.ToLower(cur[i])
}
target, ignore, extraStmt, err := fieldFuncs[field](cur[i], fname, fExec)
if err != nil {
return err
}
// may be inefficient, prune tree may be better
if ignore {
// delete related extraNum
extraStmts = extraStmts[0 : len(extraStmts)-extraNum]
return nil
}
if extraStmt != nil {
extraNum++
extraStmts = append(extraStmts, *extraStmt)
}
m[field] = target
}
m["fname"] = fname
fExec.name = fname
fieldExecs = append(fieldExecs, fExec)
stmts = append(stmts, f.format(m))
return nil
})
if err != nil {
return nil, fieldExecs, err
}
stmts = append(stmts, extraStmts...)
return stmts, fieldExecs, nil
}
type fieldExec struct {
canUnSign bool
unsign bool
name string
// tp writen by user zz file
tp string
}
func (f *fieldExec) dType() string {
index := strings.Index(f.tp, "(")
if index == -1 {
return f.tp
}
return f.tp[:index]
}