-
Notifications
You must be signed in to change notification settings - Fork 36
/
mapping.go
117 lines (97 loc) · 2.31 KB
/
mapping.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
package mappings
import (
"reflect"
"regexp"
"strings"
)
var (
matchFirstCapRe = regexp.MustCompile("(.)([A-Z][a-z]+)")
matchAllCapRe = regexp.MustCompile("([a-z0-9])([A-Z])")
)
type colProperties struct {
Name string
IsPK bool
IsGenerated bool
AutoIncrement bool
}
func getColProperties(tag string) colProperties {
var p colProperties
if tag == "" {
return p
}
parts := strings.Split(tag, ",")
p.Name = parts[0]
for _, part := range parts[1:] {
switch part {
case "pk":
p.IsPK = true
case "generated":
p.IsGenerated = true
case "autoincr":
p.AutoIncrement = true
}
}
return p
}
type Mapping struct {
All []string
PKs []string
NonPKs []string
Generated []string
NonGenerated []string
AutoIncrement []string
}
func GetMappings(typ reflect.Type) Mapping {
c := Mapping{}
if typ.Kind() == reflect.Pointer {
typ = typ.Elem()
}
if typ.Kind() != reflect.Struct {
return c
}
c.All = make([]string, typ.NumField())
c.PKs = make([]string, typ.NumField())
c.NonPKs = make([]string, typ.NumField())
c.Generated = make([]string, typ.NumField())
c.NonGenerated = make([]string, typ.NumField())
c.AutoIncrement = make([]string, typ.NumField())
// Go through the struct fields and populate the map.
// Recursively go into any child structs, adding a prefix where necessary
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
// Don't consider unexported fields
if !field.IsExported() {
continue
}
// Skip columns that have the tag "-"
tag := field.Tag.Get("db")
if tag == "-" {
continue
}
if tag == "" {
tag = snakeCase(field.Name)
}
props := getColProperties(tag)
c.All[field.Index[0]] = props.Name
if props.IsPK {
c.PKs[field.Index[0]] = props.Name
} else {
c.NonPKs[field.Index[0]] = props.Name
}
if props.IsGenerated {
c.Generated[field.Index[0]] = props.Name
} else {
c.NonGenerated[field.Index[0]] = props.Name
}
if props.AutoIncrement {
c.AutoIncrement[field.Index[0]] = props.Name
}
}
return c
}
// snakeCaseFieldFunc is a NameMapperFunc that maps struct field to snake case.
func snakeCase(str string) string {
snake := matchFirstCapRe.ReplaceAllString(str, "${1}_${2}")
snake = matchAllCapRe.ReplaceAllString(snake, "${1}_${2}")
return strings.ToLower(snake)
}