Skip to content

Commit f4311b9

Browse files
committed
Fix bug GetDBValue
1 parent c04b239 commit f4311b9

File tree

3 files changed

+397
-5
lines changed

3 files changed

+397
-5
lines changed

proxy/loader.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package proxy
2+
3+
import (
4+
"context"
5+
q "github.com/core-go/sql"
6+
"reflect"
7+
)
8+
9+
const txs = "tx"
10+
11+
func GetTx(ctx context.Context) *string {
12+
txi := ctx.Value(txs)
13+
if txi != nil {
14+
txx, ok := txi.(*string)
15+
if ok {
16+
return txx
17+
}
18+
}
19+
return nil
20+
}
21+
22+
type Proxy interface {
23+
BeginTransaction(ctx context.Context, timeout int64) (string, error)
24+
CommitTransaction(ctx context.Context, tx string) error
25+
RollbackTransaction(ctx context.Context, tx string) error
26+
Exec(ctx context.Context, query string, values ...interface{}) (int64, error)
27+
ExecBatch(ctx context.Context, master bool, stm ...q.Statement) (int64, error)
28+
Query(ctx context.Context, result interface{}, query string, values ...interface{}) error
29+
ExecTx(ctx context.Context, tx string, commit bool, query string, values ...interface{}) (int64, error)
30+
ExecBatchTx(ctx context.Context, tx string, commit bool, master bool, stm ...q.Statement) (int64, error)
31+
QueryTx(ctx context.Context, tx string, commit bool, result interface{}, query string, values ...interface{}) error
32+
33+
Insert(ctx context.Context, table string, model interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
34+
Update(ctx context.Context, table string, model interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
35+
Save(ctx context.Context, table string, model interface{}, driver string, options ...*q.Schema) (int64, error)
36+
InsertBatch(ctx context.Context, table string, models interface{}, driver string, options ...*q.Schema) (int64, error)
37+
UpdateBatch(ctx context.Context, table string, models interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
38+
SaveBatch(ctx context.Context, table string, models interface{}, driver string, options ...*q.Schema) (int64, error)
39+
40+
InsertTx(ctx context.Context, tx string, commit bool, table string, model interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
41+
UpdateTx(ctx context.Context, tx string, commit bool, table string, model interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
42+
SaveTx(ctx context.Context, tx string, commit bool, table string, model interface{}, driver string, options ...*q.Schema) (int64, error)
43+
InsertBatchTx(ctx context.Context, tx string, commit bool, table string, models interface{}, driver string, options ...*q.Schema) (int64, error)
44+
UpdateBatchTx(ctx context.Context, tx string, commit bool, table string, models interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
45+
SaveBatchTx(ctx context.Context, tx string, commit bool, table string, models interface{}, driver string, options ...*q.Schema) (int64, error)
46+
47+
InsertAndCommit(ctx context.Context, tx string, table string, model interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
48+
UpdateAndCommit(ctx context.Context, tx string, table string, model interface{}, driver string, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
49+
SaveAndCommit(ctx context.Context, tx string, table string, model interface{}, driver string, options ...*q.Schema) (int64, error)
50+
InsertBatchAndCommit(ctx context.Context, tx string, table string, models interface{}, driver string, options ...*q.Schema) (int64, error)
51+
UpdateBatchAndCommit(ctx context.Context, tx string, table string, models interface{}, buildParam func(int) string, boolSupport bool, options ...*q.Schema) (int64, error)
52+
SaveBatchAndCommit(ctx context.Context, tx string, table string, models interface{}, driver string, options ...*q.Schema) (int64, error)
53+
}
54+
55+
type Loader struct {
56+
Proxy Proxy
57+
BuildParam func(i int) string
58+
Map func(ctx context.Context, model interface{}) (interface{}, error)
59+
modelType reflect.Type
60+
modelsType reflect.Type
61+
keys []string
62+
mapJsonColumnKeys map[string]string
63+
fieldsIndex map[string]int
64+
table string
65+
IsRollback bool
66+
}
67+
68+
func NewLoader(proxy Proxy, tableName string, modelType reflect.Type, buildParam func(i int) string, options ...func(context.Context, interface{}) (interface{}, error)) (*Loader, error) {
69+
_, idNames := q.FindPrimaryKeys(modelType)
70+
mapJsonColumnKeys := q.MapJsonColumn(modelType)
71+
modelsType := reflect.Zero(reflect.SliceOf(modelType)).Type()
72+
73+
fieldsIndex, er0 := q.GetColumnIndexes(modelType)
74+
if er0 != nil {
75+
return nil, er0
76+
}
77+
var mp func(context.Context, interface{}) (interface{}, error)
78+
if len(options) > 0 {
79+
mp = options[0]
80+
}
81+
return &Loader{Proxy: proxy, IsRollback: true, BuildParam: buildParam, Map: mp, modelType: modelType, modelsType: modelsType, keys: idNames, mapJsonColumnKeys: mapJsonColumnKeys, fieldsIndex: fieldsIndex, table: tableName}, nil
82+
}
83+
84+
func (s *Loader) Keys() []string {
85+
return s.keys
86+
}
87+
88+
func (s *Loader) All(ctx context.Context) (interface{}, error) {
89+
query := q.BuildSelectAllQuery(s.table)
90+
result := reflect.New(s.modelsType).Interface()
91+
var err error
92+
tx := GetTx(ctx)
93+
if tx == nil {
94+
err = s.Proxy.Query(ctx, result, query)
95+
} else {
96+
err = s.Proxy.QueryTx(ctx, *tx, false, result, query)
97+
if err != nil {
98+
if s.IsRollback {
99+
s.Proxy.RollbackTransaction(ctx, *tx)
100+
}
101+
return result, err
102+
}
103+
}
104+
if err == nil {
105+
if s.Map != nil {
106+
return q.MapModels(ctx, result, s.Map)
107+
}
108+
return result, err
109+
}
110+
return result, err
111+
}
112+
113+
func (s *Loader) Load(ctx context.Context, id interface{}) (interface{}, error) {
114+
queryFindById, values := q.BuildFindById(s.table, s.BuildParam, id, s.mapJsonColumnKeys, s.keys)
115+
tx := GetTx(ctx)
116+
result := reflect.New(s.modelsType).Interface()
117+
var r interface{}
118+
var er1 error
119+
if tx == nil {
120+
er1 = s.Proxy.Query(ctx, result, queryFindById, values...)
121+
} else {
122+
er1 = s.Proxy.QueryTx(ctx, *tx, false, result, queryFindById, values...)
123+
}
124+
if er1 != nil {
125+
if s.IsRollback && tx != nil {
126+
s.Proxy.RollbackTransaction(ctx, *tx)
127+
}
128+
return r, er1
129+
}
130+
if s.Map != nil {
131+
_, er2 := s.Map(ctx, &r)
132+
if er2 != nil {
133+
return nil, er2
134+
}
135+
vo := reflect.Indirect(reflect.ValueOf(r))
136+
if vo.Kind() == reflect.Slice {
137+
if vo.Len() > 0 {
138+
return vo.Index(0).Addr(), nil
139+
}
140+
return nil, nil
141+
}
142+
return r, er2
143+
}
144+
vo := reflect.Indirect(reflect.ValueOf(r))
145+
if vo.Kind() == reflect.Slice {
146+
if vo.Len() > 0 {
147+
return vo.Index(0).Addr(), nil
148+
}
149+
return nil, nil
150+
}
151+
return r, er1
152+
}

proxy/writer.go

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
package proxy
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
q "github.com/core-go/sql"
7+
"reflect"
8+
"strconv"
9+
"strings"
10+
)
11+
12+
func Begin(ctx context.Context, db *sql.DB, opts ...*sql.TxOptions) (context.Context, *sql.Tx, error) {
13+
var tx *sql.Tx
14+
var err error
15+
if len(opts) > 0 && opts[0] != nil {
16+
tx, err = db.BeginTx(ctx, opts[0])
17+
} else {
18+
tx, err = db.Begin()
19+
}
20+
if err != nil {
21+
return ctx, tx, err
22+
} else {
23+
c2 := context.WithValue(ctx, txs, tx)
24+
return c2, tx, nil
25+
}
26+
}
27+
func Commit(tx *sql.Tx, err error, options ...bool) error {
28+
if err != nil {
29+
if len(options) > 0 && options[0] {
30+
tx.Rollback()
31+
}
32+
return err
33+
}
34+
return tx.Commit()
35+
}
36+
func Rollback(tx *sql.Tx, err error, options ...int64) (int64, error) {
37+
tx.Rollback()
38+
if len(options) > 0 {
39+
return options[0], err
40+
}
41+
return -1, err
42+
}
43+
func End(tx *sql.Tx, res int64, err error, options ...bool) (int64, error) {
44+
er := Commit(tx, err, options...)
45+
return res, er
46+
}
47+
48+
type Writer struct {
49+
*Loader
50+
jsonColumnMap map[string]string
51+
Mapper q.Mapper
52+
versionField string
53+
versionIndex int
54+
versionDBField string
55+
schema *q.Schema
56+
BoolSupport bool
57+
Rollback bool
58+
Driver string
59+
}
60+
61+
func NewWriter(proxy Proxy, tableName string, modelType reflect.Type, buildParam func(i int) string, options ...q.Mapper) (*Writer, error) {
62+
return NewWriterWithVersion(proxy, tableName, modelType, buildParam, "", options...)
63+
}
64+
func NewWriterWithVersion(proxy Proxy, tableName string, modelType reflect.Type, buildParam func(i int) string, versionField string, options ...q.Mapper) (*Writer, error) {
65+
var mapper q.Mapper
66+
if len(options) > 0 {
67+
mapper = options[0]
68+
}
69+
var loader *Loader
70+
var err error
71+
if mapper != nil {
72+
loader, err = NewLoader(proxy, tableName, modelType, buildParam, mapper.DbToModel)
73+
} else {
74+
loader, err = NewLoader(proxy, tableName, modelType, buildParam, nil)
75+
}
76+
if err != nil {
77+
return nil, err
78+
}
79+
schema := q.CreateSchema(modelType)
80+
jsonColumnMap := q.MakeJsonColumnMap(modelType)
81+
if len(versionField) > 0 {
82+
index := q.FindFieldIndex(modelType, versionField)
83+
if index >= 0 {
84+
_, dbFieldName, exist := q.GetFieldByIndex(modelType, index)
85+
if !exist {
86+
dbFieldName = strings.ToLower(versionField)
87+
}
88+
return &Writer{Loader: loader, Rollback: true, schema: schema, Mapper: mapper, jsonColumnMap: jsonColumnMap, versionField: versionField, versionIndex: index, versionDBField: dbFieldName}, nil
89+
}
90+
}
91+
return &Writer{Loader: loader, Rollback: true, schema: schema, Mapper: mapper, jsonColumnMap: jsonColumnMap, versionField: versionField, versionIndex: -1}, nil
92+
}
93+
func (s *Writer) Insert(ctx context.Context, model interface{}) (int64, error) {
94+
var m interface{}
95+
if s.Mapper != nil {
96+
m2, err := s.Mapper.ModelToDb(ctx, model)
97+
if err != nil {
98+
return 0, err
99+
}
100+
m = m2
101+
} else {
102+
m = model
103+
}
104+
tx := GetTx(ctx)
105+
queryInsert, values := q.BuildToInsertWithVersion(s.table, m, s.versionIndex, s.BuildParam, s.BoolSupport, nil, s.schema)
106+
if tx == nil {
107+
return s.Proxy.Exec(ctx, queryInsert, values...)
108+
} else {
109+
result, err := s.Proxy.ExecTx(ctx, *tx, false, queryInsert, values...)
110+
if err != nil {
111+
if s.Rollback {
112+
s.Proxy.RollbackTransaction(ctx, *tx)
113+
}
114+
return -1, err
115+
}
116+
return result, err
117+
}
118+
}
119+
func (s *Writer) Update(ctx context.Context, model interface{}) (int64, error) {
120+
var m interface{}
121+
if s.Mapper != nil {
122+
m2, err := s.Mapper.ModelToDb(ctx, &model)
123+
if err != nil {
124+
return 0, err
125+
}
126+
m = m2
127+
} else {
128+
m = model
129+
}
130+
tx := GetTx(ctx)
131+
query, values := q.BuildToUpdateWithVersion(s.table, m, s.versionIndex, s.BuildParam, s.BoolSupport, nil, s.schema)
132+
if tx == nil {
133+
return s.Proxy.Exec(ctx, query, values...)
134+
} else {
135+
result, err := s.Proxy.ExecTx(ctx, *tx, false, query, values...)
136+
if err != nil {
137+
if s.Rollback {
138+
s.Proxy.RollbackTransaction(ctx, *tx)
139+
}
140+
return -1, err
141+
}
142+
return result, err
143+
}
144+
}
145+
func (s *Writer) Save(ctx context.Context, model interface{}) (int64, error) {
146+
var m interface{}
147+
if s.Mapper != nil {
148+
m2, err := s.Mapper.ModelToDb(ctx, &model)
149+
if err != nil {
150+
return 0, err
151+
}
152+
m = m2
153+
} else {
154+
m = model
155+
}
156+
tx := GetTx(ctx)
157+
query, values, er0 := q.BuildToSave(s.table, m, s.Driver, s.schema)
158+
if er0 != nil {
159+
return -1, er0
160+
}
161+
if tx == nil {
162+
return s.Proxy.Exec(ctx, query, values...)
163+
} else {
164+
result, err := s.Proxy.ExecTx(ctx, *tx, false, query, values...)
165+
if err != nil {
166+
if s.Rollback {
167+
s.Proxy.RollbackTransaction(ctx, *tx)
168+
}
169+
return -1, err
170+
}
171+
return result, err
172+
}
173+
}
174+
func (s *Writer) Patch(ctx context.Context, model map[string]interface{}) (int64, error) {
175+
if s.Mapper != nil {
176+
_, err := s.Mapper.ModelToDb(ctx, &model)
177+
if err != nil {
178+
return 0, err
179+
}
180+
}
181+
MapToDB(&model, s.modelType)
182+
dbColumnMap := q.JSONToColumns(model, s.jsonColumnMap)
183+
query, values := q.BuildToPatchWithVersion(s.table, dbColumnMap, s.schema.SKeys, s.BuildParam, nil, s.versionDBField, s.schema.Fields)
184+
tx := GetTx(ctx)
185+
if tx == nil {
186+
return s.Proxy.Exec(ctx, query, values...)
187+
} else {
188+
result, err := s.Proxy.ExecTx(ctx, *tx, false, query, values...)
189+
if err != nil {
190+
if s.Rollback {
191+
s.Proxy.RollbackTransaction(ctx, *tx)
192+
}
193+
return -1, err
194+
}
195+
return result, err
196+
}
197+
}
198+
func MapToDB(model *map[string]interface{}, modelType reflect.Type) {
199+
for colName, value := range *model {
200+
if boolValue, boolOk := value.(bool); boolOk {
201+
index := q.GetIndexByTag("json", colName, modelType)
202+
if index > -1 {
203+
valueS := modelType.Field(index).Tag.Get(strconv.FormatBool(boolValue))
204+
valueInt, err := strconv.Atoi(valueS)
205+
if err != nil {
206+
(*model)[colName] = valueS
207+
} else {
208+
(*model)[colName] = valueInt
209+
}
210+
continue
211+
}
212+
}
213+
(*model)[colName] = value
214+
}
215+
}
216+
func (s *Writer) Delete(ctx context.Context, id interface{}) (int64, error) {
217+
tx := GetTx(ctx)
218+
// l := len(s.keys)
219+
query := q.BuildQueryById(id, s.modelType, s.keys[0])
220+
sql, values := q.BuildToDelete(s.table, query, s.BuildParam)
221+
if tx == nil {
222+
return s.Proxy.Exec(ctx, sql, values...)
223+
} else {
224+
result, err := s.Proxy.ExecTx(ctx, *tx, false, sql, values...)
225+
if err != nil {
226+
if s.Rollback {
227+
s.Proxy.RollbackTransaction(ctx, *tx)
228+
}
229+
return -1, err
230+
}
231+
return result, err
232+
}
233+
}

0 commit comments

Comments
 (0)