• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / go-tarantool / 5403553164

28 Jun 2023 04:41PM UTC coverage: 79.52% (+0.2%) from 79.335%
5403553164

push

github

oleg-jukovec
ci: enable more linters

- forbidigo
- gocritic
- lll
- reassign
- stylecheck
- unconvert

356 of 356 new or added lines in 15 files covered. (100.0%)

5296 of 6660 relevant lines covered (79.52%)

7621.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.39
/request.go
1
package tarantool
2

3
import (
4
        "context"
5
        "errors"
6
        "fmt"
7
        "reflect"
8
        "strings"
9
        "sync"
10

11
        "github.com/tarantool/go-iproto"
12
        "github.com/vmihailenco/msgpack/v5"
13
)
14

15
func fillSearch(enc *msgpack.Encoder, spaceNo, indexNo uint32, key interface{}) error {
1,370✔
16
        if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil {
1,370✔
17
                return err
×
18
        }
×
19
        if err := enc.EncodeUint(uint64(spaceNo)); err != nil {
1,370✔
20
                return err
×
21
        }
×
22
        if err := enc.EncodeUint(uint64(iproto.IPROTO_INDEX_ID)); err != nil {
1,370✔
23
                return err
×
24
        }
×
25
        if err := enc.EncodeUint(uint64(indexNo)); err != nil {
1,370✔
26
                return err
×
27
        }
×
28
        if err := enc.EncodeUint(uint64(iproto.IPROTO_KEY)); err != nil {
1,370✔
29
                return err
×
30
        }
×
31
        return enc.Encode(key)
1,370✔
32
}
33

34
func fillIterator(enc *msgpack.Encoder, offset, limit uint32, iterator Iter) error {
1,286✔
35
        if err := enc.EncodeUint(uint64(iproto.IPROTO_ITERATOR)); err != nil {
1,286✔
36
                return err
×
37
        }
×
38
        if err := enc.EncodeUint(uint64(iterator)); err != nil {
1,286✔
39
                return err
×
40
        }
×
41
        if err := enc.EncodeUint(uint64(iproto.IPROTO_OFFSET)); err != nil {
1,286✔
42
                return err
×
43
        }
×
44
        if err := enc.EncodeUint(uint64(offset)); err != nil {
1,286✔
45
                return err
×
46
        }
×
47
        if err := enc.EncodeUint(uint64(iproto.IPROTO_LIMIT)); err != nil {
1,286✔
48
                return err
×
49
        }
×
50
        return enc.EncodeUint(uint64(limit))
1,286✔
51
}
52

53
func fillInsert(enc *msgpack.Encoder, spaceNo uint32, tuple interface{}) error {
244✔
54
        if err := enc.EncodeMapLen(2); err != nil {
244✔
55
                return err
×
56
        }
×
57
        if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil {
244✔
58
                return err
×
59
        }
×
60
        if err := enc.EncodeUint(uint64(spaceNo)); err != nil {
244✔
61
                return err
×
62
        }
×
63
        if err := enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)); err != nil {
244✔
64
                return err
×
65
        }
×
66
        return enc.Encode(tuple)
244✔
67
}
68

69
func fillSelect(enc *msgpack.Encoder, spaceNo, indexNo, offset, limit uint32, iterator Iter,
70
        key, after interface{}, fetchPos bool) error {
1,286✔
71
        mapLen := 6
1,286✔
72
        if fetchPos {
1,302✔
73
                mapLen += 1
16✔
74
        }
16✔
75
        if after != nil {
1,298✔
76
                mapLen += 1
12✔
77
        }
12✔
78
        if err := enc.EncodeMapLen(mapLen); err != nil {
1,286✔
79
                return err
×
80
        }
×
81
        if err := fillIterator(enc, offset, limit, iterator); err != nil {
1,286✔
82
                return err
×
83
        }
×
84
        if err := fillSearch(enc, spaceNo, indexNo, key); err != nil {
1,286✔
85
                return err
×
86
        }
×
87
        if fetchPos {
1,302✔
88
                if err := enc.EncodeUint(uint64(iproto.IPROTO_FETCH_POSITION)); err != nil {
16✔
89
                        return err
×
90
                }
×
91
                if err := enc.EncodeBool(fetchPos); err != nil {
16✔
92
                        return err
×
93
                }
×
94
        }
95
        if after != nil {
1,298✔
96
                if pos, ok := after.([]byte); ok {
18✔
97
                        if err := enc.EncodeUint(uint64(iproto.IPROTO_AFTER_POSITION)); err != nil {
6✔
98
                                return err
×
99
                        }
×
100
                        if err := enc.EncodeString(string(pos)); err != nil {
6✔
101
                                return err
×
102
                        }
×
103
                } else {
6✔
104
                        if err := enc.EncodeUint(uint64(iproto.IPROTO_AFTER_TUPLE)); err != nil {
6✔
105
                                return err
×
106
                        }
×
107
                        if err := enc.Encode(after); err != nil {
6✔
108
                                return err
×
109
                        }
×
110
                }
111
        }
112
        return nil
1,286✔
113
}
114

115
func fillUpdate(enc *msgpack.Encoder, spaceNo, indexNo uint32, key, ops interface{}) error {
24✔
116
        enc.EncodeMapLen(4)
24✔
117
        if err := fillSearch(enc, spaceNo, indexNo, key); err != nil {
24✔
118
                return err
×
119
        }
×
120
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
24✔
121
        return enc.Encode(ops)
24✔
122
}
123

124
func fillUpsert(enc *msgpack.Encoder, spaceNo uint32, tuple, ops interface{}) error {
26✔
125
        enc.EncodeMapLen(3)
26✔
126
        enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID))
26✔
127
        enc.EncodeUint(uint64(spaceNo))
26✔
128
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
26✔
129
        if err := enc.Encode(tuple); err != nil {
26✔
130
                return err
×
131
        }
×
132
        enc.EncodeUint(uint64(iproto.IPROTO_OPS))
26✔
133
        return enc.Encode(ops)
26✔
134
}
135

136
func fillDelete(enc *msgpack.Encoder, spaceNo, indexNo uint32, key interface{}) error {
60✔
137
        enc.EncodeMapLen(3)
60✔
138
        return fillSearch(enc, spaceNo, indexNo, key)
60✔
139
}
60✔
140

141
func fillCall(enc *msgpack.Encoder, functionName string, args interface{}) error {
296✔
142
        enc.EncodeMapLen(2)
296✔
143
        enc.EncodeUint(uint64(iproto.IPROTO_FUNCTION_NAME))
296✔
144
        enc.EncodeString(functionName)
296✔
145
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
296✔
146
        return enc.Encode(args)
296✔
147
}
296✔
148

149
func fillEval(enc *msgpack.Encoder, expr string, args interface{}) error {
178✔
150
        enc.EncodeMapLen(2)
178✔
151
        enc.EncodeUint(uint64(iproto.IPROTO_EXPR))
178✔
152
        enc.EncodeString(expr)
178✔
153
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
178✔
154
        return enc.Encode(args)
178✔
155
}
178✔
156

157
func fillExecute(enc *msgpack.Encoder, expr string, args interface{}) error {
62✔
158
        enc.EncodeMapLen(2)
62✔
159
        enc.EncodeUint(uint64(iproto.IPROTO_SQL_TEXT))
62✔
160
        enc.EncodeString(expr)
62✔
161
        enc.EncodeUint(uint64(iproto.IPROTO_SQL_BIND))
62✔
162
        return encodeSQLBind(enc, args)
62✔
163
}
62✔
164

165
func fillPing(enc *msgpack.Encoder) error {
86✔
166
        return enc.EncodeMapLen(0)
86✔
167
}
86✔
168

169
// Ping sends empty request to Tarantool to check connection.
170
//
171
// Deprecated: the method will be removed in the next major version,
172
// use a PingRequest object + Do() instead.
173
func (conn *Connection) Ping() (*Response, error) {
14✔
174
        return conn.Do(NewPingRequest()).Get()
14✔
175
}
14✔
176

177
// Select performs select to box space.
178
//
179
// It is equal to conn.SelectAsync(...).Get().
180
//
181
// Deprecated: the method will be removed in the next major version,
182
// use a SelectRequest object + Do() instead.
183
func (conn *Connection) Select(space, index interface{}, offset, limit uint32, iterator Iter,
184
        key interface{}) (*Response, error) {
12✔
185
        return conn.SelectAsync(space, index, offset, limit, iterator, key).Get()
12✔
186
}
12✔
187

188
// Insert performs insertion to box space.
189
// Tarantool will reject Insert when tuple with same primary key exists.
190
//
191
// It is equal to conn.InsertAsync(space, tuple).Get().
192
//
193
// Deprecated: the method will be removed in the next major version,
194
// use an InsertRequest object + Do() instead.
195
func (conn *Connection) Insert(space interface{}, tuple interface{}) (*Response, error) {
12✔
196
        return conn.InsertAsync(space, tuple).Get()
12✔
197
}
12✔
198

199
// Replace performs "insert or replace" action to box space.
200
// If tuple with same primary key exists, it will be replaced.
201
//
202
// It is equal to conn.ReplaceAsync(space, tuple).Get().
203
//
204
// Deprecated: the method will be removed in the next major version,
205
// use a ReplaceRequest object + Do() instead.
206
func (conn *Connection) Replace(space interface{}, tuple interface{}) (*Response, error) {
48✔
207
        return conn.ReplaceAsync(space, tuple).Get()
48✔
208
}
48✔
209

210
// Delete performs deletion of a tuple by key.
211
// Result will contain array with deleted tuple.
212
//
213
// It is equal to conn.DeleteAsync(space, tuple).Get().
214
//
215
// Deprecated: the method will be removed in the next major version,
216
// use a DeleteRequest object + Do() instead.
217
func (conn *Connection) Delete(space, index interface{}, key interface{}) (*Response, error) {
26✔
218
        return conn.DeleteAsync(space, index, key).Get()
26✔
219
}
26✔
220

221
// Update performs update of a tuple by key.
222
// Result will contain array with updated tuple.
223
//
224
// It is equal to conn.UpdateAsync(space, tuple).Get().
225
//
226
// Deprecated: the method will be removed in the next major version,
227
// use a UpdateRequest object + Do() instead.
228
func (conn *Connection) Update(space, index interface{}, key, ops interface{}) (*Response, error) {
4✔
229
        return conn.UpdateAsync(space, index, key, ops).Get()
4✔
230
}
4✔
231

232
// Upsert performs "update or insert" action of a tuple by key.
233
// Result will not contain any tuple.
234
//
235
// It is equal to conn.UpsertAsync(space, tuple, ops).Get().
236
//
237
// Deprecated: the method will be removed in the next major version,
238
// use a UpsertRequest object + Do() instead.
239
func (conn *Connection) Upsert(space interface{}, tuple, ops interface{}) (*Response, error) {
8✔
240
        return conn.UpsertAsync(space, tuple, ops).Get()
8✔
241
}
8✔
242

243
// Call calls registered Tarantool function.
244
// It uses request code for Tarantool >= 1.7, result is an array.
245
//
246
// It is equal to conn.CallAsync(functionName, args).Get().
247
//
248
// Deprecated: the method will be removed in the next major version,
249
// use a CallRequest object + Do() instead.
250
func (conn *Connection) Call(functionName string, args interface{}) (*Response, error) {
16✔
251
        return conn.CallAsync(functionName, args).Get()
16✔
252
}
16✔
253

254
// Call16 calls registered Tarantool function.
255
// It uses request code for Tarantool 1.6, result is an array of arrays.
256
// Deprecated since Tarantool 1.7.2.
257
//
258
// It is equal to conn.Call16Async(functionName, args).Get().
259
//
260
// Deprecated: the method will be removed in the next major version,
261
// use a Call16Request object + Do() instead.
262
func (conn *Connection) Call16(functionName string, args interface{}) (*Response, error) {
4✔
263
        return conn.Call16Async(functionName, args).Get()
4✔
264
}
4✔
265

266
// Call17 calls registered Tarantool function.
267
// It uses request code for Tarantool >= 1.7, result is an array.
268
//
269
// It is equal to conn.Call17Async(functionName, args).Get().
270
//
271
// Deprecated: the method will be removed in the next major version,
272
// use a Call17Request object + Do() instead.
273
func (conn *Connection) Call17(functionName string, args interface{}) (*Response, error) {
2✔
274
        return conn.Call17Async(functionName, args).Get()
2✔
275
}
2✔
276

277
// Eval passes Lua expression for evaluation.
278
//
279
// It is equal to conn.EvalAsync(space, tuple).Get().
280
//
281
// Deprecated: the method will be removed in the next major version,
282
// use an EvalRequest object + Do() instead.
283
func (conn *Connection) Eval(expr string, args interface{}) (*Response, error) {
46✔
284
        return conn.EvalAsync(expr, args).Get()
46✔
285
}
46✔
286

287
// Execute passes sql expression to Tarantool for execution.
288
//
289
// It is equal to conn.ExecuteAsync(expr, args).Get().
290
// Since 1.6.0
291
//
292
// Deprecated: the method will be removed in the next major version,
293
// use an ExecuteRequest object + Do() instead.
294
func (conn *Connection) Execute(expr string, args interface{}) (*Response, error) {
48✔
295
        return conn.ExecuteAsync(expr, args).Get()
48✔
296
}
48✔
297

298
// single used for conn.GetTyped for decode one tuple.
299
type single struct {
300
        res   interface{}
301
        found bool
302
}
303

304
func (s *single) DecodeMsgpack(d *msgpack.Decoder) error {
4✔
305
        var err error
4✔
306
        var len int
4✔
307
        if len, err = d.DecodeArrayLen(); err != nil {
4✔
308
                return err
×
309
        }
×
310
        if s.found = len >= 1; !s.found {
6✔
311
                return nil
2✔
312
        }
2✔
313
        if len != 1 {
2✔
314
                return errors.New("tarantool returns unexpected value for Select(limit=1)")
×
315
        }
×
316
        return d.Decode(s.res)
2✔
317
}
318

319
// GetTyped performs select (with limit = 1 and offset = 0)
320
// to box space and fills typed result.
321
//
322
// It is equal to conn.SelectAsync(space, index, 0, 1, IterEq, key).GetTyped(&result)
323
//
324
// Deprecated: the method will be removed in the next major version,
325
// use a SelectRequest object + Do() instead.
326
func (conn *Connection) GetTyped(space, index interface{}, key interface{},
327
        result interface{}) error {
4✔
328
        s := single{res: result}
4✔
329
        return conn.SelectAsync(space, index, 0, 1, IterEq, key).GetTyped(&s)
4✔
330
}
4✔
331

332
// SelectTyped performs select to box space and fills typed result.
333
//
334
// It is equal to conn.SelectAsync(space, index, offset, limit, iterator, key).GetTyped(&result)
335
//
336
// Deprecated: the method will be removed in the next major version,
337
// use a SelectRequest object + Do() instead.
338
func (conn *Connection) SelectTyped(space, index interface{}, offset, limit uint32, iterator Iter,
339
        key interface{}, result interface{}) error {
1,172✔
340
        return conn.SelectAsync(space, index, offset, limit, iterator, key).GetTyped(result)
1,172✔
341
}
1,172✔
342

343
// InsertTyped performs insertion to box space.
344
// Tarantool will reject Insert when tuple with same primary key exists.
345
//
346
// It is equal to conn.InsertAsync(space, tuple).GetTyped(&result).
347
//
348
// Deprecated: the method will be removed in the next major version,
349
// use an InsertRequest object + Do() instead.
350
func (conn *Connection) InsertTyped(space interface{}, tuple interface{},
351
        result interface{}) error {
6✔
352
        return conn.InsertAsync(space, tuple).GetTyped(result)
6✔
353
}
6✔
354

355
// ReplaceTyped performs "insert or replace" action to box space.
356
// If tuple with same primary key exists, it will be replaced.
357
//
358
// It is equal to conn.ReplaceAsync(space, tuple).GetTyped(&result).
359
//
360
// Deprecated: the method will be removed in the next major version,
361
// use a ReplaceRequest object + Do() instead.
362
func (conn *Connection) ReplaceTyped(space interface{}, tuple interface{},
363
        result interface{}) error {
×
364
        return conn.ReplaceAsync(space, tuple).GetTyped(result)
×
365
}
×
366

367
// DeleteTyped performs deletion of a tuple by key and fills result with deleted tuple.
368
//
369
// It is equal to conn.DeleteAsync(space, tuple).GetTyped(&result).
370
//
371
// Deprecated: the method will be removed in the next major version,
372
// use a DeleteRequest object + Do() instead.
373
func (conn *Connection) DeleteTyped(space, index interface{}, key interface{},
374
        result interface{}) error {
×
375
        return conn.DeleteAsync(space, index, key).GetTyped(result)
×
376
}
×
377

378
// UpdateTyped performs update of a tuple by key and fills result with updated tuple.
379
//
380
// It is equal to conn.UpdateAsync(space, tuple, ops).GetTyped(&result).
381
//
382
// Deprecated: the method will be removed in the next major version,
383
// use a UpdateRequest object + Do() instead.
384
func (conn *Connection) UpdateTyped(space, index interface{}, key, ops interface{},
385
        result interface{}) error {
×
386
        return conn.UpdateAsync(space, index, key, ops).GetTyped(result)
×
387
}
×
388

389
// CallTyped calls registered function.
390
// It uses request code for Tarantool >= 1.7, result is an array.
391
//
392
// It is equal to conn.Call16Async(functionName, args).GetTyped(&result).
393
//
394
// Deprecated: the method will be removed in the next major version,
395
// use a CallRequest object + Do() instead.
396
func (conn *Connection) CallTyped(functionName string, args interface{},
397
        result interface{}) error {
×
398
        return conn.CallAsync(functionName, args).GetTyped(result)
×
399
}
×
400

401
// Call16Typed calls registered function.
402
// It uses request code for Tarantool 1.6, result is an array of arrays.
403
// Deprecated since Tarantool 1.7.2.
404
//
405
// It is equal to conn.Call16Async(functionName, args).GetTyped(&result).
406
//
407
// Deprecated: the method will be removed in the next major version,
408
// use a Call16Request object + Do() instead.
409
func (conn *Connection) Call16Typed(functionName string, args interface{},
410
        result interface{}) error {
×
411
        return conn.Call16Async(functionName, args).GetTyped(result)
×
412
}
×
413

414
// Call17Typed calls registered function.
415
// It uses request code for Tarantool >= 1.7, result is an array.
416
//
417
// It is equal to conn.Call17Async(functionName, args).GetTyped(&result).
418
//
419
// Deprecated: the method will be removed in the next major version,
420
// use a Call17Request object + Do() instead.
421
func (conn *Connection) Call17Typed(functionName string, args interface{},
422
        result interface{}) error {
×
423
        return conn.Call17Async(functionName, args).GetTyped(result)
×
424
}
×
425

426
// EvalTyped passes Lua expression for evaluation.
427
//
428
// It is equal to conn.EvalAsync(space, tuple).GetTyped(&result).
429
//
430
// Deprecated: the method will be removed in the next major version,
431
// use an EvalRequest object + Do() instead.
432
func (conn *Connection) EvalTyped(expr string, args interface{}, result interface{}) error {
6✔
433
        return conn.EvalAsync(expr, args).GetTyped(result)
6✔
434
}
6✔
435

436
// ExecuteTyped passes sql expression to Tarantool for execution.
437
//
438
// In addition to error returns sql info and columns meta data
439
// Since 1.6.0
440
//
441
// Deprecated: the method will be removed in the next major version,
442
// use an ExecuteRequest object + Do() instead.
443
func (conn *Connection) ExecuteTyped(expr string, args interface{},
444
        result interface{}) (SQLInfo, []ColumnMetaData, error) {
2✔
445
        fut := conn.ExecuteAsync(expr, args)
2✔
446
        err := fut.GetTyped(&result)
2✔
447
        return fut.resp.SQLInfo, fut.resp.MetaData, err
2✔
448
}
2✔
449

450
// SelectAsync sends select request to Tarantool and returns Future.
451
//
452
// Deprecated: the method will be removed in the next major version,
453
// use a SelectRequest object + Do() instead.
454
func (conn *Connection) SelectAsync(space, index interface{}, offset, limit uint32, iterator Iter,
455
        key interface{}) *Future {
1,188✔
456
        req := NewSelectRequest(space).
1,188✔
457
                Index(index).
1,188✔
458
                Offset(offset).
1,188✔
459
                Limit(limit).
1,188✔
460
                Iterator(iterator).
1,188✔
461
                Key(key)
1,188✔
462
        return conn.Do(req)
1,188✔
463
}
1,188✔
464

465
// InsertAsync sends insert action to Tarantool and returns Future.
466
// Tarantool will reject Insert when tuple with same primary key exists.
467
//
468
// Deprecated: the method will be removed in the next major version,
469
// use an InsertRequest object + Do() instead.
470
func (conn *Connection) InsertAsync(space interface{}, tuple interface{}) *Future {
18✔
471
        req := NewInsertRequest(space).Tuple(tuple)
18✔
472
        return conn.Do(req)
18✔
473
}
18✔
474

475
// ReplaceAsync sends "insert or replace" action to Tarantool and returns Future.
476
// If tuple with same primary key exists, it will be replaced.
477
//
478
// Deprecated: the method will be removed in the next major version,
479
// use a ReplaceRequest object + Do() instead.
480
func (conn *Connection) ReplaceAsync(space interface{}, tuple interface{}) *Future {
48✔
481
        req := NewReplaceRequest(space).Tuple(tuple)
48✔
482
        return conn.Do(req)
48✔
483
}
48✔
484

485
// DeleteAsync sends deletion action to Tarantool and returns Future.
486
// Future's result will contain array with deleted tuple.
487
//
488
// Deprecated: the method will be removed in the next major version,
489
// use a DeleteRequest object + Do() instead.
490
func (conn *Connection) DeleteAsync(space, index interface{}, key interface{}) *Future {
26✔
491
        req := NewDeleteRequest(space).Index(index).Key(key)
26✔
492
        return conn.Do(req)
26✔
493
}
26✔
494

495
// Update sends deletion of a tuple by key and returns Future.
496
// Future's result will contain array with updated tuple.
497
//
498
// Deprecated: the method will be removed in the next major version,
499
// use a UpdateRequest object + Do() instead.
500
func (conn *Connection) UpdateAsync(space, index interface{}, key, ops interface{}) *Future {
4✔
501
        req := NewUpdateRequest(space).Index(index).Key(key)
4✔
502
        req.ops = ops
4✔
503
        return conn.Do(req)
4✔
504
}
4✔
505

506
// UpsertAsync sends "update or insert" action to Tarantool and returns Future.
507
// Future's sesult will not contain any tuple.
508
//
509
// Deprecated: the method will be removed in the next major version,
510
// use a UpsertRequest object + Do() instead.
511
func (conn *Connection) UpsertAsync(space interface{}, tuple interface{},
512
        ops interface{}) *Future {
8✔
513
        req := NewUpsertRequest(space).Tuple(tuple)
8✔
514
        req.ops = ops
8✔
515
        return conn.Do(req)
8✔
516
}
8✔
517

518
// CallAsync sends a call to registered Tarantool function and returns Future.
519
// It uses request code for Tarantool >= 1.7, so future's result is an array.
520
//
521
// Deprecated: the method will be removed in the next major version,
522
// use a CallRequest object + Do() instead.
523
func (conn *Connection) CallAsync(functionName string, args interface{}) *Future {
16✔
524
        req := NewCallRequest(functionName).Args(args)
16✔
525
        return conn.Do(req)
16✔
526
}
16✔
527

528
// Call16Async sends a call to registered Tarantool function and returns Future.
529
// It uses request code for Tarantool 1.6, so future's result is an array of arrays.
530
// Deprecated since Tarantool 1.7.2.
531
//
532
// Deprecated: the method will be removed in the next major version,
533
// use a Call16Request object + Do() instead.
534
func (conn *Connection) Call16Async(functionName string, args interface{}) *Future {
4✔
535
        req := NewCall16Request(functionName).Args(args)
4✔
536
        return conn.Do(req)
4✔
537
}
4✔
538

539
// Call17Async sends a call to registered Tarantool function and returns Future.
540
// It uses request code for Tarantool >= 1.7, so future's result is an array.
541
//
542
// Deprecated: the method will be removed in the next major version,
543
// use a Call17Request object + Do() instead.
544
func (conn *Connection) Call17Async(functionName string, args interface{}) *Future {
14✔
545
        req := NewCall17Request(functionName).Args(args)
14✔
546
        return conn.Do(req)
14✔
547
}
14✔
548

549
// EvalAsync sends a Lua expression for evaluation and returns Future.
550
//
551
// Deprecated: the method will be removed in the next major version,
552
// use an EvalRequest object + Do() instead.
553
func (conn *Connection) EvalAsync(expr string, args interface{}) *Future {
52✔
554
        req := NewEvalRequest(expr).Args(args)
52✔
555
        return conn.Do(req)
52✔
556
}
52✔
557

558
// ExecuteAsync sends a sql expression for execution and returns Future.
559
// Since 1.6.0
560
//
561
// Deprecated: the method will be removed in the next major version,
562
// use an ExecuteRequest object + Do() instead.
563
func (conn *Connection) ExecuteAsync(expr string, args interface{}) *Future {
50✔
564
        req := NewExecuteRequest(expr).Args(args)
50✔
565
        return conn.Do(req)
50✔
566
}
50✔
567

568
// KeyValueBind is a type for encoding named SQL parameters
569
type KeyValueBind struct {
570
        Key   string
571
        Value interface{}
572
}
573

574
//
575
// private
576
//
577

578
// this map is needed for caching names of struct fields in lower case
579
// to avoid extra allocations in heap by calling strings.ToLower()
580
var lowerCaseNames sync.Map
581

582
func encodeSQLBind(enc *msgpack.Encoder, from interface{}) error {
74✔
583
        // internal function for encoding single map in msgpack
74✔
584
        encodeKeyInterface := func(key string, val interface{}) error {
92✔
585
                if err := enc.EncodeMapLen(1); err != nil {
18✔
586
                        return err
×
587
                }
×
588
                if err := enc.EncodeString(":" + key); err != nil {
18✔
589
                        return err
×
590
                }
×
591
                if err := enc.Encode(val); err != nil {
18✔
592
                        return err
×
593
                }
×
594
                return nil
18✔
595
        }
596

597
        encodeKeyValue := func(key string, val reflect.Value) error {
78✔
598
                if err := enc.EncodeMapLen(1); err != nil {
4✔
599
                        return err
×
600
                }
×
601
                if err := enc.EncodeString(":" + key); err != nil {
4✔
602
                        return err
×
603
                }
×
604
                if err := enc.EncodeValue(val); err != nil {
4✔
605
                        return err
×
606
                }
×
607
                return nil
4✔
608
        }
609

610
        encodeNamedFromMap := func(mp map[string]interface{}) error {
78✔
611
                if err := enc.EncodeArrayLen(len(mp)); err != nil {
4✔
612
                        return err
×
613
                }
×
614
                for k, v := range mp {
12✔
615
                        if err := encodeKeyInterface(k, v); err != nil {
8✔
616
                                return err
×
617
                        }
×
618
                }
619
                return nil
4✔
620
        }
621

622
        encodeNamedFromStruct := func(val reflect.Value) error {
76✔
623
                if err := enc.EncodeArrayLen(val.NumField()); err != nil {
2✔
624
                        return err
×
625
                }
×
626
                cached, ok := lowerCaseNames.Load(val.Type())
2✔
627
                if !ok {
4✔
628
                        fields := make([]string, val.NumField())
2✔
629
                        for i := 0; i < val.NumField(); i++ {
6✔
630
                                key := val.Type().Field(i).Name
4✔
631
                                fields[i] = strings.ToLower(key)
4✔
632
                                v := val.Field(i)
4✔
633
                                if err := encodeKeyValue(fields[i], v); err != nil {
4✔
634
                                        return err
×
635
                                }
×
636
                        }
637
                        lowerCaseNames.Store(val.Type(), fields)
2✔
638
                        return nil
2✔
639
                }
640

641
                fields := cached.([]string)
×
642
                for i := 0; i < val.NumField(); i++ {
×
643
                        k := fields[i]
×
644
                        v := val.Field(i)
×
645
                        if err := encodeKeyValue(k, v); err != nil {
×
646
                                return err
×
647
                        }
×
648
                }
649
                return nil
×
650
        }
651

652
        encodeSlice := func(from interface{}) error {
140✔
653
                castedSlice, ok := from.([]interface{})
66✔
654
                if !ok {
68✔
655
                        castedKVSlice := from.([]KeyValueBind)
2✔
656
                        t := len(castedKVSlice)
2✔
657
                        if err := enc.EncodeArrayLen(t); err != nil {
2✔
658
                                return err
×
659
                        }
×
660
                        for _, v := range castedKVSlice {
6✔
661
                                if err := encodeKeyInterface(v.Key, v.Value); err != nil {
4✔
662
                                        return err
×
663
                                }
×
664
                        }
665
                        return nil
2✔
666
                }
667

668
                if err := enc.EncodeArrayLen(len(castedSlice)); err != nil {
64✔
669
                        return err
×
670
                }
×
671
                for i := 0; i < len(castedSlice); i++ {
114✔
672
                        if kvb, ok := castedSlice[i].(KeyValueBind); ok {
56✔
673
                                k := kvb.Key
6✔
674
                                v := kvb.Value
6✔
675
                                if err := encodeKeyInterface(k, v); err != nil {
6✔
676
                                        return err
×
677
                                }
×
678
                        } else {
44✔
679
                                if err := enc.Encode(castedSlice[i]); err != nil {
44✔
680
                                        return err
×
681
                                }
×
682
                        }
683
                }
684
                return nil
64✔
685
        }
686

687
        val := reflect.ValueOf(from)
74✔
688
        switch val.Kind() {
74✔
689
        case reflect.Map:
4✔
690
                mp, ok := from.(map[string]interface{})
4✔
691
                if !ok {
4✔
692
                        return errors.New("failed to encode map: wrong format")
×
693
                }
×
694
                if err := encodeNamedFromMap(mp); err != nil {
4✔
695
                        return err
×
696
                }
×
697
        case reflect.Struct:
2✔
698
                if err := encodeNamedFromStruct(val); err != nil {
2✔
699
                        return err
×
700
                }
×
701
        case reflect.Slice, reflect.Array:
66✔
702
                if err := encodeSlice(from); err != nil {
66✔
703
                        return err
×
704
                }
×
705
        }
706
        return nil
74✔
707
}
708

709
// Request is an interface that provides the necessary data to create a request
710
// that will be sent to a tarantool instance.
711
type Request interface {
712
        // Type returns a IPROTO type of the request.
713
        Type() iproto.Type
714
        // Body fills an msgpack.Encoder with a request body.
715
        Body(resolver SchemaResolver, enc *msgpack.Encoder) error
716
        // Ctx returns a context of the request.
717
        Ctx() context.Context
718
        // Async returns true if the request does not expect response.
719
        Async() bool
720
}
721

722
// ConnectedRequest is an interface that provides the info about a Connection
723
// the request belongs to.
724
type ConnectedRequest interface {
725
        Request
726
        // Conn returns a Connection the request belongs to.
727
        Conn() *Connection
728
}
729

730
type baseRequest struct {
731
        rtype iproto.Type
732
        async bool
733
        ctx   context.Context
734
}
735

736
// Type returns a IPROTO type for the request.
737
func (req *baseRequest) Type() iproto.Type {
4,277✔
738
        return req.rtype
4,277✔
739
}
4,277✔
740

741
// Async returns true if the request does not require a response.
742
func (req *baseRequest) Async() bool {
3,651✔
743
        return req.async
3,651✔
744
}
3,651✔
745

746
// Ctx returns a context of the request.
747
func (req *baseRequest) Ctx() context.Context {
7,349✔
748
        return req.ctx
7,349✔
749
}
7,349✔
750

751
type spaceRequest struct {
752
        baseRequest
753
        space interface{}
754
}
755

756
func (req *spaceRequest) setSpace(space interface{}) {
1,644✔
757
        req.space = space
1,644✔
758
}
1,644✔
759

760
type spaceIndexRequest struct {
761
        spaceRequest
762
        index interface{}
763
}
764

765
func (req *spaceIndexRequest) setIndex(index interface{}) {
1,302✔
766
        req.index = index
1,302✔
767
}
1,302✔
768

769
// authRequest implements IPROTO_AUTH request.
770
type authRequest struct {
771
        auth       Auth
772
        user, pass string
773
}
774

775
// newChapSha1AuthRequest create a new authRequest with chap-sha1
776
// authentication method.
777
func newChapSha1AuthRequest(user, password, salt string) (authRequest, error) {
613✔
778
        req := authRequest{}
613✔
779
        scr, err := scramble(salt, password)
613✔
780
        if err != nil {
613✔
781
                return req, fmt.Errorf("scrambling failure: %w", err)
×
782
        }
×
783

784
        req.auth = ChapSha1Auth
613✔
785
        req.user = user
613✔
786
        req.pass = string(scr)
613✔
787
        return req, nil
613✔
788
}
789

790
// newPapSha256AuthRequest create a new authRequest with pap-sha256
791
// authentication method.
792
func newPapSha256AuthRequest(user, password string) authRequest {
3✔
793
        return authRequest{
3✔
794
                auth: PapSha256Auth,
3✔
795
                user: user,
3✔
796
                pass: password,
3✔
797
        }
3✔
798
}
3✔
799

800
// Type returns a IPROTO type for the request.
801
func (req authRequest) Type() iproto.Type {
616✔
802
        return iproto.IPROTO_AUTH
616✔
803
}
616✔
804

805
// Async returns true if the request does not require a response.
806
func (req authRequest) Async() bool {
×
807
        return false
×
808
}
×
809

810
// Ctx returns a context of the request.
811
func (req authRequest) Ctx() context.Context {
×
812
        return nil
×
813
}
×
814

815
// Body fills an encoder with the auth request body.
816
func (req authRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
616✔
817
        return enc.Encode(map[uint32]interface{}{
616✔
818
                uint32(iproto.IPROTO_USER_NAME): req.user,
616✔
819
                uint32(iproto.IPROTO_TUPLE):     []interface{}{req.auth.String(), req.pass},
616✔
820
        })
616✔
821
}
616✔
822

823
// PingRequest helps you to create an execute request object for execution
824
// by a Connection.
825
type PingRequest struct {
826
        baseRequest
827
}
828

829
// NewPingRequest returns a new PingRequest.
830
func NewPingRequest() *PingRequest {
88✔
831
        req := new(PingRequest)
88✔
832
        req.rtype = iproto.IPROTO_PING
88✔
833
        return req
88✔
834
}
88✔
835

836
// Body fills an msgpack.Encoder with the ping request body.
837
func (req *PingRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
84✔
838
        return fillPing(enc)
84✔
839
}
84✔
840

841
// Context sets a passed context to the request.
842
//
843
// Pay attention that when using context with request objects,
844
// the timeout option for Connection does not affect the lifetime
845
// of the request. For those purposes use context.WithTimeout() as
846
// the root context.
847
func (req *PingRequest) Context(ctx context.Context) *PingRequest {
8✔
848
        req.ctx = ctx
8✔
849
        return req
8✔
850
}
8✔
851

852
// SelectRequest allows you to create a select request object for execution
853
// by a Connection.
854
type SelectRequest struct {
855
        spaceIndexRequest
856
        isIteratorSet, fetchPos bool
857
        offset, limit           uint32
858
        iterator                Iter
859
        key, after              interface{}
860
}
861

862
// NewSelectRequest returns a new empty SelectRequest.
863
func NewSelectRequest(space interface{}) *SelectRequest {
1,252✔
864
        req := new(SelectRequest)
1,252✔
865
        req.rtype = iproto.IPROTO_SELECT
1,252✔
866
        req.setSpace(space)
1,252✔
867
        req.isIteratorSet = false
1,252✔
868
        req.fetchPos = false
1,252✔
869
        req.iterator = IterAll
1,252✔
870
        req.key = []interface{}{}
1,252✔
871
        req.after = nil
1,252✔
872
        req.limit = 0xFFFFFFFF
1,252✔
873
        return req
1,252✔
874
}
1,252✔
875

876
// Index sets the index for the select request.
877
// Note: default value is 0.
878
func (req *SelectRequest) Index(index interface{}) *SelectRequest {
1,230✔
879
        req.setIndex(index)
1,230✔
880
        return req
1,230✔
881
}
1,230✔
882

883
// Offset sets the offset for the select request.
884
// Note: default value is 0.
885
func (req *SelectRequest) Offset(offset uint32) *SelectRequest {
1,192✔
886
        req.offset = offset
1,192✔
887
        return req
1,192✔
888
}
1,192✔
889

890
// Limit sets the limit for the select request.
891
// Note: default value is 0xFFFFFFFF.
892
func (req *SelectRequest) Limit(limit uint32) *SelectRequest {
1,220✔
893
        req.limit = limit
1,220✔
894
        return req
1,220✔
895
}
1,220✔
896

897
// Iterator set the iterator for the select request.
898
// Note: default value is IterAll if key is not set or IterEq otherwise.
899
func (req *SelectRequest) Iterator(iterator Iter) *SelectRequest {
1,228✔
900
        req.iterator = iterator
1,228✔
901
        req.isIteratorSet = true
1,228✔
902
        return req
1,228✔
903
}
1,228✔
904

905
// Key set the key for the select request.
906
// Note: default value is empty.
907
func (req *SelectRequest) Key(key interface{}) *SelectRequest {
1,232✔
908
        req.key = key
1,232✔
909
        if !req.isIteratorSet {
1,236✔
910
                req.iterator = IterEq
4✔
911
        }
4✔
912
        return req
1,232✔
913
}
914

915
// FetchPos determines whether to fetch positions of the last tuple. A position
916
// descriptor will be saved in Response.Pos value.
917
//
918
// Note: default value is false.
919
//
920
// Requires Tarantool >= 2.11.
921
// Since 1.11.0
922
func (req *SelectRequest) FetchPos(fetch bool) *SelectRequest {
10✔
923
        req.fetchPos = fetch
10✔
924
        return req
10✔
925
}
10✔
926

927
// After must contain a tuple from which selection must continue or its
928
// position (a value from Response.Pos).
929
//
930
// Note: default value in nil.
931
//
932
// Requires Tarantool >= 2.11.
933
// Since 1.11.0
934
func (req *SelectRequest) After(after interface{}) *SelectRequest {
8✔
935
        req.after = after
8✔
936
        return req
8✔
937
}
8✔
938

939
// Body fills an encoder with the select request body.
940
func (req *SelectRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
1,282✔
941
        spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index)
1,282✔
942
        if err != nil {
1,288✔
943
                return err
6✔
944
        }
6✔
945

946
        return fillSelect(enc, spaceNo, indexNo, req.offset, req.limit, req.iterator,
1,276✔
947
                req.key, req.after, req.fetchPos)
1,276✔
948
}
949

950
// Context sets a passed context to the request.
951
//
952
// Pay attention that when using context with request objects,
953
// the timeout option for Connection does not affect the lifetime
954
// of the request. For those purposes use context.WithTimeout() as
955
// the root context.
956
func (req *SelectRequest) Context(ctx context.Context) *SelectRequest {
2✔
957
        req.ctx = ctx
2✔
958
        return req
2✔
959
}
2✔
960

961
// InsertRequest helps you to create an insert request object for execution
962
// by a Connection.
963
type InsertRequest struct {
964
        spaceRequest
965
        tuple interface{}
966
}
967

968
// NewInsertRequest returns a new empty InsertRequest.
969
func NewInsertRequest(space interface{}) *InsertRequest {
76✔
970
        req := new(InsertRequest)
76✔
971
        req.rtype = iproto.IPROTO_INSERT
76✔
972
        req.setSpace(space)
76✔
973
        req.tuple = []interface{}{}
76✔
974
        return req
76✔
975
}
76✔
976

977
// Tuple sets the tuple for insertion the insert request.
978
// Note: default value is nil.
979
func (req *InsertRequest) Tuple(tuple interface{}) *InsertRequest {
62✔
980
        req.tuple = tuple
62✔
981
        return req
62✔
982
}
62✔
983

984
// Body fills an msgpack.Encoder with the insert request body.
985
func (req *InsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
68✔
986
        spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil)
68✔
987
        if err != nil {
70✔
988
                return err
2✔
989
        }
2✔
990

991
        return fillInsert(enc, spaceNo, req.tuple)
66✔
992
}
993

994
// Context sets a passed context to the request.
995
//
996
// Pay attention that when using context with request objects,
997
// the timeout option for Connection does not affect the lifetime
998
// of the request. For those purposes use context.WithTimeout() as
999
// the root context.
1000
func (req *InsertRequest) Context(ctx context.Context) *InsertRequest {
2✔
1001
        req.ctx = ctx
2✔
1002
        return req
2✔
1003
}
2✔
1004

1005
// ReplaceRequest helps you to create a replace request object for execution
1006
// by a Connection.
1007
type ReplaceRequest struct {
1008
        spaceRequest
1009
        tuple interface{}
1010
}
1011

1012
// NewReplaceRequest returns a new empty ReplaceRequest.
1013
func NewReplaceRequest(space interface{}) *ReplaceRequest {
180✔
1014
        req := new(ReplaceRequest)
180✔
1015
        req.rtype = iproto.IPROTO_REPLACE
180✔
1016
        req.setSpace(space)
180✔
1017
        req.tuple = []interface{}{}
180✔
1018
        return req
180✔
1019
}
180✔
1020

1021
// Tuple sets the tuple for replace by the replace request.
1022
// Note: default value is nil.
1023
func (req *ReplaceRequest) Tuple(tuple interface{}) *ReplaceRequest {
166✔
1024
        req.tuple = tuple
166✔
1025
        return req
166✔
1026
}
166✔
1027

1028
// Body fills an msgpack.Encoder with the replace request body.
1029
func (req *ReplaceRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
172✔
1030
        spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil)
172✔
1031
        if err != nil {
174✔
1032
                return err
2✔
1033
        }
2✔
1034

1035
        return fillInsert(enc, spaceNo, req.tuple)
170✔
1036
}
1037

1038
// Context sets a passed context to the request.
1039
//
1040
// Pay attention that when using context with request objects,
1041
// the timeout option for Connection does not affect the lifetime
1042
// of the request. For those purposes use context.WithTimeout() as
1043
// the root context.
1044
func (req *ReplaceRequest) Context(ctx context.Context) *ReplaceRequest {
2✔
1045
        req.ctx = ctx
2✔
1046
        return req
2✔
1047
}
2✔
1048

1049
// DeleteRequest helps you to create a delete request object for execution
1050
// by a Connection.
1051
type DeleteRequest struct {
1052
        spaceIndexRequest
1053
        key interface{}
1054
}
1055

1056
// NewDeleteRequest returns a new empty DeleteRequest.
1057
func NewDeleteRequest(space interface{}) *DeleteRequest {
70✔
1058
        req := new(DeleteRequest)
70✔
1059
        req.rtype = iproto.IPROTO_DELETE
70✔
1060
        req.setSpace(space)
70✔
1061
        req.key = []interface{}{}
70✔
1062
        return req
70✔
1063
}
70✔
1064

1065
// Index sets the index for the delete request.
1066
// Note: default value is 0.
1067
func (req *DeleteRequest) Index(index interface{}) *DeleteRequest {
54✔
1068
        req.setIndex(index)
54✔
1069
        return req
54✔
1070
}
54✔
1071

1072
// Key sets the key of tuple for the delete request.
1073
// Note: default value is empty.
1074
func (req *DeleteRequest) Key(key interface{}) *DeleteRequest {
50✔
1075
        req.key = key
50✔
1076
        return req
50✔
1077
}
50✔
1078

1079
// Body fills an msgpack.Encoder with the delete request body.
1080
func (req *DeleteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
62✔
1081
        spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index)
62✔
1082
        if err != nil {
68✔
1083
                return err
6✔
1084
        }
6✔
1085

1086
        return fillDelete(enc, spaceNo, indexNo, req.key)
56✔
1087
}
1088

1089
// Context sets a passed context to the request.
1090
//
1091
// Pay attention that when using context with request objects,
1092
// the timeout option for Connection does not affect the lifetime
1093
// of the request. For those purposes use context.WithTimeout() as
1094
// the root context.
1095
func (req *DeleteRequest) Context(ctx context.Context) *DeleteRequest {
2✔
1096
        req.ctx = ctx
2✔
1097
        return req
2✔
1098
}
2✔
1099

1100
// UpdateRequest helps you to create an update request object for execution
1101
// by a Connection.
1102
type UpdateRequest struct {
1103
        spaceIndexRequest
1104
        key interface{}
1105
        ops interface{}
1106
}
1107

1108
// NewUpdateRequest returns a new empty UpdateRequest.
1109
func NewUpdateRequest(space interface{}) *UpdateRequest {
34✔
1110
        req := new(UpdateRequest)
34✔
1111
        req.rtype = iproto.IPROTO_UPDATE
34✔
1112
        req.setSpace(space)
34✔
1113
        req.key = []interface{}{}
34✔
1114
        req.ops = []interface{}{}
34✔
1115
        return req
34✔
1116
}
34✔
1117

1118
// Index sets the index for the update request.
1119
// Note: default value is 0.
1120
func (req *UpdateRequest) Index(index interface{}) *UpdateRequest {
18✔
1121
        req.setIndex(index)
18✔
1122
        return req
18✔
1123
}
18✔
1124

1125
// Key sets the key of tuple for the update request.
1126
// Note: default value is empty.
1127
func (req *UpdateRequest) Key(key interface{}) *UpdateRequest {
14✔
1128
        req.key = key
14✔
1129
        return req
14✔
1130
}
14✔
1131

1132
// Operations sets operations to be performed on update.
1133
// Note: default value is empty.
1134
func (req *UpdateRequest) Operations(ops *Operations) *UpdateRequest {
8✔
1135
        if ops != nil {
16✔
1136
                req.ops = ops.ops
8✔
1137
        }
8✔
1138
        return req
8✔
1139
}
1140

1141
// Body fills an msgpack.Encoder with the update request body.
1142
func (req *UpdateRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
26✔
1143
        spaceNo, indexNo, err := res.ResolveSpaceIndex(req.space, req.index)
26✔
1144
        if err != nil {
32✔
1145
                return err
6✔
1146
        }
6✔
1147

1148
        return fillUpdate(enc, spaceNo, indexNo, req.key, req.ops)
20✔
1149
}
1150

1151
// Context sets a passed context to the request.
1152
//
1153
// Pay attention that when using context with request objects,
1154
// the timeout option for Connection does not affect the lifetime
1155
// of the request. For those purposes use context.WithTimeout() as
1156
// the root context.
1157
func (req *UpdateRequest) Context(ctx context.Context) *UpdateRequest {
2✔
1158
        req.ctx = ctx
2✔
1159
        return req
2✔
1160
}
2✔
1161

1162
// UpsertRequest helps you to create an upsert request object for execution
1163
// by a Connection.
1164
type UpsertRequest struct {
1165
        spaceRequest
1166
        tuple interface{}
1167
        ops   interface{}
1168
}
1169

1170
// NewUpsertRequest returns a new empty UpsertRequest.
1171
func NewUpsertRequest(space interface{}) *UpsertRequest {
32✔
1172
        req := new(UpsertRequest)
32✔
1173
        req.rtype = iproto.IPROTO_UPSERT
32✔
1174
        req.setSpace(space)
32✔
1175
        req.tuple = []interface{}{}
32✔
1176
        req.ops = []interface{}{}
32✔
1177
        return req
32✔
1178
}
32✔
1179

1180
// Tuple sets the tuple for insertion or update by the upsert request.
1181
// Note: default value is empty.
1182
func (req *UpsertRequest) Tuple(tuple interface{}) *UpsertRequest {
18✔
1183
        req.tuple = tuple
18✔
1184
        return req
18✔
1185
}
18✔
1186

1187
// Operations sets operations to be performed on update case by the upsert request.
1188
// Note: default value is empty.
1189
func (req *UpsertRequest) Operations(ops *Operations) *UpsertRequest {
8✔
1190
        if ops != nil {
16✔
1191
                req.ops = ops.ops
8✔
1192
        }
8✔
1193
        return req
8✔
1194
}
1195

1196
// Body fills an msgpack.Encoder with the upsert request body.
1197
func (req *UpsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
24✔
1198
        spaceNo, _, err := res.ResolveSpaceIndex(req.space, nil)
24✔
1199
        if err != nil {
26✔
1200
                return err
2✔
1201
        }
2✔
1202

1203
        return fillUpsert(enc, spaceNo, req.tuple, req.ops)
22✔
1204
}
1205

1206
// Context sets a passed context to the request.
1207
//
1208
// Pay attention that when using context with request objects,
1209
// the timeout option for Connection does not affect the lifetime
1210
// of the request. For those purposes use context.WithTimeout() as
1211
// the root context.
1212
func (req *UpsertRequest) Context(ctx context.Context) *UpsertRequest {
2✔
1213
        req.ctx = ctx
2✔
1214
        return req
2✔
1215
}
2✔
1216

1217
// CallRequest helps you to create a call request object for execution
1218
// by a Connection.
1219
type CallRequest struct {
1220
        baseRequest
1221
        function string
1222
        args     interface{}
1223
}
1224

1225
// NewCallRequest returns a new empty CallRequest. It uses request code for
1226
// Tarantool >= 1.7.
1227
func NewCallRequest(function string) *CallRequest {
320✔
1228
        req := new(CallRequest)
320✔
1229
        req.rtype = iproto.IPROTO_CALL
320✔
1230
        req.function = function
320✔
1231
        return req
320✔
1232
}
320✔
1233

1234
// Args sets the args for the call request.
1235
// Note: default value is empty.
1236
func (req *CallRequest) Args(args interface{}) *CallRequest {
116✔
1237
        req.args = args
116✔
1238
        return req
116✔
1239
}
116✔
1240

1241
// Body fills an encoder with the call request body.
1242
func (req *CallRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
288✔
1243
        args := req.args
288✔
1244
        if args == nil {
496✔
1245
                args = []interface{}{}
208✔
1246
        }
208✔
1247
        return fillCall(enc, req.function, args)
288✔
1248
}
1249

1250
// Context sets a passed context to the request.
1251
//
1252
// Pay attention that when using context with request objects,
1253
// the timeout option for Connection does not affect the lifetime
1254
// of the request. For those purposes use context.WithTimeout() as
1255
// the root context.
1256
func (req *CallRequest) Context(ctx context.Context) *CallRequest {
8✔
1257
        req.ctx = ctx
8✔
1258
        return req
8✔
1259
}
8✔
1260

1261
// NewCall16Request returns a new empty Call16Request. It uses request code for
1262
// Tarantool 1.6.
1263
// Deprecated since Tarantool 1.7.2.
1264
func NewCall16Request(function string) *CallRequest {
18✔
1265
        req := NewCallRequest(function)
18✔
1266
        req.rtype = iproto.IPROTO_CALL_16
18✔
1267
        return req
18✔
1268
}
18✔
1269

1270
// NewCall17Request returns a new empty CallRequest. It uses request code for
1271
// Tarantool >= 1.7.
1272
func NewCall17Request(function string) *CallRequest {
28✔
1273
        req := NewCallRequest(function)
28✔
1274
        req.rtype = iproto.IPROTO_CALL
28✔
1275
        return req
28✔
1276
}
28✔
1277

1278
// EvalRequest helps you to create an eval request object for execution
1279
// by a Connection.
1280
type EvalRequest struct {
1281
        baseRequest
1282
        expr string
1283
        args interface{}
1284
}
1285

1286
// NewEvalRequest returns a new empty EvalRequest.
1287
func NewEvalRequest(expr string) *EvalRequest {
182✔
1288
        req := new(EvalRequest)
182✔
1289
        req.rtype = iproto.IPROTO_EVAL
182✔
1290
        req.expr = expr
182✔
1291
        req.args = []interface{}{}
182✔
1292
        return req
182✔
1293
}
182✔
1294

1295
// Args sets the args for the eval request.
1296
// Note: default value is empty.
1297
func (req *EvalRequest) Args(args interface{}) *EvalRequest {
168✔
1298
        req.args = args
168✔
1299
        return req
168✔
1300
}
168✔
1301

1302
// Body fills an msgpack.Encoder with the eval request body.
1303
func (req *EvalRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
174✔
1304
        return fillEval(enc, req.expr, req.args)
174✔
1305
}
174✔
1306

1307
// Context sets a passed context to the request.
1308
//
1309
// Pay attention that when using context with request objects,
1310
// the timeout option for Connection does not affect the lifetime
1311
// of the request. For those purposes use context.WithTimeout() as
1312
// the root context.
1313
func (req *EvalRequest) Context(ctx context.Context) *EvalRequest {
2✔
1314
        req.ctx = ctx
2✔
1315
        return req
2✔
1316
}
2✔
1317

1318
// ExecuteRequest helps you to create an execute request object for execution
1319
// by a Connection.
1320
type ExecuteRequest struct {
1321
        baseRequest
1322
        expr string
1323
        args interface{}
1324
}
1325

1326
// NewExecuteRequest returns a new empty ExecuteRequest.
1327
func NewExecuteRequest(expr string) *ExecuteRequest {
66✔
1328
        req := new(ExecuteRequest)
66✔
1329
        req.rtype = iproto.IPROTO_EXECUTE
66✔
1330
        req.expr = expr
66✔
1331
        req.args = []interface{}{}
66✔
1332
        return req
66✔
1333
}
66✔
1334

1335
// Args sets the args for the execute request.
1336
// Note: default value is empty.
1337
func (req *ExecuteRequest) Args(args interface{}) *ExecuteRequest {
52✔
1338
        req.args = args
52✔
1339
        return req
52✔
1340
}
52✔
1341

1342
// Body fills an msgpack.Encoder with the execute request body.
1343
func (req *ExecuteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
58✔
1344
        return fillExecute(enc, req.expr, req.args)
58✔
1345
}
58✔
1346

1347
// Context sets a passed context to the request.
1348
//
1349
// Pay attention that when using context with request objects,
1350
// the timeout option for Connection does not affect the lifetime
1351
// of the request. For those purposes use context.WithTimeout() as
1352
// the root context.
1353
func (req *ExecuteRequest) Context(ctx context.Context) *ExecuteRequest {
2✔
1354
        req.ctx = ctx
2✔
1355
        return req
2✔
1356
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc