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

tarantool / go-tarantool / 6933294594

20 Nov 2023 04:56PM UTC coverage: 79.76% (+0.08%) from 79.68%
6933294594

Pull #349

github

askalt
docs: update according to the changes
Pull Request #349: connection: support connection via an existing socket fd

255 of 309 new or added lines in 7 files covered. (82.52%)

24 existing lines in 3 files now uncovered.

5647 of 7080 relevant lines covered (79.76%)

11113.95 hits per line

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

80.73
/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
type spaceEncoder struct {
16
        Id   uint32
17
        Name string
18
        IsId bool
19
}
20

21
func newSpaceEncoder(res SchemaResolver, spaceInfo interface{}) (spaceEncoder, error) {
1,698✔
22
        if res.NamesUseSupported() {
2,575✔
23
                if spaceName, ok := spaceInfo.(string); ok {
1,026✔
24
                        return spaceEncoder{
149✔
25
                                Id:   0,
149✔
26
                                Name: spaceName,
149✔
27
                                IsId: false,
149✔
28
                        }, nil
149✔
29
                }
149✔
30
        }
31

32
        spaceId, err := res.ResolveSpace(spaceInfo)
1,549✔
33
        return spaceEncoder{
1,549✔
34
                Id:   spaceId,
1,549✔
35
                IsId: true,
1,549✔
36
        }, err
1,549✔
37
}
38

39
func (e spaceEncoder) Encode(enc *msgpack.Encoder) error {
1,674✔
40
        if e.IsId {
3,199✔
41
                if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_ID)); err != nil {
1,525✔
42
                        return err
×
43
                }
×
44
                return enc.EncodeUint(uint64(e.Id))
1,525✔
45
        }
46
        if err := enc.EncodeUint(uint64(iproto.IPROTO_SPACE_NAME)); err != nil {
149✔
47
                return err
×
48
        }
×
49
        return enc.EncodeString(e.Name)
149✔
50
}
51

52
type indexEncoder struct {
53
        Id   uint32
54
        Name string
55
        IsId bool
56
}
57

58
func newIndexEncoder(res SchemaResolver, indexInfo interface{},
59
        spaceNo uint32) (indexEncoder, error) {
1,396✔
60
        if res.NamesUseSupported() {
2,116✔
61
                if indexName, ok := indexInfo.(string); ok {
753✔
62
                        return indexEncoder{
33✔
63
                                Name: indexName,
33✔
64
                                IsId: false,
33✔
65
                        }, nil
33✔
66
                }
33✔
67
        }
68

69
        indexId, err := res.ResolveIndex(indexInfo, spaceNo)
1,363✔
70
        return indexEncoder{
1,363✔
71
                Id:   indexId,
1,363✔
72
                IsId: true,
1,363✔
73
        }, err
1,363✔
74
}
75

76
func (e indexEncoder) Encode(enc *msgpack.Encoder) error {
1,390✔
77
        if e.IsId {
2,747✔
78
                if err := enc.EncodeUint(uint64(iproto.IPROTO_INDEX_ID)); err != nil {
1,357✔
79
                        return err
×
80
                }
×
81
                return enc.EncodeUint(uint64(e.Id))
1,357✔
82
        }
83
        if err := enc.EncodeUint(uint64(iproto.IPROTO_INDEX_NAME)); err != nil {
33✔
84
                return err
×
85
        }
×
86
        return enc.EncodeString(e.Name)
33✔
87
}
88

89
func fillSearch(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder,
90
        key interface{}) error {
1,390✔
91
        if err := spaceEnc.Encode(enc); err != nil {
1,390✔
92
                return err
×
93
        }
×
94

95
        if err := indexEnc.Encode(enc); err != nil {
1,390✔
96
                return err
×
97
        }
×
98

99
        if err := enc.EncodeUint(uint64(iproto.IPROTO_KEY)); err != nil {
1,390✔
100
                return err
×
101
        }
×
102
        return enc.Encode(key)
1,390✔
103
}
104

105
func fillIterator(enc *msgpack.Encoder, offset, limit uint32, iterator Iter) error {
1,292✔
106
        if err := enc.EncodeUint(uint64(iproto.IPROTO_ITERATOR)); err != nil {
1,292✔
107
                return err
×
108
        }
×
109
        if err := enc.EncodeUint(uint64(iterator)); err != nil {
1,292✔
110
                return err
×
111
        }
×
112
        if err := enc.EncodeUint(uint64(iproto.IPROTO_OFFSET)); err != nil {
1,292✔
113
                return err
×
114
        }
×
115
        if err := enc.EncodeUint(uint64(offset)); err != nil {
1,292✔
116
                return err
×
117
        }
×
118
        if err := enc.EncodeUint(uint64(iproto.IPROTO_LIMIT)); err != nil {
1,292✔
119
                return err
×
120
        }
×
121
        return enc.EncodeUint(uint64(limit))
1,292✔
122
}
123

124
func fillInsert(enc *msgpack.Encoder, spaceEnc spaceEncoder, tuple interface{}) error {
254✔
125
        if err := enc.EncodeMapLen(2); err != nil {
254✔
126
                return err
×
127
        }
×
128
        if err := spaceEnc.Encode(enc); err != nil {
254✔
129
                return err
×
130
        }
×
131

132
        if err := enc.EncodeUint(uint64(iproto.IPROTO_TUPLE)); err != nil {
254✔
133
                return err
×
134
        }
×
135
        return enc.Encode(tuple)
254✔
136
}
137

138
func fillSelect(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder,
139
        offset, limit uint32, iterator Iter, key, after interface{}, fetchPos bool) error {
1,292✔
140
        mapLen := 6
1,292✔
141
        if fetchPos {
1,308✔
142
                mapLen += 1
16✔
143
        }
16✔
144
        if after != nil {
1,304✔
145
                mapLen += 1
12✔
146
        }
12✔
147
        if err := enc.EncodeMapLen(mapLen); err != nil {
1,292✔
148
                return err
×
149
        }
×
150
        if err := fillIterator(enc, offset, limit, iterator); err != nil {
1,292✔
151
                return err
×
152
        }
×
153
        if err := fillSearch(enc, spaceEnc, indexEnc, key); err != nil {
1,292✔
154
                return err
×
155
        }
×
156
        if fetchPos {
1,308✔
157
                if err := enc.EncodeUint(uint64(iproto.IPROTO_FETCH_POSITION)); err != nil {
16✔
158
                        return err
×
159
                }
×
160
                if err := enc.EncodeBool(fetchPos); err != nil {
16✔
161
                        return err
×
162
                }
×
163
        }
164
        if after != nil {
1,304✔
165
                if pos, ok := after.([]byte); ok {
18✔
166
                        if err := enc.EncodeUint(uint64(iproto.IPROTO_AFTER_POSITION)); err != nil {
6✔
167
                                return err
×
168
                        }
×
169
                        if err := enc.EncodeString(string(pos)); err != nil {
6✔
170
                                return err
×
171
                        }
×
172
                } else {
6✔
173
                        if err := enc.EncodeUint(uint64(iproto.IPROTO_AFTER_TUPLE)); err != nil {
6✔
174
                                return err
×
175
                        }
×
176
                        if err := enc.Encode(after); err != nil {
6✔
177
                                return err
×
178
                        }
×
179
                }
180
        }
181
        return nil
1,292✔
182
}
183

184
func fillUpdate(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder,
185
        key interface{}, ops *Operations) error {
30✔
186
        enc.EncodeMapLen(4)
30✔
187
        if err := fillSearch(enc, spaceEnc, indexEnc, key); err != nil {
30✔
188
                return err
×
189
        }
×
190
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
30✔
191
        if ops == nil {
48✔
192
                return enc.Encode([]interface{}{})
18✔
193
        }
18✔
194
        return enc.Encode(ops)
12✔
195
}
196

197
func fillUpsert(enc *msgpack.Encoder, spaceEnc spaceEncoder, tuple interface{},
198
        ops *Operations) error {
30✔
199
        enc.EncodeMapLen(3)
30✔
200
        if err := spaceEnc.Encode(enc); err != nil {
30✔
201
                return err
×
202
        }
×
203

204
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
30✔
205
        if err := enc.Encode(tuple); err != nil {
30✔
206
                return err
×
207
        }
×
208
        enc.EncodeUint(uint64(iproto.IPROTO_OPS))
30✔
209
        if ops == nil {
42✔
210
                return enc.Encode([]interface{}{})
12✔
211
        }
12✔
212
        return enc.Encode(ops)
18✔
213
}
214

215
func fillDelete(enc *msgpack.Encoder, spaceEnc spaceEncoder, indexEnc indexEncoder,
216
        key interface{}) error {
68✔
217
        enc.EncodeMapLen(3)
68✔
218
        return fillSearch(enc, spaceEnc, indexEnc, key)
68✔
219
}
68✔
220

221
func fillCall(enc *msgpack.Encoder, functionName string, args interface{}) error {
299✔
222
        enc.EncodeMapLen(2)
299✔
223
        enc.EncodeUint(uint64(iproto.IPROTO_FUNCTION_NAME))
299✔
224
        enc.EncodeString(functionName)
299✔
225
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
299✔
226
        return enc.Encode(args)
299✔
227
}
299✔
228

229
func fillEval(enc *msgpack.Encoder, expr string, args interface{}) error {
179✔
230
        enc.EncodeMapLen(2)
179✔
231
        enc.EncodeUint(uint64(iproto.IPROTO_EXPR))
179✔
232
        enc.EncodeString(expr)
179✔
233
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
179✔
234
        return enc.Encode(args)
179✔
235
}
179✔
236

237
func fillExecute(enc *msgpack.Encoder, expr string, args interface{}) error {
62✔
238
        enc.EncodeMapLen(2)
62✔
239
        enc.EncodeUint(uint64(iproto.IPROTO_SQL_TEXT))
62✔
240
        enc.EncodeString(expr)
62✔
241
        enc.EncodeUint(uint64(iproto.IPROTO_SQL_BIND))
62✔
242
        return encodeSQLBind(enc, args)
62✔
243
}
62✔
244

245
func fillPing(enc *msgpack.Encoder) error {
92✔
246
        return enc.EncodeMapLen(0)
92✔
247
}
92✔
248

249
func fillWatchOnce(enc *msgpack.Encoder, key string) error {
6✔
250
        if err := enc.EncodeMapLen(1); err != nil {
6✔
251
                return err
×
252
        }
×
253
        if err := enc.EncodeUint(uint64(iproto.IPROTO_EVENT_KEY)); err != nil {
6✔
254
                return err
×
255
        }
×
256
        return enc.EncodeString(key)
6✔
257
}
258

259
// Ping sends empty request to Tarantool to check connection.
260
//
261
// Deprecated: the method will be removed in the next major version,
262
// use a PingRequest object + Do() instead.
263
func (conn *Connection) Ping() (*Response, error) {
4✔
264
        return conn.Do(NewPingRequest()).Get()
4✔
265
}
4✔
266

267
// Select performs select to box space.
268
//
269
// It is equal to conn.SelectAsync(...).Get().
270
//
271
// Deprecated: the method will be removed in the next major version,
272
// use a SelectRequest object + Do() instead.
273
func (conn *Connection) Select(space, index interface{}, offset, limit uint32, iterator Iter,
274
        key interface{}) (*Response, error) {
12✔
275
        return conn.SelectAsync(space, index, offset, limit, iterator, key).Get()
12✔
276
}
12✔
277

278
// Insert performs insertion to box space.
279
// Tarantool will reject Insert when tuple with same primary key exists.
280
//
281
// It is equal to conn.InsertAsync(space, tuple).Get().
282
//
283
// Deprecated: the method will be removed in the next major version,
284
// use an InsertRequest object + Do() instead.
285
func (conn *Connection) Insert(space interface{}, tuple interface{}) (*Response, error) {
12✔
286
        return conn.InsertAsync(space, tuple).Get()
12✔
287
}
12✔
288

289
// Replace performs "insert or replace" action to box space.
290
// If tuple with same primary key exists, it will be replaced.
291
//
292
// It is equal to conn.ReplaceAsync(space, tuple).Get().
293
//
294
// Deprecated: the method will be removed in the next major version,
295
// use a ReplaceRequest object + Do() instead.
296
func (conn *Connection) Replace(space interface{}, tuple interface{}) (*Response, error) {
48✔
297
        return conn.ReplaceAsync(space, tuple).Get()
48✔
298
}
48✔
299

300
// Delete performs deletion of a tuple by key.
301
// Result will contain array with deleted tuple.
302
//
303
// It is equal to conn.DeleteAsync(space, tuple).Get().
304
//
305
// Deprecated: the method will be removed in the next major version,
306
// use a DeleteRequest object + Do() instead.
307
func (conn *Connection) Delete(space, index interface{}, key interface{}) (*Response, error) {
26✔
308
        return conn.DeleteAsync(space, index, key).Get()
26✔
309
}
26✔
310

311
// Update performs update of a tuple by key.
312
// Result will contain array with updated tuple.
313
//
314
// It is equal to conn.UpdateAsync(space, tuple).Get().
315
//
316
// Deprecated: the method will be removed in the next major version,
317
// use a UpdateRequest object + Do() instead.
318
func (conn *Connection) Update(space, index, key interface{}, ops *Operations) (*Response, error) {
4✔
319
        return conn.UpdateAsync(space, index, key, ops).Get()
4✔
320
}
4✔
321

322
// Upsert performs "update or insert" action of a tuple by key.
323
// Result will not contain any tuple.
324
//
325
// It is equal to conn.UpsertAsync(space, tuple, ops).Get().
326
//
327
// Deprecated: the method will be removed in the next major version,
328
// use a UpsertRequest object + Do() instead.
329
func (conn *Connection) Upsert(space, tuple interface{}, ops *Operations) (*Response, error) {
8✔
330
        return conn.UpsertAsync(space, tuple, ops).Get()
8✔
331
}
8✔
332

333
// Call calls registered Tarantool function.
334
// It uses request code for Tarantool >= 1.7, result is an array.
335
//
336
// It is equal to conn.CallAsync(functionName, args).Get().
337
//
338
// Deprecated: the method will be removed in the next major version,
339
// use a CallRequest object + Do() instead.
340
func (conn *Connection) Call(functionName string, args interface{}) (*Response, error) {
16✔
341
        return conn.CallAsync(functionName, args).Get()
16✔
342
}
16✔
343

344
// Call16 calls registered Tarantool function.
345
// It uses request code for Tarantool 1.6, result is an array of arrays.
346
// Deprecated since Tarantool 1.7.2.
347
//
348
// It is equal to conn.Call16Async(functionName, args).Get().
349
//
350
// Deprecated: the method will be removed in the next major version,
351
// use a Call16Request object + Do() instead.
352
func (conn *Connection) Call16(functionName string, args interface{}) (*Response, error) {
4✔
353
        return conn.Call16Async(functionName, args).Get()
4✔
354
}
4✔
355

356
// Call17 calls registered Tarantool function.
357
// It uses request code for Tarantool >= 1.7, result is an array.
358
//
359
// It is equal to conn.Call17Async(functionName, args).Get().
360
//
361
// Deprecated: the method will be removed in the next major version,
362
// use a Call17Request object + Do() instead.
363
func (conn *Connection) Call17(functionName string, args interface{}) (*Response, error) {
2✔
364
        return conn.Call17Async(functionName, args).Get()
2✔
365
}
2✔
366

367
// Eval passes Lua expression for evaluation.
368
//
369
// It is equal to conn.EvalAsync(space, tuple).Get().
370
//
371
// Deprecated: the method will be removed in the next major version,
372
// use an EvalRequest object + Do() instead.
373
func (conn *Connection) Eval(expr string, args interface{}) (*Response, error) {
46✔
374
        return conn.EvalAsync(expr, args).Get()
46✔
375
}
46✔
376

377
// Execute passes sql expression to Tarantool for execution.
378
//
379
// It is equal to conn.ExecuteAsync(expr, args).Get().
380
// Since 1.6.0
381
//
382
// Deprecated: the method will be removed in the next major version,
383
// use an ExecuteRequest object + Do() instead.
384
func (conn *Connection) Execute(expr string, args interface{}) (*Response, error) {
48✔
385
        return conn.ExecuteAsync(expr, args).Get()
48✔
386
}
48✔
387

388
// single used for conn.GetTyped for decode one tuple.
389
type single struct {
390
        res   interface{}
391
        found bool
392
}
393

394
func (s *single) DecodeMsgpack(d *msgpack.Decoder) error {
4✔
395
        var err error
4✔
396
        var len int
4✔
397
        if len, err = d.DecodeArrayLen(); err != nil {
4✔
398
                return err
×
399
        }
×
400
        if s.found = len >= 1; !s.found {
6✔
401
                return nil
2✔
402
        }
2✔
403
        if len != 1 {
2✔
404
                return errors.New("tarantool returns unexpected value for Select(limit=1)")
×
405
        }
×
406
        return d.Decode(s.res)
2✔
407
}
408

409
// GetTyped performs select (with limit = 1 and offset = 0)
410
// to box space and fills typed result.
411
//
412
// It is equal to conn.SelectAsync(space, index, 0, 1, IterEq, key).GetTyped(&result)
413
//
414
// Deprecated: the method will be removed in the next major version,
415
// use a SelectRequest object + Do() instead.
416
func (conn *Connection) GetTyped(space, index interface{}, key interface{},
417
        result interface{}) error {
4✔
418
        s := single{res: result}
4✔
419
        return conn.SelectAsync(space, index, 0, 1, IterEq, key).GetTyped(&s)
4✔
420
}
4✔
421

422
// SelectTyped performs select to box space and fills typed result.
423
//
424
// It is equal to conn.SelectAsync(space, index, offset, limit, iterator, key).GetTyped(&result)
425
//
426
// Deprecated: the method will be removed in the next major version,
427
// use a SelectRequest object + Do() instead.
428
func (conn *Connection) SelectTyped(space, index interface{}, offset, limit uint32, iterator Iter,
429
        key interface{}, result interface{}) error {
1,166✔
430
        return conn.SelectAsync(space, index, offset, limit, iterator, key).GetTyped(result)
1,166✔
431
}
1,166✔
432

433
// InsertTyped performs insertion to box space.
434
// Tarantool will reject Insert when tuple with same primary key exists.
435
//
436
// It is equal to conn.InsertAsync(space, tuple).GetTyped(&result).
437
//
438
// Deprecated: the method will be removed in the next major version,
439
// use an InsertRequest object + Do() instead.
440
func (conn *Connection) InsertTyped(space interface{}, tuple interface{},
441
        result interface{}) error {
6✔
442
        return conn.InsertAsync(space, tuple).GetTyped(result)
6✔
443
}
6✔
444

445
// ReplaceTyped performs "insert or replace" action to box space.
446
// If tuple with same primary key exists, it will be replaced.
447
//
448
// It is equal to conn.ReplaceAsync(space, tuple).GetTyped(&result).
449
//
450
// Deprecated: the method will be removed in the next major version,
451
// use a ReplaceRequest object + Do() instead.
452
func (conn *Connection) ReplaceTyped(space interface{}, tuple interface{},
453
        result interface{}) error {
×
454
        return conn.ReplaceAsync(space, tuple).GetTyped(result)
×
455
}
×
456

457
// DeleteTyped performs deletion of a tuple by key and fills result with deleted tuple.
458
//
459
// It is equal to conn.DeleteAsync(space, tuple).GetTyped(&result).
460
//
461
// Deprecated: the method will be removed in the next major version,
462
// use a DeleteRequest object + Do() instead.
463
func (conn *Connection) DeleteTyped(space, index interface{}, key interface{},
464
        result interface{}) error {
×
465
        return conn.DeleteAsync(space, index, key).GetTyped(result)
×
466
}
×
467

468
// UpdateTyped performs update of a tuple by key and fills result with updated tuple.
469
//
470
// It is equal to conn.UpdateAsync(space, tuple, ops).GetTyped(&result).
471
//
472
// Deprecated: the method will be removed in the next major version,
473
// use a UpdateRequest object + Do() instead.
474
func (conn *Connection) UpdateTyped(space, index interface{}, key interface{},
475
        ops *Operations, result interface{}) error {
×
476
        return conn.UpdateAsync(space, index, key, ops).GetTyped(result)
×
477
}
×
478

479
// CallTyped calls registered function.
480
// It uses request code for Tarantool >= 1.7, result is an array.
481
//
482
// It is equal to conn.Call16Async(functionName, args).GetTyped(&result).
483
//
484
// Deprecated: the method will be removed in the next major version,
485
// use a CallRequest object + Do() instead.
486
func (conn *Connection) CallTyped(functionName string, args interface{},
487
        result interface{}) error {
×
488
        return conn.CallAsync(functionName, args).GetTyped(result)
×
489
}
×
490

491
// Call16Typed calls registered function.
492
// It uses request code for Tarantool 1.6, result is an array of arrays.
493
// Deprecated since Tarantool 1.7.2.
494
//
495
// It is equal to conn.Call16Async(functionName, args).GetTyped(&result).
496
//
497
// Deprecated: the method will be removed in the next major version,
498
// use a Call16Request object + Do() instead.
499
func (conn *Connection) Call16Typed(functionName string, args interface{},
500
        result interface{}) error {
×
501
        return conn.Call16Async(functionName, args).GetTyped(result)
×
502
}
×
503

504
// Call17Typed calls registered function.
505
// It uses request code for Tarantool >= 1.7, result is an array.
506
//
507
// It is equal to conn.Call17Async(functionName, args).GetTyped(&result).
508
//
509
// Deprecated: the method will be removed in the next major version,
510
// use a Call17Request object + Do() instead.
511
func (conn *Connection) Call17Typed(functionName string, args interface{},
512
        result interface{}) error {
×
513
        return conn.Call17Async(functionName, args).GetTyped(result)
×
514
}
×
515

516
// EvalTyped passes Lua expression for evaluation.
517
//
518
// It is equal to conn.EvalAsync(space, tuple).GetTyped(&result).
519
//
520
// Deprecated: the method will be removed in the next major version,
521
// use an EvalRequest object + Do() instead.
522
func (conn *Connection) EvalTyped(expr string, args interface{}, result interface{}) error {
7✔
523
        return conn.EvalAsync(expr, args).GetTyped(result)
7✔
524
}
7✔
525

526
// ExecuteTyped passes sql expression to Tarantool for execution.
527
//
528
// In addition to error returns sql info and columns meta data
529
// Since 1.6.0
530
//
531
// Deprecated: the method will be removed in the next major version,
532
// use an ExecuteRequest object + Do() instead.
533
func (conn *Connection) ExecuteTyped(expr string, args interface{},
534
        result interface{}) (SQLInfo, []ColumnMetaData, error) {
2✔
535
        fut := conn.ExecuteAsync(expr, args)
2✔
536
        err := fut.GetTyped(&result)
2✔
537
        return fut.resp.SQLInfo, fut.resp.MetaData, err
2✔
538
}
2✔
539

540
// SelectAsync sends select request to Tarantool and returns Future.
541
//
542
// Deprecated: the method will be removed in the next major version,
543
// use a SelectRequest object + Do() instead.
544
func (conn *Connection) SelectAsync(space, index interface{}, offset, limit uint32, iterator Iter,
545
        key interface{}) *Future {
1,182✔
546
        req := NewSelectRequest(space).
1,182✔
547
                Index(index).
1,182✔
548
                Offset(offset).
1,182✔
549
                Limit(limit).
1,182✔
550
                Iterator(iterator).
1,182✔
551
                Key(key)
1,182✔
552
        return conn.Do(req)
1,182✔
553
}
1,182✔
554

555
// InsertAsync sends insert action to Tarantool and returns Future.
556
// Tarantool will reject Insert when tuple with same primary key exists.
557
//
558
// Deprecated: the method will be removed in the next major version,
559
// use an InsertRequest object + Do() instead.
560
func (conn *Connection) InsertAsync(space interface{}, tuple interface{}) *Future {
18✔
561
        req := NewInsertRequest(space).Tuple(tuple)
18✔
562
        return conn.Do(req)
18✔
563
}
18✔
564

565
// ReplaceAsync sends "insert or replace" action to Tarantool and returns Future.
566
// If tuple with same primary key exists, it will be replaced.
567
//
568
// Deprecated: the method will be removed in the next major version,
569
// use a ReplaceRequest object + Do() instead.
570
func (conn *Connection) ReplaceAsync(space interface{}, tuple interface{}) *Future {
48✔
571
        req := NewReplaceRequest(space).Tuple(tuple)
48✔
572
        return conn.Do(req)
48✔
573
}
48✔
574

575
// DeleteAsync sends deletion action to Tarantool and returns Future.
576
// Future's result will contain array with deleted tuple.
577
//
578
// Deprecated: the method will be removed in the next major version,
579
// use a DeleteRequest object + Do() instead.
580
func (conn *Connection) DeleteAsync(space, index interface{}, key interface{}) *Future {
26✔
581
        req := NewDeleteRequest(space).Index(index).Key(key)
26✔
582
        return conn.Do(req)
26✔
583
}
26✔
584

585
// Update sends deletion of a tuple by key and returns Future.
586
// Future's result will contain array with updated tuple.
587
//
588
// Deprecated: the method will be removed in the next major version,
589
// use a UpdateRequest object + Do() instead.
590
func (conn *Connection) UpdateAsync(space, index interface{}, key interface{},
591
        ops *Operations) *Future {
4✔
592
        req := NewUpdateRequest(space).Index(index).Key(key)
4✔
593
        req.ops = ops
4✔
594
        return conn.Do(req)
4✔
595
}
4✔
596

597
// UpsertAsync sends "update or insert" action to Tarantool and returns Future.
598
// Future's sesult will not contain any tuple.
599
//
600
// Deprecated: the method will be removed in the next major version,
601
// use a UpsertRequest object + Do() instead.
602
func (conn *Connection) UpsertAsync(space, tuple interface{}, ops *Operations) *Future {
8✔
603
        req := NewUpsertRequest(space).Tuple(tuple)
8✔
604
        req.ops = ops
8✔
605
        return conn.Do(req)
8✔
606
}
8✔
607

608
// CallAsync sends a call to registered Tarantool function and returns Future.
609
// It uses request code for Tarantool >= 1.7, so future's result is an array.
610
//
611
// Deprecated: the method will be removed in the next major version,
612
// use a CallRequest object + Do() instead.
613
func (conn *Connection) CallAsync(functionName string, args interface{}) *Future {
16✔
614
        req := NewCallRequest(functionName).Args(args)
16✔
615
        return conn.Do(req)
16✔
616
}
16✔
617

618
// Call16Async sends a call to registered Tarantool function and returns Future.
619
// It uses request code for Tarantool 1.6, so future's result is an array of arrays.
620
// Deprecated since Tarantool 1.7.2.
621
//
622
// Deprecated: the method will be removed in the next major version,
623
// use a Call16Request object + Do() instead.
624
func (conn *Connection) Call16Async(functionName string, args interface{}) *Future {
4✔
625
        req := NewCall16Request(functionName).Args(args)
4✔
626
        return conn.Do(req)
4✔
627
}
4✔
628

629
// Call17Async sends a call to registered Tarantool function and returns Future.
630
// It uses request code for Tarantool >= 1.7, so future's result is an array.
631
//
632
// Deprecated: the method will be removed in the next major version,
633
// use a Call17Request object + Do() instead.
634
func (conn *Connection) Call17Async(functionName string, args interface{}) *Future {
14✔
635
        req := NewCall17Request(functionName).Args(args)
14✔
636
        return conn.Do(req)
14✔
637
}
14✔
638

639
// EvalAsync sends a Lua expression for evaluation and returns Future.
640
//
641
// Deprecated: the method will be removed in the next major version,
642
// use an EvalRequest object + Do() instead.
643
func (conn *Connection) EvalAsync(expr string, args interface{}) *Future {
53✔
644
        req := NewEvalRequest(expr).Args(args)
53✔
645
        return conn.Do(req)
53✔
646
}
53✔
647

648
// ExecuteAsync sends a sql expression for execution and returns Future.
649
// Since 1.6.0
650
//
651
// Deprecated: the method will be removed in the next major version,
652
// use an ExecuteRequest object + Do() instead.
653
func (conn *Connection) ExecuteAsync(expr string, args interface{}) *Future {
50✔
654
        req := NewExecuteRequest(expr).Args(args)
50✔
655
        return conn.Do(req)
50✔
656
}
50✔
657

658
// KeyValueBind is a type for encoding named SQL parameters
659
type KeyValueBind struct {
660
        Key   string
661
        Value interface{}
662
}
663

664
//
665
// private
666
//
667

668
// this map is needed for caching names of struct fields in lower case
669
// to avoid extra allocations in heap by calling strings.ToLower()
670
var lowerCaseNames sync.Map
671

672
func encodeSQLBind(enc *msgpack.Encoder, from interface{}) error {
74✔
673
        // internal function for encoding single map in msgpack
74✔
674
        encodeKeyInterface := func(key string, val interface{}) error {
92✔
675
                if err := enc.EncodeMapLen(1); err != nil {
18✔
676
                        return err
×
677
                }
×
678
                if err := enc.EncodeString(":" + key); err != nil {
18✔
679
                        return err
×
680
                }
×
681
                if err := enc.Encode(val); err != nil {
18✔
682
                        return err
×
683
                }
×
684
                return nil
18✔
685
        }
686

687
        encodeKeyValue := func(key string, val reflect.Value) error {
78✔
688
                if err := enc.EncodeMapLen(1); err != nil {
4✔
689
                        return err
×
690
                }
×
691
                if err := enc.EncodeString(":" + key); err != nil {
4✔
692
                        return err
×
693
                }
×
694
                if err := enc.EncodeValue(val); err != nil {
4✔
695
                        return err
×
696
                }
×
697
                return nil
4✔
698
        }
699

700
        encodeNamedFromMap := func(mp map[string]interface{}) error {
78✔
701
                if err := enc.EncodeArrayLen(len(mp)); err != nil {
4✔
702
                        return err
×
703
                }
×
704
                for k, v := range mp {
12✔
705
                        if err := encodeKeyInterface(k, v); err != nil {
8✔
706
                                return err
×
707
                        }
×
708
                }
709
                return nil
4✔
710
        }
711

712
        encodeNamedFromStruct := func(val reflect.Value) error {
76✔
713
                if err := enc.EncodeArrayLen(val.NumField()); err != nil {
2✔
714
                        return err
×
715
                }
×
716
                cached, ok := lowerCaseNames.Load(val.Type())
2✔
717
                if !ok {
4✔
718
                        fields := make([]string, val.NumField())
2✔
719
                        for i := 0; i < val.NumField(); i++ {
6✔
720
                                key := val.Type().Field(i).Name
4✔
721
                                fields[i] = strings.ToLower(key)
4✔
722
                                v := val.Field(i)
4✔
723
                                if err := encodeKeyValue(fields[i], v); err != nil {
4✔
724
                                        return err
×
725
                                }
×
726
                        }
727
                        lowerCaseNames.Store(val.Type(), fields)
2✔
728
                        return nil
2✔
729
                }
730

731
                fields := cached.([]string)
×
732
                for i := 0; i < val.NumField(); i++ {
×
733
                        k := fields[i]
×
734
                        v := val.Field(i)
×
735
                        if err := encodeKeyValue(k, v); err != nil {
×
736
                                return err
×
737
                        }
×
738
                }
739
                return nil
×
740
        }
741

742
        encodeSlice := func(from interface{}) error {
140✔
743
                castedSlice, ok := from.([]interface{})
66✔
744
                if !ok {
68✔
745
                        castedKVSlice := from.([]KeyValueBind)
2✔
746
                        t := len(castedKVSlice)
2✔
747
                        if err := enc.EncodeArrayLen(t); err != nil {
2✔
748
                                return err
×
749
                        }
×
750
                        for _, v := range castedKVSlice {
6✔
751
                                if err := encodeKeyInterface(v.Key, v.Value); err != nil {
4✔
752
                                        return err
×
753
                                }
×
754
                        }
755
                        return nil
2✔
756
                }
757

758
                if err := enc.EncodeArrayLen(len(castedSlice)); err != nil {
64✔
759
                        return err
×
760
                }
×
761
                for i := 0; i < len(castedSlice); i++ {
114✔
762
                        if kvb, ok := castedSlice[i].(KeyValueBind); ok {
56✔
763
                                k := kvb.Key
6✔
764
                                v := kvb.Value
6✔
765
                                if err := encodeKeyInterface(k, v); err != nil {
6✔
766
                                        return err
×
767
                                }
×
768
                        } else {
44✔
769
                                if err := enc.Encode(castedSlice[i]); err != nil {
44✔
770
                                        return err
×
771
                                }
×
772
                        }
773
                }
774
                return nil
64✔
775
        }
776

777
        val := reflect.ValueOf(from)
74✔
778
        switch val.Kind() {
74✔
779
        case reflect.Map:
4✔
780
                mp, ok := from.(map[string]interface{})
4✔
781
                if !ok {
4✔
782
                        return errors.New("failed to encode map: wrong format")
×
783
                }
×
784
                if err := encodeNamedFromMap(mp); err != nil {
4✔
785
                        return err
×
786
                }
×
787
        case reflect.Struct:
2✔
788
                if err := encodeNamedFromStruct(val); err != nil {
2✔
789
                        return err
×
790
                }
×
791
        case reflect.Slice, reflect.Array:
66✔
792
                if err := encodeSlice(from); err != nil {
66✔
793
                        return err
×
794
                }
×
795
        }
796
        return nil
74✔
797
}
798

799
// Request is an interface that provides the necessary data to create a request
800
// that will be sent to a tarantool instance.
801
type Request interface {
802
        // Type returns a IPROTO type of the request.
803
        Type() iproto.Type
804
        // Body fills an msgpack.Encoder with a request body.
805
        Body(resolver SchemaResolver, enc *msgpack.Encoder) error
806
        // Ctx returns a context of the request.
807
        Ctx() context.Context
808
        // Async returns true if the request does not expect response.
809
        Async() bool
810
}
811

812
// ConnectedRequest is an interface that provides the info about a Connection
813
// the request belongs to.
814
type ConnectedRequest interface {
815
        Request
816
        // Conn returns a Connection the request belongs to.
817
        Conn() *Connection
818
}
819

820
type baseRequest struct {
821
        rtype iproto.Type
822
        async bool
823
        ctx   context.Context
824
}
825

826
// Type returns a IPROTO type for the request.
827
func (req *baseRequest) Type() iproto.Type {
4,372✔
828
        return req.rtype
4,372✔
829
}
4,372✔
830

831
// Async returns true if the request does not require a response.
832
func (req *baseRequest) Async() bool {
3,662✔
833
        return req.async
3,662✔
834
}
3,662✔
835

836
// Ctx returns a context of the request.
837
func (req *baseRequest) Ctx() context.Context {
7,382✔
838
        return req.ctx
7,382✔
839
}
7,382✔
840

841
type spaceRequest struct {
842
        baseRequest
843
        space interface{}
844
}
845

846
func (req *spaceRequest) setSpace(space interface{}) {
1,660✔
847
        req.space = space
1,660✔
848
}
1,660✔
849

850
type spaceIndexRequest struct {
851
        spaceRequest
852
        index interface{}
853
}
854

855
func (req *spaceIndexRequest) setIndex(index interface{}) {
1,304✔
856
        req.index = index
1,304✔
857
}
1,304✔
858

859
// authRequest implements IPROTO_AUTH request.
860
type authRequest struct {
861
        auth       Auth
862
        user, pass string
863
}
864

865
// newChapSha1AuthRequest create a new authRequest with chap-sha1
866
// authentication method.
867
func newChapSha1AuthRequest(user, password, salt string) (authRequest, error) {
683✔
868
        req := authRequest{}
683✔
869
        scr, err := scramble(salt, password)
683✔
870
        if err != nil {
683✔
871
                return req, fmt.Errorf("scrambling failure: %w", err)
×
872
        }
×
873

874
        req.auth = ChapSha1Auth
683✔
875
        req.user = user
683✔
876
        req.pass = string(scr)
683✔
877
        return req, nil
683✔
878
}
879

880
// newPapSha256AuthRequest create a new authRequest with pap-sha256
881
// authentication method.
882
func newPapSha256AuthRequest(user, password string) authRequest {
5✔
883
        return authRequest{
5✔
884
                auth: PapSha256Auth,
5✔
885
                user: user,
5✔
886
                pass: password,
5✔
887
        }
5✔
888
}
5✔
889

890
// Type returns a IPROTO type for the request.
891
func (req authRequest) Type() iproto.Type {
688✔
892
        return iproto.IPROTO_AUTH
688✔
893
}
688✔
894

895
// Async returns true if the request does not require a response.
896
func (req authRequest) Async() bool {
×
897
        return false
×
898
}
×
899

900
// Ctx returns a context of the request.
901
func (req authRequest) Ctx() context.Context {
×
902
        return nil
×
903
}
×
904

905
// Body fills an encoder with the auth request body.
906
func (req authRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
688✔
907
        if err := enc.EncodeMapLen(2); err != nil {
688✔
NEW
908
                return err
×
NEW
909
        }
×
910
        if err := enc.EncodeUint32(uint32(iproto.IPROTO_USER_NAME)); err != nil {
688✔
NEW
911
                return err
×
NEW
912
        }
×
913
        if err := enc.EncodeString(req.user); err != nil {
688✔
NEW
914
                return err
×
NEW
915
        }
×
916
        if err := enc.EncodeUint32(uint32(iproto.IPROTO_TUPLE)); err != nil {
688✔
NEW
917
                return err
×
NEW
918
        }
×
919
        if err := enc.EncodeArrayLen(2); err != nil {
688✔
NEW
920
                return err
×
NEW
921
        }
×
922
        if err := enc.EncodeString(req.auth.String()); err != nil {
688✔
NEW
923
                return err
×
NEW
924
        }
×
925
        if err := enc.EncodeString(req.pass); err != nil {
688✔
NEW
926
                return err
×
NEW
927
        }
×
928
        return nil
688✔
929
}
930

931
// PingRequest helps you to create an execute request object for execution
932
// by a Connection.
933
type PingRequest struct {
934
        baseRequest
935
}
936

937
// NewPingRequest returns a new PingRequest.
938
func NewPingRequest() *PingRequest {
94✔
939
        req := new(PingRequest)
94✔
940
        req.rtype = iproto.IPROTO_PING
94✔
941
        return req
94✔
942
}
94✔
943

944
// Body fills an msgpack.Encoder with the ping request body.
945
func (req *PingRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
90✔
946
        return fillPing(enc)
90✔
947
}
90✔
948

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

960
// SelectRequest allows you to create a select request object for execution
961
// by a Connection.
962
type SelectRequest struct {
963
        spaceIndexRequest
964
        isIteratorSet, fetchPos bool
965
        offset, limit           uint32
966
        iterator                Iter
967
        key, after              interface{}
968
}
969

970
// NewSelectRequest returns a new empty SelectRequest.
971
func NewSelectRequest(space interface{}) *SelectRequest {
1,254✔
972
        req := new(SelectRequest)
1,254✔
973
        req.rtype = iproto.IPROTO_SELECT
1,254✔
974
        req.setSpace(space)
1,254✔
975
        req.isIteratorSet = false
1,254✔
976
        req.fetchPos = false
1,254✔
977
        req.iterator = IterAll
1,254✔
978
        req.key = []interface{}{}
1,254✔
979
        req.after = nil
1,254✔
980
        req.limit = 0xFFFFFFFF
1,254✔
981
        return req
1,254✔
982
}
1,254✔
983

984
// Index sets the index for the select request.
985
// Note: default value is 0.
986
func (req *SelectRequest) Index(index interface{}) *SelectRequest {
1,230✔
987
        req.setIndex(index)
1,230✔
988
        return req
1,230✔
989
}
1,230✔
990

991
// Offset sets the offset for the select request.
992
// Note: default value is 0.
993
func (req *SelectRequest) Offset(offset uint32) *SelectRequest {
1,186✔
994
        req.offset = offset
1,186✔
995
        return req
1,186✔
996
}
1,186✔
997

998
// Limit sets the limit for the select request.
999
// Note: default value is 0xFFFFFFFF.
1000
func (req *SelectRequest) Limit(limit uint32) *SelectRequest {
1,214✔
1001
        req.limit = limit
1,214✔
1002
        return req
1,214✔
1003
}
1,214✔
1004

1005
// Iterator set the iterator for the select request.
1006
// Note: default value is IterAll if key is not set or IterEq otherwise.
1007
func (req *SelectRequest) Iterator(iterator Iter) *SelectRequest {
1,222✔
1008
        req.iterator = iterator
1,222✔
1009
        req.isIteratorSet = true
1,222✔
1010
        return req
1,222✔
1011
}
1,222✔
1012

1013
// Key set the key for the select request.
1014
// Note: default value is empty.
1015
func (req *SelectRequest) Key(key interface{}) *SelectRequest {
1,226✔
1016
        req.key = key
1,226✔
1017
        if !req.isIteratorSet {
1,230✔
1018
                req.iterator = IterEq
4✔
1019
        }
4✔
1020
        return req
1,226✔
1021
}
1022

1023
// FetchPos determines whether to fetch positions of the last tuple. A position
1024
// descriptor will be saved in Response.Pos value.
1025
//
1026
// Note: default value is false.
1027
//
1028
// Requires Tarantool >= 2.11.
1029
// Since 1.11.0
1030
func (req *SelectRequest) FetchPos(fetch bool) *SelectRequest {
10✔
1031
        req.fetchPos = fetch
10✔
1032
        return req
10✔
1033
}
10✔
1034

1035
// After must contain a tuple from which selection must continue or its
1036
// position (a value from Response.Pos).
1037
//
1038
// Note: default value in nil.
1039
//
1040
// Requires Tarantool >= 2.11.
1041
// Since 1.11.0
1042
func (req *SelectRequest) After(after interface{}) *SelectRequest {
8✔
1043
        req.after = after
8✔
1044
        return req
8✔
1045
}
8✔
1046

1047
// Body fills an encoder with the select request body.
1048
func (req *SelectRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
1,284✔
1049
        spaceEnc, err := newSpaceEncoder(res, req.space)
1,284✔
1050
        if err != nil {
1,288✔
1051
                return err
4✔
1052
        }
4✔
1053
        indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id)
1,280✔
1054
        if err != nil {
1,282✔
1055
                return err
2✔
1056
        }
2✔
1057

1058
        return fillSelect(enc, spaceEnc, indexEnc, req.offset, req.limit, req.iterator,
1,278✔
1059
                req.key, req.after, req.fetchPos)
1,278✔
1060
}
1061

1062
// Context sets a passed context to the request.
1063
//
1064
// Pay attention that when using context with request objects,
1065
// the timeout option for Connection does not affect the lifetime
1066
// of the request. For those purposes use context.WithTimeout() as
1067
// the root context.
1068
func (req *SelectRequest) Context(ctx context.Context) *SelectRequest {
2✔
1069
        req.ctx = ctx
2✔
1070
        return req
2✔
1071
}
2✔
1072

1073
// InsertRequest helps you to create an insert request object for execution
1074
// by a Connection.
1075
type InsertRequest struct {
1076
        spaceRequest
1077
        tuple interface{}
1078
}
1079

1080
// NewInsertRequest returns a new empty InsertRequest.
1081
func NewInsertRequest(space interface{}) *InsertRequest {
78✔
1082
        req := new(InsertRequest)
78✔
1083
        req.rtype = iproto.IPROTO_INSERT
78✔
1084
        req.setSpace(space)
78✔
1085
        req.tuple = []interface{}{}
78✔
1086
        return req
78✔
1087
}
78✔
1088

1089
// Tuple sets the tuple for insertion the insert request.
1090
// Note: default value is nil.
1091
func (req *InsertRequest) Tuple(tuple interface{}) *InsertRequest {
62✔
1092
        req.tuple = tuple
62✔
1093
        return req
62✔
1094
}
62✔
1095

1096
// Body fills an msgpack.Encoder with the insert request body.
1097
func (req *InsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
70✔
1098
        spaceEnc, err := newSpaceEncoder(res, req.space)
70✔
1099
        if err != nil {
72✔
1100
                return err
2✔
1101
        }
2✔
1102

1103
        return fillInsert(enc, spaceEnc, req.tuple)
68✔
1104
}
1105

1106
// Context sets a passed context to the request.
1107
//
1108
// Pay attention that when using context with request objects,
1109
// the timeout option for Connection does not affect the lifetime
1110
// of the request. For those purposes use context.WithTimeout() as
1111
// the root context.
1112
func (req *InsertRequest) Context(ctx context.Context) *InsertRequest {
2✔
1113
        req.ctx = ctx
2✔
1114
        return req
2✔
1115
}
2✔
1116

1117
// ReplaceRequest helps you to create a replace request object for execution
1118
// by a Connection.
1119
type ReplaceRequest struct {
1120
        spaceRequest
1121
        tuple interface{}
1122
}
1123

1124
// NewReplaceRequest returns a new empty ReplaceRequest.
1125
func NewReplaceRequest(space interface{}) *ReplaceRequest {
184✔
1126
        req := new(ReplaceRequest)
184✔
1127
        req.rtype = iproto.IPROTO_REPLACE
184✔
1128
        req.setSpace(space)
184✔
1129
        req.tuple = []interface{}{}
184✔
1130
        return req
184✔
1131
}
184✔
1132

1133
// Tuple sets the tuple for replace by the replace request.
1134
// Note: default value is nil.
1135
func (req *ReplaceRequest) Tuple(tuple interface{}) *ReplaceRequest {
168✔
1136
        req.tuple = tuple
168✔
1137
        return req
168✔
1138
}
168✔
1139

1140
// Body fills an msgpack.Encoder with the replace request body.
1141
func (req *ReplaceRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
176✔
1142
        spaceEnc, err := newSpaceEncoder(res, req.space)
176✔
1143
        if err != nil {
178✔
1144
                return err
2✔
1145
        }
2✔
1146

1147
        return fillInsert(enc, spaceEnc, req.tuple)
174✔
1148
}
1149

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

1161
// DeleteRequest helps you to create a delete request object for execution
1162
// by a Connection.
1163
type DeleteRequest struct {
1164
        spaceIndexRequest
1165
        key interface{}
1166
}
1167

1168
// NewDeleteRequest returns a new empty DeleteRequest.
1169
func NewDeleteRequest(space interface{}) *DeleteRequest {
74✔
1170
        req := new(DeleteRequest)
74✔
1171
        req.rtype = iproto.IPROTO_DELETE
74✔
1172
        req.setSpace(space)
74✔
1173
        req.key = []interface{}{}
74✔
1174
        return req
74✔
1175
}
74✔
1176

1177
// Index sets the index for the delete request.
1178
// Note: default value is 0.
1179
func (req *DeleteRequest) Index(index interface{}) *DeleteRequest {
56✔
1180
        req.setIndex(index)
56✔
1181
        return req
56✔
1182
}
56✔
1183

1184
// Key sets the key of tuple for the delete request.
1185
// Note: default value is empty.
1186
func (req *DeleteRequest) Key(key interface{}) *DeleteRequest {
50✔
1187
        req.key = key
50✔
1188
        return req
50✔
1189
}
50✔
1190

1191
// Body fills an msgpack.Encoder with the delete request body.
1192
func (req *DeleteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
66✔
1193
        spaceEnc, err := newSpaceEncoder(res, req.space)
66✔
1194
        if err != nil {
70✔
1195
                return err
4✔
1196
        }
4✔
1197
        indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id)
62✔
1198
        if err != nil {
64✔
1199
                return err
2✔
1200
        }
2✔
1201

1202
        return fillDelete(enc, spaceEnc, indexEnc, req.key)
60✔
1203
}
1204

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

1216
// UpdateRequest helps you to create an update request object for execution
1217
// by a Connection.
1218
type UpdateRequest struct {
1219
        spaceIndexRequest
1220
        key interface{}
1221
        ops *Operations
1222
}
1223

1224
// NewUpdateRequest returns a new empty UpdateRequest.
1225
func NewUpdateRequest(space interface{}) *UpdateRequest {
36✔
1226
        req := new(UpdateRequest)
36✔
1227
        req.rtype = iproto.IPROTO_UPDATE
36✔
1228
        req.setSpace(space)
36✔
1229
        req.key = []interface{}{}
36✔
1230
        return req
36✔
1231
}
36✔
1232

1233
// Index sets the index for the update request.
1234
// Note: default value is 0.
1235
func (req *UpdateRequest) Index(index interface{}) *UpdateRequest {
18✔
1236
        req.setIndex(index)
18✔
1237
        return req
18✔
1238
}
18✔
1239

1240
// Key sets the key of tuple for the update request.
1241
// Note: default value is empty.
1242
func (req *UpdateRequest) Key(key interface{}) *UpdateRequest {
12✔
1243
        req.key = key
12✔
1244
        return req
12✔
1245
}
12✔
1246

1247
// Operations sets operations to be performed on update.
1248
// Note: default value is empty.
1249
func (req *UpdateRequest) Operations(ops *Operations) *UpdateRequest {
6✔
1250
        req.ops = ops
6✔
1251
        return req
6✔
1252
}
6✔
1253

1254
// Body fills an msgpack.Encoder with the update request body.
1255
func (req *UpdateRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
28✔
1256
        spaceEnc, err := newSpaceEncoder(res, req.space)
28✔
1257
        if err != nil {
32✔
1258
                return err
4✔
1259
        }
4✔
1260
        indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id)
24✔
1261
        if err != nil {
26✔
1262
                return err
2✔
1263
        }
2✔
1264

1265
        return fillUpdate(enc, spaceEnc, indexEnc, req.key, req.ops)
22✔
1266
}
1267

1268
// Context sets a passed context to the request.
1269
//
1270
// Pay attention that when using context with request objects,
1271
// the timeout option for Connection does not affect the lifetime
1272
// of the request. For those purposes use context.WithTimeout() as
1273
// the root context.
1274
func (req *UpdateRequest) Context(ctx context.Context) *UpdateRequest {
2✔
1275
        req.ctx = ctx
2✔
1276
        return req
2✔
1277
}
2✔
1278

1279
// UpsertRequest helps you to create an upsert request object for execution
1280
// by a Connection.
1281
type UpsertRequest struct {
1282
        spaceRequest
1283
        tuple interface{}
1284
        ops   *Operations
1285
}
1286

1287
// NewUpsertRequest returns a new empty UpsertRequest.
1288
func NewUpsertRequest(space interface{}) *UpsertRequest {
34✔
1289
        req := new(UpsertRequest)
34✔
1290
        req.rtype = iproto.IPROTO_UPSERT
34✔
1291
        req.setSpace(space)
34✔
1292
        req.tuple = []interface{}{}
34✔
1293
        return req
34✔
1294
}
34✔
1295

1296
// Tuple sets the tuple for insertion or update by the upsert request.
1297
// Note: default value is empty.
1298
func (req *UpsertRequest) Tuple(tuple interface{}) *UpsertRequest {
18✔
1299
        req.tuple = tuple
18✔
1300
        return req
18✔
1301
}
18✔
1302

1303
// Operations sets operations to be performed on update case by the upsert request.
1304
// Note: default value is empty.
1305
func (req *UpsertRequest) Operations(ops *Operations) *UpsertRequest {
8✔
1306
        req.ops = ops
8✔
1307
        return req
8✔
1308
}
8✔
1309

1310
// Body fills an msgpack.Encoder with the upsert request body.
1311
func (req *UpsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
26✔
1312
        spaceEnc, err := newSpaceEncoder(res, req.space)
26✔
1313
        if err != nil {
28✔
1314
                return err
2✔
1315
        }
2✔
1316

1317
        return fillUpsert(enc, spaceEnc, req.tuple, req.ops)
24✔
1318
}
1319

1320
// Context sets a passed context to the request.
1321
//
1322
// Pay attention that when using context with request objects,
1323
// the timeout option for Connection does not affect the lifetime
1324
// of the request. For those purposes use context.WithTimeout() as
1325
// the root context.
1326
func (req *UpsertRequest) Context(ctx context.Context) *UpsertRequest {
2✔
1327
        req.ctx = ctx
2✔
1328
        return req
2✔
1329
}
2✔
1330

1331
// CallRequest helps you to create a call request object for execution
1332
// by a Connection.
1333
type CallRequest struct {
1334
        baseRequest
1335
        function string
1336
        args     interface{}
1337
}
1338

1339
// NewCallRequest returns a new empty CallRequest. It uses request code for
1340
// Tarantool >= 1.7.
1341
func NewCallRequest(function string) *CallRequest {
323✔
1342
        req := new(CallRequest)
323✔
1343
        req.rtype = iproto.IPROTO_CALL
323✔
1344
        req.function = function
323✔
1345
        return req
323✔
1346
}
323✔
1347

1348
// Args sets the args for the call request.
1349
// Note: default value is empty.
1350
func (req *CallRequest) Args(args interface{}) *CallRequest {
118✔
1351
        req.args = args
118✔
1352
        return req
118✔
1353
}
118✔
1354

1355
// Body fills an encoder with the call request body.
1356
func (req *CallRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
291✔
1357
        args := req.args
291✔
1358
        if args == nil {
501✔
1359
                args = []interface{}{}
210✔
1360
        }
210✔
1361
        return fillCall(enc, req.function, args)
291✔
1362
}
1363

1364
// Context sets a passed context to the request.
1365
//
1366
// Pay attention that when using context with request objects,
1367
// the timeout option for Connection does not affect the lifetime
1368
// of the request. For those purposes use context.WithTimeout() as
1369
// the root context.
1370
func (req *CallRequest) Context(ctx context.Context) *CallRequest {
8✔
1371
        req.ctx = ctx
8✔
1372
        return req
8✔
1373
}
8✔
1374

1375
// NewCall16Request returns a new empty Call16Request. It uses request code for
1376
// Tarantool 1.6.
1377
// Deprecated since Tarantool 1.7.2.
1378
func NewCall16Request(function string) *CallRequest {
18✔
1379
        req := NewCallRequest(function)
18✔
1380
        req.rtype = iproto.IPROTO_CALL_16
18✔
1381
        return req
18✔
1382
}
18✔
1383

1384
// NewCall17Request returns a new empty CallRequest. It uses request code for
1385
// Tarantool >= 1.7.
1386
func NewCall17Request(function string) *CallRequest {
28✔
1387
        req := NewCallRequest(function)
28✔
1388
        req.rtype = iproto.IPROTO_CALL
28✔
1389
        return req
28✔
1390
}
28✔
1391

1392
// EvalRequest helps you to create an eval request object for execution
1393
// by a Connection.
1394
type EvalRequest struct {
1395
        baseRequest
1396
        expr string
1397
        args interface{}
1398
}
1399

1400
// NewEvalRequest returns a new empty EvalRequest.
1401
func NewEvalRequest(expr string) *EvalRequest {
183✔
1402
        req := new(EvalRequest)
183✔
1403
        req.rtype = iproto.IPROTO_EVAL
183✔
1404
        req.expr = expr
183✔
1405
        req.args = []interface{}{}
183✔
1406
        return req
183✔
1407
}
183✔
1408

1409
// Args sets the args for the eval request.
1410
// Note: default value is empty.
1411
func (req *EvalRequest) Args(args interface{}) *EvalRequest {
169✔
1412
        req.args = args
169✔
1413
        return req
169✔
1414
}
169✔
1415

1416
// Body fills an msgpack.Encoder with the eval request body.
1417
func (req *EvalRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
175✔
1418
        return fillEval(enc, req.expr, req.args)
175✔
1419
}
175✔
1420

1421
// Context sets a passed context to the request.
1422
//
1423
// Pay attention that when using context with request objects,
1424
// the timeout option for Connection does not affect the lifetime
1425
// of the request. For those purposes use context.WithTimeout() as
1426
// the root context.
1427
func (req *EvalRequest) Context(ctx context.Context) *EvalRequest {
2✔
1428
        req.ctx = ctx
2✔
1429
        return req
2✔
1430
}
2✔
1431

1432
// ExecuteRequest helps you to create an execute request object for execution
1433
// by a Connection.
1434
type ExecuteRequest struct {
1435
        baseRequest
1436
        expr string
1437
        args interface{}
1438
}
1439

1440
// NewExecuteRequest returns a new empty ExecuteRequest.
1441
func NewExecuteRequest(expr string) *ExecuteRequest {
66✔
1442
        req := new(ExecuteRequest)
66✔
1443
        req.rtype = iproto.IPROTO_EXECUTE
66✔
1444
        req.expr = expr
66✔
1445
        req.args = []interface{}{}
66✔
1446
        return req
66✔
1447
}
66✔
1448

1449
// Args sets the args for the execute request.
1450
// Note: default value is empty.
1451
func (req *ExecuteRequest) Args(args interface{}) *ExecuteRequest {
52✔
1452
        req.args = args
52✔
1453
        return req
52✔
1454
}
52✔
1455

1456
// Body fills an msgpack.Encoder with the execute request body.
1457
func (req *ExecuteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
58✔
1458
        return fillExecute(enc, req.expr, req.args)
58✔
1459
}
58✔
1460

1461
// Context sets a passed context to the request.
1462
//
1463
// Pay attention that when using context with request objects,
1464
// the timeout option for Connection does not affect the lifetime
1465
// of the request. For those purposes use context.WithTimeout() as
1466
// the root context.
1467
func (req *ExecuteRequest) Context(ctx context.Context) *ExecuteRequest {
2✔
1468
        req.ctx = ctx
2✔
1469
        return req
2✔
1470
}
2✔
1471

1472
// WatchOnceRequest synchronously fetches the value currently associated with a
1473
// specified notification key without subscribing to changes.
1474
type WatchOnceRequest struct {
1475
        baseRequest
1476
        key string
1477
}
1478

1479
// NewWatchOnceRequest returns a new watchOnceRequest.
1480
func NewWatchOnceRequest(key string) *WatchOnceRequest {
12✔
1481
        req := new(WatchOnceRequest)
12✔
1482
        req.rtype = iproto.IPROTO_WATCH_ONCE
12✔
1483
        req.key = key
12✔
1484
        return req
12✔
1485
}
12✔
1486

1487
// Body fills an msgpack.Encoder with the watchOnce request body.
1488
func (req *WatchOnceRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
4✔
1489
        return fillWatchOnce(enc, req.key)
4✔
1490
}
4✔
1491

1492
// Context sets a passed context to the request.
1493
func (req *WatchOnceRequest) Context(ctx context.Context) *WatchOnceRequest {
2✔
1494
        req.ctx = ctx
2✔
1495
        return req
2✔
1496
}
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

© 2025 Coveralls, Inc