-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathdml_provider.go
executable file
·147 lines (128 loc) · 4.55 KB
/
dml_provider.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
package dsc
import (
"reflect"
"strings"
"github.com/viant/toolbox"
)
//metaDmlProvider represents tag mapping base dml provider.
type metaDmlProvider struct {
dmlBuilder *DmlBuilder
columnToFieldNameMap map[string](map[string]string)
}
func (p *metaDmlProvider) pkColumns() []string {
return p.dmlBuilder.TableDescriptor.PkColumns
}
//Key returns primary key values
func (p *metaDmlProvider) Key(instance interface{}) []interface{} {
result := p.readValues(instance, p.pkColumns())
return result
}
//SetKey sets a key on passed in instance pointer
func (p *metaDmlProvider) SetKey(instancePointer interface{}, seq int64) {
toolbox.AssertPointerKind(instancePointer, reflect.Struct, "instance")
key := p.pkColumns()[0]
columnSetting := p.columnToFieldNameMap[strings.ToLower(key)]
if field, found := columnSetting["fieldName"]; found {
var reflectable = reflect.ValueOf(instancePointer)
if reflectable.Kind() == reflect.Ptr {
field := reflectable.Elem().FieldByName(field)
field.SetInt(seq)
}
}
}
func (p *metaDmlProvider) readValues(instance interface{}, columns []string) []interface{} {
var result = make([]interface{}, len(columns))
var reflectable = reflect.ValueOf(instance)
if reflectable.Kind() == reflect.Ptr {
reflectable = reflectable.Elem()
}
for i, column := range columns {
result[i] = p.readValue(reflectable, column)
}
return result
}
func (p *metaDmlProvider) mapValueIfNeeded(value interface{}, column string, columnSetting map[string]string) interface{} {
if mapping, found := columnSetting["valueMap"]; found {
stringValue := toolbox.AsString(value)
reverseMapValue := toolbox.MakeReverseStringMap(mapping, ":", ",")
if mappedValue, ok := reverseMapValue[stringValue]; ok {
return mappedValue
}
}
return value
}
func (p *metaDmlProvider) readValue(source reflect.Value, column string) interface{} {
columnSetting := p.columnToFieldNameMap[strings.ToLower(column)]
if fieldName, ok := columnSetting["fieldName"]; ok {
field := source.FieldByName(fieldName)
value := toolbox.UnwrapValue(&field)
if toolbox.IsZero(field) && value != nil && toolbox.IsStruct(value) {
value = nil
}
return p.mapValueIfNeeded(value, column, columnSetting)
}
return nil
}
//Get returns a ParametrizedSQL for specified sqlType and target instance.
func (p *metaDmlProvider) Get(sqlType int, instance interface{}) *ParametrizedSQL {
var reflectable = reflect.ValueOf(instance)
if reflectable.Kind() == reflect.Ptr {
reflectable = reflectable.Elem()
}
//toolbox.AssertKind(instance, reflect.Type, "instance")
return p.dmlBuilder.GetParametrizedSQL(sqlType, func(column string) interface{} {
return p.readValue(reflectable, column)
})
}
func newMetaDmlProvider(table string, targetType reflect.Type) (DmlProvider, error) {
descriptor, err := NewTableDescriptor(table, targetType)
if err != nil {
return nil, err
}
dmlBuilder := NewDmlBuilder(descriptor)
return &metaDmlProvider{dmlBuilder: dmlBuilder,
columnToFieldNameMap: toolbox.NewFieldSettingByKey(targetType, "column")}, nil
}
//NewDmlProviderIfNeeded returns a new NewDmlProvider for a table and target type if passed provider was nil.
func NewDmlProviderIfNeeded(provider DmlProvider, table string, targetType reflect.Type) (DmlProvider, error) {
if provider != nil {
return provider, nil
}
return newMetaDmlProvider(table, targetType)
}
//NewKeyGetterIfNeeded returns a new key getter if supplied keyGetter was nil for the target type
func NewKeyGetterIfNeeded(keyGetter KeyGetter, table string, targetType reflect.Type) (KeyGetter, error) {
if keyGetter != nil {
return keyGetter, nil
}
return newMetaDmlProvider(table, targetType)
}
type mapDmlProvider struct {
tableDescriptor *TableDescriptor
dmlBuilder *DmlBuilder
}
func (p *mapDmlProvider) Key(instance interface{}) []interface{} {
var record = toolbox.AsMap(instance)
var result = make([]interface{}, len(p.tableDescriptor.PkColumns))
for i, column := range p.tableDescriptor.PkColumns {
result[i] = record[column]
}
return result
}
func (p *mapDmlProvider) SetKey(instance interface{}, seq int64) {
var record = toolbox.AsMap(instance)
record[p.tableDescriptor.PkColumns[0]] = seq
}
func (p *mapDmlProvider) Get(sqlType int, instance interface{}) *ParametrizedSQL {
var record = toolbox.AsMap(instance)
return p.dmlBuilder.GetParametrizedSQL(sqlType, func(column string) interface{} {
return record[column]
})
}
func NewMapDmlProvider(descriptor *TableDescriptor) DmlProvider {
var result = &mapDmlProvider{
tableDescriptor: descriptor,
dmlBuilder: NewDmlBuilder(descriptor),
}
return result
}