forked from si3nloong/sqlike
-
Notifications
You must be signed in to change notification settings - Fork 0
/
schema.go
124 lines (110 loc) · 3.66 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
package schema
import (
"encoding/json"
"fmt"
"reflect"
"sync"
"time"
"cloud.google.com/go/civil"
"github.com/RevenueMonster/sqlike/reflext"
"github.com/RevenueMonster/sqlike/sql/driver"
sqltype "github.com/RevenueMonster/sqlike/sql/type"
"github.com/RevenueMonster/sqlike/sqlike/columns"
"github.com/google/uuid"
"github.com/paulmach/orb"
gouuid "github.com/satori/go.uuid"
"golang.org/x/text/currency"
"golang.org/x/text/language"
)
// DataTyper :
type DataTyper interface {
DataType(info driver.Info, sf reflext.StructFielder) columns.Column
}
// DataTypeFunc :
type DataTypeFunc func(sf reflext.StructFielder) columns.Column
// Builder :
type Builder struct {
mutex *sync.Mutex
typeMap map[interface{}]sqltype.Type
builders map[sqltype.Type]DataTypeFunc
}
// NewBuilder :
func NewBuilder() *Builder {
sb := &Builder{
mutex: new(sync.Mutex),
typeMap: make(map[interface{}]sqltype.Type),
builders: make(map[sqltype.Type]DataTypeFunc),
}
sb.SetDefaultTypes()
return sb
}
// SetType :
func (sb *Builder) SetType(it interface{}, t sqltype.Type) {
sb.mutex.Lock()
defer sb.mutex.Unlock()
sb.typeMap[it] = t
}
// SetTypeBuilder :
func (sb *Builder) SetTypeBuilder(t sqltype.Type, builder DataTypeFunc) {
sb.mutex.Lock()
defer sb.mutex.Unlock()
sb.builders[t] = builder
}
// LookUpType :
func (sb *Builder) LookUpType(t reflect.Type) (typ sqltype.Type, exists bool) {
t = reflext.Deref(t)
typ, exists = sb.typeMap[t]
return
}
// GetColumn :
func (sb *Builder) GetColumn(info driver.Info, sf reflext.StructFielder) (columns.Column, error) {
t := reflext.Deref(sf.Type())
v := reflect.New(t)
if x, ok := v.Interface().(DataTyper); ok {
return x.DataType(info, sf), nil
}
if x, ok := sb.typeMap[t]; ok {
return sb.builders[x](sf), nil
}
if x, ok := sb.typeMap[t.Kind()]; ok {
return sb.builders[x](sf), nil
}
return columns.Column{}, fmt.Errorf("schema: invalid data type support %v", t)
}
// SetDefaultTypes :
func (sb *Builder) SetDefaultTypes() {
sb.SetType(reflect.TypeOf([]byte{}), sqltype.Byte)
sb.SetType(reflect.TypeOf(uuid.UUID{}), sqltype.UUID)
sb.SetType(reflect.TypeOf(gouuid.UUID{}), sqltype.UUID)
sb.SetType(reflect.TypeOf(language.Tag{}), sqltype.String)
sb.SetType(reflect.TypeOf(currency.Unit{}), sqltype.Char)
sb.SetType(reflect.TypeOf(time.Time{}), sqltype.DateTime)
sb.SetType(reflect.TypeOf(time.Location{}), sqltype.String)
sb.SetType(reflect.TypeOf(civil.Date{}), sqltype.Date)
sb.SetType(reflect.TypeOf(civil.Time{}), sqltype.Time)
sb.SetType(reflect.TypeOf(json.RawMessage{}), sqltype.JSON)
sb.SetType(reflect.TypeOf(orb.Point{}), sqltype.Point)
sb.SetType(reflect.TypeOf(orb.LineString{}), sqltype.LineString)
sb.SetType(reflect.TypeOf(orb.Polygon{}), sqltype.Polygon)
sb.SetType(reflect.TypeOf(orb.MultiPoint{}), sqltype.MultiPoint)
sb.SetType(reflect.TypeOf(orb.MultiLineString{}), sqltype.MultiLineString)
sb.SetType(reflect.TypeOf(orb.MultiPolygon{}), sqltype.MultiPolygon)
sb.SetType(reflect.String, sqltype.String)
sb.SetType(reflect.Bool, sqltype.Bool)
sb.SetType(reflect.Int, sqltype.Int)
sb.SetType(reflect.Int8, sqltype.Int8)
sb.SetType(reflect.Int16, sqltype.Int16)
sb.SetType(reflect.Int32, sqltype.Int32)
sb.SetType(reflect.Int64, sqltype.Int64)
sb.SetType(reflect.Uint, sqltype.Uint)
sb.SetType(reflect.Uint8, sqltype.Uint8)
sb.SetType(reflect.Uint16, sqltype.Uint16)
sb.SetType(reflect.Uint32, sqltype.Uint32)
sb.SetType(reflect.Uint64, sqltype.Uint64)
sb.SetType(reflect.Float32, sqltype.Float32)
sb.SetType(reflect.Float64, sqltype.Float64)
sb.SetType(reflect.Struct, sqltype.Struct)
sb.SetType(reflect.Array, sqltype.Array)
sb.SetType(reflect.Slice, sqltype.Slice)
sb.SetType(reflect.Map, sqltype.Map)
}