/
daoopt.go
166 lines (129 loc) · 3.89 KB
/
daoopt.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
package sqlx
import (
"context"
"database/sql"
"fmt"
"reflect"
"github.com/bingoohuang/gor"
"github.com/bingoohuang/gor/defaults"
)
// CreateDaoOpt defines the options for CreateDao.
type CreateDaoOpt struct {
Error *error
Ctx context.Context
QueryMaxRows int `default:"-1"`
RowScanInterceptor RowScanInterceptor
DotSQL func(name string) (SQLPart, error)
Logger DaoLogger
ErrSetter func(err error)
DBGetter DBGetter
}
// CreateDaoOpter defines the option pattern interface for CreateDaoOpt.
type CreateDaoOpter interface {
ApplyCreateOpt(*CreateDaoOpt)
}
// CreateDaoOptFn defines the func prototype to option applying.
type CreateDaoOptFn func(*CreateDaoOpt)
// ApplyCreateOpt applies the option.
func (c CreateDaoOptFn) ApplyCreateOpt(opt *CreateDaoOpt) { c(opt) }
// WithError specifies the err pointer to receive error.
func WithError(err *error) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.Error = err })
}
// WithCtx specifies the context.Context to sdb execution processes.
func WithCtx(ctx context.Context) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.Ctx = ctx })
}
// WithLimit specifies the max rows to be fetched when execute query.
func WithLimit(maxRows int) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.QueryMaxRows = maxRows })
}
// WithLogger specifies dao logger.
func WithLogger(logger DaoLogger) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.Logger = logger })
}
// WithSQLFile imports SQL queries from the file.
func WithSQLFile(sqlFile string) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) {
ds, err := DotSQLLoadFile(sqlFile)
if err != nil {
panic(err)
}
opt.DotSQL = ds.Raw
})
}
// WithDB imports a db.
func WithDB(db *sql.DB) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.DBGetter = MakeDB(db) })
}
// WithSQLStr imports SQL queries from the string.
func WithSQLStr(s string) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) {
ds, err := DotSQLLoadString(s)
if err != nil {
panic(err)
}
opt.DotSQL = ds.Raw
})
}
// WithRowScanInterceptor specifies the RowScanInterceptor after a row fetched.
func WithRowScanInterceptor(interceptor RowScanInterceptor) CreateDaoOpter {
return CreateDaoOptFn(func(opt *CreateDaoOpt) { opt.RowScanInterceptor = interceptor })
}
// RowScanInterceptor defines the interceptor after a row scanning.
type RowScanInterceptor interface {
After(rowIndex int, v ...interface{}) (bool, error)
}
// RowScanInterceptorFn defines the interceptor function after a row scanning.
type RowScanInterceptorFn func(rowIndex int, v ...interface{}) (bool, error)
// After is revoked after after a row scanning.
func (r RowScanInterceptorFn) After(rowIndex int, v ...interface{}) (bool, error) {
return r(rowIndex, v...)
}
func applyCreateDaoOption(createDaoOpts []CreateDaoOpter) (*CreateDaoOpt, error) {
opt := &CreateDaoOpt{}
if err := defaults.Set(opt); err != nil {
return nil, fmt.Errorf("failed to set defaults for CreateDaoOpt error %w", err)
}
for _, v := range createDaoOpts {
v.ApplyCreateOpt(opt)
}
if opt.Ctx == nil {
opt.Ctx = context.Background()
}
if opt.DotSQL == nil {
opt.DotSQL = func(string) (SQLPart, error) { return nil, nil }
}
return opt, nil
}
func createErrorSetter(v reflect.Value, option *CreateDaoOpt) {
for i := 0; i < v.NumField(); i++ {
fv := v.Field(i)
f := v.Type().Field(i)
if f.PkgPath != "" /* not exportable? */ {
continue
}
if !gor.IsError(f.Type) {
continue
}
option.ErrSetter = func(err error) {
if option.Error != nil {
*option.Error = err
}
if fv.IsNil() && err == nil {
return
}
if err == nil {
fv.Set(reflect.Zero(f.Type))
} else {
fv.Set(reflect.ValueOf(err))
}
}
return
}
option.ErrSetter = func(err error) {
if option.Error != nil {
*option.Error = err
}
}
}