1 package exec
2
3 import (
4 "context"
5 gsql "database/sql"
6 "reflect"
7
8 "github.com/doug-martin/goqu/v9/internal/errors"
9 "github.com/doug-martin/goqu/v9/internal/util"
10 )
11
12 type (
13 QueryExecutor struct {
14 de DbExecutor
15 err error
16 query string
17 args []interface{}
18 }
19 )
20
21 var (
22 errUnsupportedScanStructType = errors.New("type must be a pointer to a struct when scanning into a struct")
23 errUnsupportedScanStructsType = errors.New("type must be a pointer to a slice when scanning into structs")
24 errUnsupportedScanValsType = errors.New("type must be a pointer to a slice when scanning into vals")
25 errScanValPointer = errors.New("type must be a pointer when scanning into val")
26 errScanValNonSlice = errors.New("type cannot be a pointer to a slice when scanning into val")
27 )
28
29 func newQueryExecutor(de DbExecutor, err error, query string, args ...interface{}) QueryExecutor {
30 return QueryExecutor{de: de, err: err, query: query, args: args}
31 }
32
33 func (q QueryExecutor) ToSQL() (sql string, args []interface{}, err error) {
34 return q.query, q.args, q.err
35 }
36
37 func (q QueryExecutor) Exec() (gsql.Result, error) {
38 return q.ExecContext(context.Background())
39 }
40
41 func (q QueryExecutor) ExecContext(ctx context.Context) (gsql.Result, error) {
42 if q.err != nil {
43 return nil, q.err
44 }
45 return q.de.ExecContext(ctx, q.query, q.args...)
46 }
47
48 func (q QueryExecutor) Query() (*gsql.Rows, error) {
49 return q.QueryContext(context.Background())
50 }
51
52 func (q QueryExecutor) QueryContext(ctx context.Context) (*gsql.Rows, error) {
53 if q.err != nil {
54 return nil, q.err
55 }
56 return q.de.QueryContext(ctx, q.query, q.args...)
57 }
58
59
60
61
62
63
64
65
66
67
68 func (q QueryExecutor) ScanStructs(i interface{}) error {
69 return q.ScanStructsContext(context.Background(), i)
70 }
71
72
73
74
75
76
77
78
79
80
81 func (q QueryExecutor) ScanStructsContext(ctx context.Context, i interface{}) error {
82 scanner, err := q.ScannerContext(ctx)
83 if err != nil {
84 return err
85 }
86 defer func() { _ = scanner.Close() }()
87 return scanner.ScanStructs(i)
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102 func (q QueryExecutor) ScanStruct(i interface{}) (bool, error) {
103 return q.ScanStructContext(context.Background(), i)
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118 func (q QueryExecutor) ScanStructContext(ctx context.Context, i interface{}) (bool, error) {
119 val := reflect.ValueOf(i)
120 if !util.IsPointer(val.Kind()) {
121 return false, errUnsupportedScanStructType
122 }
123 val = reflect.Indirect(val)
124 if !util.IsStruct(val.Kind()) {
125 return false, errUnsupportedScanStructType
126 }
127
128 scanner, err := q.ScannerContext(ctx)
129 if err != nil {
130 return false, err
131 }
132
133 defer func() { _ = scanner.Close() }()
134
135 if scanner.Next() {
136 err = scanner.ScanStruct(i)
137 if err != nil {
138 return false, err
139 }
140
141 return true, scanner.Err()
142 }
143
144 return false, scanner.Err()
145 }
146
147
148
149
150
151
152
153
154 func (q QueryExecutor) ScanVals(i interface{}) error {
155 return q.ScanValsContext(context.Background(), i)
156 }
157
158
159
160
161
162
163
164
165 func (q QueryExecutor) ScanValsContext(ctx context.Context, i interface{}) error {
166 scanner, err := q.ScannerContext(ctx)
167 if err != nil {
168 return err
169 }
170 defer func() { _ = scanner.Close() }()
171 return scanner.ScanVals(i)
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185 func (q QueryExecutor) ScanVal(i interface{}) (bool, error) {
186 return q.ScanValContext(context.Background(), i)
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200 func (q QueryExecutor) ScanValContext(ctx context.Context, i interface{}) (bool, error) {
201 val := reflect.ValueOf(i)
202 if !util.IsPointer(val.Kind()) {
203 return false, errScanValPointer
204 }
205 val = reflect.Indirect(val)
206 if util.IsSlice(val.Kind()) {
207 switch i.(type) {
208 case *gsql.RawBytes:
209 case *[]byte:
210 case gsql.Scanner:
211 default:
212 return false, errScanValNonSlice
213 }
214 }
215
216 scanner, err := q.ScannerContext(ctx)
217 if err != nil {
218 return false, err
219 }
220
221 defer func() { _ = scanner.Close() }()
222
223 if scanner.Next() {
224 err = scanner.ScanVal(i)
225 if err != nil {
226 return false, err
227 }
228
229 return true, scanner.Err()
230 }
231
232 return false, scanner.Err()
233 }
234
235
236 func (q QueryExecutor) Scanner() (Scanner, error) {
237 return q.ScannerContext(context.Background())
238 }
239
240
241 func (q QueryExecutor) ScannerContext(ctx context.Context) (Scanner, error) {
242 rows, err := q.QueryContext(ctx)
243 if err != nil {
244 return nil, err
245 }
246 return NewScanner(rows), nil
247 }
248
View as plain text