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

tarantool / go-tarantool / 13930913017

18 Mar 2025 06:33PM UTC coverage: 75.939% (+0.08%) from 75.863%
13930913017

Pull #435

github

maksim.konovalov
pool: Pooler interface supports GetInfo method in TopologyEditor
Pull Request #435: pool: Pooler interface supports GetInfo method in TopologyEditor

2992 of 3940 relevant lines covered (75.94%)

9863.87 hits per line

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

80.25
/request.go
1
package tarantool
2

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

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

16
type spaceEncoder struct {
17
        Id   uint32
18
        Name string
19
        IsId bool
20
}
21

22
func newSpaceEncoder(res SchemaResolver, spaceInfo interface{}) (spaceEncoder, error) {
881✔
23
        if res.NamesUseSupported() {
1,734✔
24
                if spaceName, ok := spaceInfo.(string); ok {
994✔
25
                        return spaceEncoder{
141✔
26
                                Id:   0,
141✔
27
                                Name: spaceName,
141✔
28
                                IsId: false,
141✔
29
                        }, nil
141✔
30
                }
141✔
31
        }
32

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

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

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

59
func newIndexEncoder(res SchemaResolver, indexInfo interface{},
60
        spaceNo uint32) (indexEncoder, error) {
723✔
61
        if res.NamesUseSupported() {
1,434✔
62
                if indexName, ok := indexInfo.(string); ok {
738✔
63
                        return indexEncoder{
27✔
64
                                Name: indexName,
27✔
65
                                IsId: false,
27✔
66
                        }, nil
27✔
67
                }
27✔
68
        }
69

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

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

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

96
        if err := indexEnc.Encode(enc); err != nil {
720✔
97
                return err
×
98
        }
×
99

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

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

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

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

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

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

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

205
        enc.EncodeUint(uint64(iproto.IPROTO_TUPLE))
15✔
206
        if err := enc.Encode(tuple); err != nil {
15✔
207
                return err
×
208
        }
×
209
        enc.EncodeUint(uint64(iproto.IPROTO_OPS))
15✔
210
        if ops == nil {
21✔
211
                return enc.Encode([]interface{}{})
6✔
212
        }
6✔
213
        return enc.Encode(ops)
9✔
214
}
215

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

528
// ExecuteTyped passes sql expression to Tarantool for execution.
529
//
530
// In addition to error returns sql info and columns meta data
531
// Since 1.6.0
532
//
533
// Deprecated: the method will be removed in the next major version,
534
// use an ExecuteRequest object + Do() instead.
535
func (conn *Connection) ExecuteTyped(expr string, args interface{},
536
        result interface{}) (SQLInfo, []ColumnMetaData, error) {
1✔
537
        var (
1✔
538
                sqlInfo  SQLInfo
1✔
539
                metaData []ColumnMetaData
1✔
540
        )
1✔
541

1✔
542
        fut := conn.ExecuteAsync(expr, args)
1✔
543
        err := fut.GetTyped(&result)
1✔
544
        if resp, ok := fut.resp.(*ExecuteResponse); ok {
2✔
545
                sqlInfo = resp.sqlInfo
1✔
546
                metaData = resp.metaData
1✔
547
        } else if err == nil {
1✔
548
                err = fmt.Errorf("unexpected response type %T, want: *ExecuteResponse", fut.resp)
×
549
        }
×
550
        return sqlInfo, metaData, err
1✔
551
}
552

553
// SelectAsync sends select request to Tarantool and returns Future.
554
//
555
// Deprecated: the method will be removed in the next major version,
556
// use a SelectRequest object + Do() instead.
557
func (conn *Connection) SelectAsync(space, index interface{}, offset, limit uint32, iterator Iter,
558
        key interface{}) *Future {
16✔
559
        req := NewSelectRequest(space).
16✔
560
                Index(index).
16✔
561
                Offset(offset).
16✔
562
                Limit(limit).
16✔
563
                Iterator(iterator).
16✔
564
                Key(key)
16✔
565
        return conn.Do(req)
16✔
566
}
16✔
567

568
// InsertAsync sends insert action to Tarantool and returns Future.
569
// Tarantool will reject Insert when tuple with same primary key exists.
570
//
571
// Deprecated: the method will be removed in the next major version,
572
// use an InsertRequest object + Do() instead.
573
func (conn *Connection) InsertAsync(space interface{}, tuple interface{}) *Future {
9✔
574
        req := NewInsertRequest(space).Tuple(tuple)
9✔
575
        return conn.Do(req)
9✔
576
}
9✔
577

578
// ReplaceAsync sends "insert or replace" action to Tarantool and returns Future.
579
// If tuple with same primary key exists, it will be replaced.
580
//
581
// Deprecated: the method will be removed in the next major version,
582
// use a ReplaceRequest object + Do() instead.
583
func (conn *Connection) ReplaceAsync(space interface{}, tuple interface{}) *Future {
24✔
584
        req := NewReplaceRequest(space).Tuple(tuple)
24✔
585
        return conn.Do(req)
24✔
586
}
24✔
587

588
// DeleteAsync sends deletion action to Tarantool and returns Future.
589
// Future's result will contain array with deleted tuple.
590
//
591
// Deprecated: the method will be removed in the next major version,
592
// use a DeleteRequest object + Do() instead.
593
func (conn *Connection) DeleteAsync(space, index interface{}, key interface{}) *Future {
13✔
594
        req := NewDeleteRequest(space).Index(index).Key(key)
13✔
595
        return conn.Do(req)
13✔
596
}
13✔
597

598
// Update sends deletion of a tuple by key and returns Future.
599
// Future's result will contain array with updated tuple.
600
//
601
// Deprecated: the method will be removed in the next major version,
602
// use a UpdateRequest object + Do() instead.
603
func (conn *Connection) UpdateAsync(space, index interface{}, key interface{},
604
        ops *Operations) *Future {
2✔
605
        req := NewUpdateRequest(space).Index(index).Key(key)
2✔
606
        req.ops = ops
2✔
607
        return conn.Do(req)
2✔
608
}
2✔
609

610
// UpsertAsync sends "update or insert" action to Tarantool and returns Future.
611
// Future's sesult will not contain any tuple.
612
//
613
// Deprecated: the method will be removed in the next major version,
614
// use a UpsertRequest object + Do() instead.
615
func (conn *Connection) UpsertAsync(space, tuple interface{}, ops *Operations) *Future {
4✔
616
        req := NewUpsertRequest(space).Tuple(tuple)
4✔
617
        req.ops = ops
4✔
618
        return conn.Do(req)
4✔
619
}
4✔
620

621
// CallAsync sends a call to registered Tarantool function and returns Future.
622
// It uses request code for Tarantool >= 1.7, so future's result is an array.
623
//
624
// Deprecated: the method will be removed in the next major version,
625
// use a CallRequest object + Do() instead.
626
func (conn *Connection) CallAsync(functionName string, args interface{}) *Future {
8✔
627
        req := NewCallRequest(functionName).Args(args)
8✔
628
        return conn.Do(req)
8✔
629
}
8✔
630

631
// Call16Async sends a call to registered Tarantool function and returns Future.
632
// It uses request code for Tarantool 1.6, so future's result is an array of arrays.
633
// Deprecated since Tarantool 1.7.2.
634
//
635
// Deprecated: the method will be removed in the next major version,
636
// use a Call16Request object + Do() instead.
637
func (conn *Connection) Call16Async(functionName string, args interface{}) *Future {
2✔
638
        req := NewCall16Request(functionName).Args(args)
2✔
639
        return conn.Do(req)
2✔
640
}
2✔
641

642
// Call17Async sends a call to registered Tarantool function and returns Future.
643
// It uses request code for Tarantool >= 1.7, so future's result is an array.
644
//
645
// Deprecated: the method will be removed in the next major version,
646
// use a Call17Request object + Do() instead.
647
func (conn *Connection) Call17Async(functionName string, args interface{}) *Future {
7✔
648
        req := NewCall17Request(functionName).Args(args)
7✔
649
        return conn.Do(req)
7✔
650
}
7✔
651

652
// EvalAsync sends a Lua expression for evaluation and returns Future.
653
//
654
// Deprecated: the method will be removed in the next major version,
655
// use an EvalRequest object + Do() instead.
656
func (conn *Connection) EvalAsync(expr string, args interface{}) *Future {
27✔
657
        req := NewEvalRequest(expr).Args(args)
27✔
658
        return conn.Do(req)
27✔
659
}
27✔
660

661
// ExecuteAsync sends a sql expression for execution and returns Future.
662
// Since 1.6.0
663
//
664
// Deprecated: the method will be removed in the next major version,
665
// use an ExecuteRequest object + Do() instead.
666
func (conn *Connection) ExecuteAsync(expr string, args interface{}) *Future {
1✔
667
        req := NewExecuteRequest(expr).Args(args)
1✔
668
        return conn.Do(req)
1✔
669
}
1✔
670

671
// KeyValueBind is a type for encoding named SQL parameters
672
type KeyValueBind struct {
673
        Key   string
674
        Value interface{}
675
}
676

677
//
678
// private
679
//
680

681
// this map is needed for caching names of struct fields in lower case
682
// to avoid extra allocations in heap by calling strings.ToLower()
683
var lowerCaseNames sync.Map
684

685
func encodeSQLBind(enc *msgpack.Encoder, from interface{}) error {
37✔
686
        // internal function for encoding single map in msgpack
37✔
687
        encodeKeyInterface := func(key string, val interface{}) error {
46✔
688
                if err := enc.EncodeMapLen(1); err != nil {
9✔
689
                        return err
×
690
                }
×
691
                if err := enc.EncodeString(":" + key); err != nil {
9✔
692
                        return err
×
693
                }
×
694
                if err := enc.Encode(val); err != nil {
9✔
695
                        return err
×
696
                }
×
697
                return nil
9✔
698
        }
699

700
        encodeKeyValue := func(key string, val reflect.Value) error {
39✔
701
                if err := enc.EncodeMapLen(1); err != nil {
2✔
702
                        return err
×
703
                }
×
704
                if err := enc.EncodeString(":" + key); err != nil {
2✔
705
                        return err
×
706
                }
×
707
                if err := enc.EncodeValue(val); err != nil {
2✔
708
                        return err
×
709
                }
×
710
                return nil
2✔
711
        }
712

713
        encodeNamedFromMap := func(mp map[string]interface{}) error {
39✔
714
                if err := enc.EncodeArrayLen(len(mp)); err != nil {
2✔
715
                        return err
×
716
                }
×
717
                for k, v := range mp {
6✔
718
                        if err := encodeKeyInterface(k, v); err != nil {
4✔
719
                                return err
×
720
                        }
×
721
                }
722
                return nil
2✔
723
        }
724

725
        encodeNamedFromStruct := func(val reflect.Value) error {
38✔
726
                if err := enc.EncodeArrayLen(val.NumField()); err != nil {
1✔
727
                        return err
×
728
                }
×
729
                cached, ok := lowerCaseNames.Load(val.Type())
1✔
730
                if !ok {
2✔
731
                        fields := make([]string, val.NumField())
1✔
732
                        for i := 0; i < val.NumField(); i++ {
3✔
733
                                key := val.Type().Field(i).Name
2✔
734
                                fields[i] = strings.ToLower(key)
2✔
735
                                v := val.Field(i)
2✔
736
                                if err := encodeKeyValue(fields[i], v); err != nil {
2✔
737
                                        return err
×
738
                                }
×
739
                        }
740
                        lowerCaseNames.Store(val.Type(), fields)
1✔
741
                        return nil
1✔
742
                }
743

744
                fields := cached.([]string)
×
745
                for i := 0; i < val.NumField(); i++ {
×
746
                        k := fields[i]
×
747
                        v := val.Field(i)
×
748
                        if err := encodeKeyValue(k, v); err != nil {
×
749
                                return err
×
750
                        }
×
751
                }
752
                return nil
×
753
        }
754

755
        encodeSlice := func(from interface{}) error {
70✔
756
                castedSlice, ok := from.([]interface{})
33✔
757
                if !ok {
34✔
758
                        castedKVSlice := from.([]KeyValueBind)
1✔
759
                        t := len(castedKVSlice)
1✔
760
                        if err := enc.EncodeArrayLen(t); err != nil {
1✔
761
                                return err
×
762
                        }
×
763
                        for _, v := range castedKVSlice {
3✔
764
                                if err := encodeKeyInterface(v.Key, v.Value); err != nil {
2✔
765
                                        return err
×
766
                                }
×
767
                        }
768
                        return nil
1✔
769
                }
770

771
                if err := enc.EncodeArrayLen(len(castedSlice)); err != nil {
32✔
772
                        return err
×
773
                }
×
774
                for i := 0; i < len(castedSlice); i++ {
57✔
775
                        if kvb, ok := castedSlice[i].(KeyValueBind); ok {
28✔
776
                                k := kvb.Key
3✔
777
                                v := kvb.Value
3✔
778
                                if err := encodeKeyInterface(k, v); err != nil {
3✔
779
                                        return err
×
780
                                }
×
781
                        } else {
22✔
782
                                if err := enc.Encode(castedSlice[i]); err != nil {
22✔
783
                                        return err
×
784
                                }
×
785
                        }
786
                }
787
                return nil
32✔
788
        }
789

790
        val := reflect.ValueOf(from)
37✔
791
        switch val.Kind() {
37✔
792
        case reflect.Map:
2✔
793
                mp, ok := from.(map[string]interface{})
2✔
794
                if !ok {
2✔
795
                        return errors.New("failed to encode map: wrong format")
×
796
                }
×
797
                if err := encodeNamedFromMap(mp); err != nil {
2✔
798
                        return err
×
799
                }
×
800
        case reflect.Struct:
1✔
801
                if err := encodeNamedFromStruct(val); err != nil {
1✔
802
                        return err
×
803
                }
×
804
        case reflect.Slice, reflect.Array:
33✔
805
                if err := encodeSlice(from); err != nil {
33✔
806
                        return err
×
807
                }
×
808
        }
809
        return nil
37✔
810
}
811

812
// Request is an interface that provides the necessary data to create a request
813
// that will be sent to a tarantool instance.
814
type Request interface {
815
        // Type returns a IPROTO type of the request.
816
        Type() iproto.Type
817
        // Body fills an msgpack.Encoder with a request body.
818
        Body(resolver SchemaResolver, enc *msgpack.Encoder) error
819
        // Ctx returns a context of the request.
820
        Ctx() context.Context
821
        // Async returns true if the request does not expect response.
822
        Async() bool
823
        // Response creates a response for current request type.
824
        Response(header Header, body io.Reader) (Response, error)
825
}
826

827
// ConnectedRequest is an interface that provides the info about a Connection
828
// the request belongs to.
829
type ConnectedRequest interface {
830
        Request
831
        // Conn returns a Connection the request belongs to.
832
        Conn() *Connection
833
}
834

835
type baseRequest struct {
836
        rtype iproto.Type
837
        async bool
838
        ctx   context.Context
839
}
840

841
// Type returns a IPROTO type for the request.
842
func (req *baseRequest) Type() iproto.Type {
2,165✔
843
        return req.rtype
2,165✔
844
}
2,165✔
845

846
// Async returns true if the request does not require a response.
847
func (req *baseRequest) Async() bool {
1,836✔
848
        return req.async
1,836✔
849
}
1,836✔
850

851
// Ctx returns a context of the request.
852
func (req *baseRequest) Ctx() context.Context {
3,694✔
853
        return req.ctx
3,694✔
854
}
3,694✔
855

856
// Response creates a response for the baseRequest.
857
func (req *baseRequest) Response(header Header, body io.Reader) (Response, error) {
1,464✔
858
        return DecodeBaseResponse(header, body)
1,464✔
859
}
1,464✔
860

861
type spaceRequest struct {
862
        baseRequest
863
        space interface{}
864
}
865

866
func (req *spaceRequest) setSpace(space interface{}) {
873✔
867
        req.space = space
873✔
868
}
873✔
869

870
func EncodeSpace(res SchemaResolver, enc *msgpack.Encoder, space interface{}) error {
6✔
871
        spaceEnc, err := newSpaceEncoder(res, space)
6✔
872
        if err != nil {
7✔
873
                return err
1✔
874
        }
1✔
875
        if err := spaceEnc.Encode(enc); err != nil {
5✔
876
                return err
×
877
        }
×
878
        return nil
5✔
879
}
880

881
type spaceIndexRequest struct {
882
        spaceRequest
883
        index interface{}
884
}
885

886
func (req *spaceIndexRequest) setIndex(index interface{}) {
681✔
887
        req.index = index
681✔
888
}
681✔
889

890
// authRequest implements IPROTO_AUTH request.
891
type authRequest struct {
892
        auth       Auth
893
        user, pass string
894
}
895

896
// newChapSha1AuthRequest create a new authRequest with chap-sha1
897
// authentication method.
898
func newChapSha1AuthRequest(user, password, salt string) (authRequest, error) {
316✔
899
        req := authRequest{}
316✔
900
        scr, err := scramble(salt, password)
316✔
901
        if err != nil {
316✔
902
                return req, fmt.Errorf("scrambling failure: %w", err)
×
903
        }
×
904

905
        req.auth = ChapSha1Auth
316✔
906
        req.user = user
316✔
907
        req.pass = string(scr)
316✔
908
        return req, nil
316✔
909
}
910

911
// newPapSha256AuthRequest create a new authRequest with pap-sha256
912
// authentication method.
913
func newPapSha256AuthRequest(user, password string) authRequest {
2✔
914
        return authRequest{
2✔
915
                auth: PapSha256Auth,
2✔
916
                user: user,
2✔
917
                pass: password,
2✔
918
        }
2✔
919
}
2✔
920

921
// Type returns a IPROTO type for the request.
922
func (req authRequest) Type() iproto.Type {
318✔
923
        return iproto.IPROTO_AUTH
318✔
924
}
318✔
925

926
// Async returns true if the request does not require a response.
927
func (req authRequest) Async() bool {
×
928
        return false
×
929
}
×
930

931
// Ctx returns a context of the request.
932
func (req authRequest) Ctx() context.Context {
×
933
        return nil
×
934
}
×
935

936
// Body fills an encoder with the auth request body.
937
func (req authRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
318✔
938
        if err := enc.EncodeMapLen(2); err != nil {
318✔
939
                return err
×
940
        }
×
941
        if err := enc.EncodeUint32(uint32(iproto.IPROTO_USER_NAME)); err != nil {
318✔
942
                return err
×
943
        }
×
944
        if err := enc.EncodeString(req.user); err != nil {
318✔
945
                return err
×
946
        }
×
947
        if err := enc.EncodeUint32(uint32(iproto.IPROTO_TUPLE)); err != nil {
318✔
948
                return err
×
949
        }
×
950
        if err := enc.EncodeArrayLen(2); err != nil {
318✔
951
                return err
×
952
        }
×
953
        if err := enc.EncodeString(req.auth.String()); err != nil {
318✔
954
                return err
×
955
        }
×
956
        if err := enc.EncodeString(req.pass); err != nil {
318✔
957
                return err
×
958
        }
×
959
        return nil
318✔
960
}
961

962
// Response creates a response for the authRequest.
963
func (req authRequest) Response(header Header, body io.Reader) (Response, error) {
317✔
964
        return DecodeBaseResponse(header, body)
317✔
965
}
317✔
966

967
// PingRequest helps you to create an execute request object for execution
968
// by a Connection.
969
type PingRequest struct {
970
        baseRequest
971
}
972

973
// NewPingRequest returns a new PingRequest.
974
func NewPingRequest() *PingRequest {
41✔
975
        req := new(PingRequest)
41✔
976
        req.rtype = iproto.IPROTO_PING
41✔
977
        return req
41✔
978
}
41✔
979

980
// Body fills an msgpack.Encoder with the ping request body.
981
func (req *PingRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
35✔
982
        return fillPing(enc)
35✔
983
}
35✔
984

985
// Context sets a passed context to the request.
986
//
987
// Pay attention that when using context with request objects,
988
// the timeout option for Connection does not affect the lifetime
989
// of the request. For those purposes use context.WithTimeout() as
990
// the root context.
991
func (req *PingRequest) Context(ctx context.Context) *PingRequest {
4✔
992
        req.ctx = ctx
4✔
993
        return req
4✔
994
}
4✔
995

996
// SelectRequest allows you to create a select request object for execution
997
// by a Connection.
998
type SelectRequest struct {
999
        spaceIndexRequest
1000
        isIteratorSet, fetchPos bool
1001
        offset, limit           uint32
1002
        iterator                Iter
1003
        key, after              interface{}
1004
}
1005

1006
// NewSelectRequest returns a new empty SelectRequest.
1007
func NewSelectRequest(space interface{}) *SelectRequest {
659✔
1008
        req := new(SelectRequest)
659✔
1009
        req.rtype = iproto.IPROTO_SELECT
659✔
1010
        req.setSpace(space)
659✔
1011
        req.isIteratorSet = false
659✔
1012
        req.fetchPos = false
659✔
1013
        req.iterator = IterAll
659✔
1014
        req.key = []interface{}{}
659✔
1015
        req.after = nil
659✔
1016
        req.limit = 0xFFFFFFFF
659✔
1017
        return req
659✔
1018
}
659✔
1019

1020
// Index sets the index for the select request.
1021
// Note: default value is 0.
1022
func (req *SelectRequest) Index(index interface{}) *SelectRequest {
644✔
1023
        req.setIndex(index)
644✔
1024
        return req
644✔
1025
}
644✔
1026

1027
// Offset sets the offset for the select request.
1028
// Note: default value is 0.
1029
func (req *SelectRequest) Offset(offset uint32) *SelectRequest {
18✔
1030
        req.offset = offset
18✔
1031
        return req
18✔
1032
}
18✔
1033

1034
// Limit sets the limit for the select request.
1035
// Note: default value is 0xFFFFFFFF.
1036
func (req *SelectRequest) Limit(limit uint32) *SelectRequest {
636✔
1037
        req.limit = limit
636✔
1038
        return req
636✔
1039
}
636✔
1040

1041
// Iterator set the iterator for the select request.
1042
// Note: default value is IterAll if key is not set or IterEq otherwise.
1043
func (req *SelectRequest) Iterator(iterator Iter) *SelectRequest {
36✔
1044
        req.iterator = iterator
36✔
1045
        req.isIteratorSet = true
36✔
1046
        return req
36✔
1047
}
36✔
1048

1049
// Key set the key for the select request.
1050
// Note: default value is empty.
1051
func (req *SelectRequest) Key(key interface{}) *SelectRequest {
39✔
1052
        req.key = key
39✔
1053
        if !req.isIteratorSet {
42✔
1054
                req.iterator = IterEq
3✔
1055
        }
3✔
1056
        return req
39✔
1057
}
1058

1059
// FetchPos determines whether to fetch positions of the last tuple. A position
1060
// descriptor will be saved in Response.Pos value.
1061
//
1062
// Note: default value is false.
1063
//
1064
// Requires Tarantool >= 2.11.
1065
// Since 1.11.0
1066
func (req *SelectRequest) FetchPos(fetch bool) *SelectRequest {
5✔
1067
        req.fetchPos = fetch
5✔
1068
        return req
5✔
1069
}
5✔
1070

1071
// After must contain a tuple from which selection must continue or its
1072
// position (a value from Response.Pos).
1073
//
1074
// Note: default value in nil.
1075
//
1076
// Requires Tarantool >= 2.11.
1077
// Since 1.11.0
1078
func (req *SelectRequest) After(after interface{}) *SelectRequest {
4✔
1079
        req.after = after
4✔
1080
        return req
4✔
1081
}
4✔
1082

1083
// Body fills an encoder with the select request body.
1084
func (req *SelectRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
667✔
1085
        spaceEnc, err := newSpaceEncoder(res, req.space)
667✔
1086
        if err != nil {
669✔
1087
                return err
2✔
1088
        }
2✔
1089
        indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id)
665✔
1090
        if err != nil {
666✔
1091
                return err
1✔
1092
        }
1✔
1093

1094
        return fillSelect(enc, spaceEnc, indexEnc, req.offset, req.limit, req.iterator,
664✔
1095
                req.key, req.after, req.fetchPos)
664✔
1096
}
1097

1098
// Context sets a passed context to the request.
1099
//
1100
// Pay attention that when using context with request objects,
1101
// the timeout option for Connection does not affect the lifetime
1102
// of the request. For those purposes use context.WithTimeout() as
1103
// the root context.
1104
func (req *SelectRequest) Context(ctx context.Context) *SelectRequest {
1✔
1105
        req.ctx = ctx
1✔
1106
        return req
1✔
1107
}
1✔
1108

1109
// Response creates a response for the SelectRequest.
1110
func (req *SelectRequest) Response(header Header, body io.Reader) (Response, error) {
655✔
1111
        baseResp, err := createBaseResponse(header, body)
655✔
1112
        if err != nil {
655✔
1113
                return nil, err
×
1114
        }
×
1115
        return &SelectResponse{baseResponse: baseResp}, nil
655✔
1116
}
1117

1118
// InsertRequest helps you to create an insert request object for execution
1119
// by a Connection.
1120
type InsertRequest struct {
1121
        spaceRequest
1122
        tuple interface{}
1123
}
1124

1125
// NewInsertRequest returns a new empty InsertRequest.
1126
func NewInsertRequest(space interface{}) *InsertRequest {
42✔
1127
        req := new(InsertRequest)
42✔
1128
        req.rtype = iproto.IPROTO_INSERT
42✔
1129
        req.setSpace(space)
42✔
1130
        req.tuple = []interface{}{}
42✔
1131
        return req
42✔
1132
}
42✔
1133

1134
// Tuple sets the tuple for insertion the insert request.
1135
// Note: default value is nil.
1136
func (req *InsertRequest) Tuple(tuple interface{}) *InsertRequest {
32✔
1137
        req.tuple = tuple
32✔
1138
        return req
32✔
1139
}
32✔
1140

1141
// Body fills an msgpack.Encoder with the insert request body.
1142
func (req *InsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
36✔
1143
        spaceEnc, err := newSpaceEncoder(res, req.space)
36✔
1144
        if err != nil {
37✔
1145
                return err
1✔
1146
        }
1✔
1147

1148
        return fillInsert(enc, spaceEnc, req.tuple)
35✔
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 *InsertRequest) Context(ctx context.Context) *InsertRequest {
1✔
1158
        req.ctx = ctx
1✔
1159
        return req
1✔
1160
}
1✔
1161

1162
// ReplaceRequest helps you to create a replace request object for execution
1163
// by a Connection.
1164
type ReplaceRequest struct {
1165
        spaceRequest
1166
        tuple interface{}
1167
}
1168

1169
// NewReplaceRequest returns a new empty ReplaceRequest.
1170
func NewReplaceRequest(space interface{}) *ReplaceRequest {
94✔
1171
        req := new(ReplaceRequest)
94✔
1172
        req.rtype = iproto.IPROTO_REPLACE
94✔
1173
        req.setSpace(space)
94✔
1174
        req.tuple = []interface{}{}
94✔
1175
        return req
94✔
1176
}
94✔
1177

1178
// Tuple sets the tuple for replace by the replace request.
1179
// Note: default value is nil.
1180
func (req *ReplaceRequest) Tuple(tuple interface{}) *ReplaceRequest {
84✔
1181
        req.tuple = tuple
84✔
1182
        return req
84✔
1183
}
84✔
1184

1185
// Body fills an msgpack.Encoder with the replace request body.
1186
func (req *ReplaceRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
88✔
1187
        spaceEnc, err := newSpaceEncoder(res, req.space)
88✔
1188
        if err != nil {
89✔
1189
                return err
1✔
1190
        }
1✔
1191

1192
        return fillInsert(enc, spaceEnc, req.tuple)
87✔
1193
}
1194

1195
// Context sets a passed context to the request.
1196
//
1197
// Pay attention that when using context with request objects,
1198
// the timeout option for Connection does not affect the lifetime
1199
// of the request. For those purposes use context.WithTimeout() as
1200
// the root context.
1201
func (req *ReplaceRequest) Context(ctx context.Context) *ReplaceRequest {
1✔
1202
        req.ctx = ctx
1✔
1203
        return req
1✔
1204
}
1✔
1205

1206
// DeleteRequest helps you to create a delete request object for execution
1207
// by a Connection.
1208
type DeleteRequest struct {
1209
        spaceIndexRequest
1210
        key interface{}
1211
}
1212

1213
// NewDeleteRequest returns a new empty DeleteRequest.
1214
func NewDeleteRequest(space interface{}) *DeleteRequest {
39✔
1215
        req := new(DeleteRequest)
39✔
1216
        req.rtype = iproto.IPROTO_DELETE
39✔
1217
        req.setSpace(space)
39✔
1218
        req.key = []interface{}{}
39✔
1219
        return req
39✔
1220
}
39✔
1221

1222
// Index sets the index for the delete request.
1223
// Note: default value is 0.
1224
func (req *DeleteRequest) Index(index interface{}) *DeleteRequest {
28✔
1225
        req.setIndex(index)
28✔
1226
        return req
28✔
1227
}
28✔
1228

1229
// Key sets the key of tuple for the delete request.
1230
// Note: default value is empty.
1231
func (req *DeleteRequest) Key(key interface{}) *DeleteRequest {
25✔
1232
        req.key = key
25✔
1233
        return req
25✔
1234
}
25✔
1235

1236
// Body fills an msgpack.Encoder with the delete request body.
1237
func (req *DeleteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
33✔
1238
        spaceEnc, err := newSpaceEncoder(res, req.space)
33✔
1239
        if err != nil {
35✔
1240
                return err
2✔
1241
        }
2✔
1242
        indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id)
31✔
1243
        if err != nil {
32✔
1244
                return err
1✔
1245
        }
1✔
1246

1247
        return fillDelete(enc, spaceEnc, indexEnc, req.key)
30✔
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 *DeleteRequest) Context(ctx context.Context) *DeleteRequest {
1✔
1257
        req.ctx = ctx
1✔
1258
        return req
1✔
1259
}
1✔
1260

1261
// UpdateRequest helps you to create an update request object for execution
1262
// by a Connection.
1263
type UpdateRequest struct {
1264
        spaceIndexRequest
1265
        key interface{}
1266
        ops *Operations
1267
}
1268

1269
// NewUpdateRequest returns a new empty UpdateRequest.
1270
func NewUpdateRequest(space interface{}) *UpdateRequest {
20✔
1271
        req := new(UpdateRequest)
20✔
1272
        req.rtype = iproto.IPROTO_UPDATE
20✔
1273
        req.setSpace(space)
20✔
1274
        req.key = []interface{}{}
20✔
1275
        return req
20✔
1276
}
20✔
1277

1278
// Index sets the index for the update request.
1279
// Note: default value is 0.
1280
func (req *UpdateRequest) Index(index interface{}) *UpdateRequest {
9✔
1281
        req.setIndex(index)
9✔
1282
        return req
9✔
1283
}
9✔
1284

1285
// Key sets the key of tuple for the update request.
1286
// Note: default value is empty.
1287
func (req *UpdateRequest) Key(key interface{}) *UpdateRequest {
6✔
1288
        req.key = key
6✔
1289
        return req
6✔
1290
}
6✔
1291

1292
// Operations sets operations to be performed on update.
1293
// Note: default value is empty.
1294
func (req *UpdateRequest) Operations(ops *Operations) *UpdateRequest {
3✔
1295
        req.ops = ops
3✔
1296
        return req
3✔
1297
}
3✔
1298

1299
// Body fills an msgpack.Encoder with the update request body.
1300
func (req *UpdateRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
14✔
1301
        spaceEnc, err := newSpaceEncoder(res, req.space)
14✔
1302
        if err != nil {
16✔
1303
                return err
2✔
1304
        }
2✔
1305
        indexEnc, err := newIndexEncoder(res, req.index, spaceEnc.Id)
12✔
1306
        if err != nil {
13✔
1307
                return err
1✔
1308
        }
1✔
1309

1310
        return fillUpdate(enc, spaceEnc, indexEnc, req.key, req.ops)
11✔
1311
}
1312

1313
// Context sets a passed context to the request.
1314
//
1315
// Pay attention that when using context with request objects,
1316
// the timeout option for Connection does not affect the lifetime
1317
// of the request. For those purposes use context.WithTimeout() as
1318
// the root context.
1319
func (req *UpdateRequest) Context(ctx context.Context) *UpdateRequest {
1✔
1320
        req.ctx = ctx
1✔
1321
        return req
1✔
1322
}
1✔
1323

1324
// UpsertRequest helps you to create an upsert request object for execution
1325
// by a Connection.
1326
type UpsertRequest struct {
1327
        spaceRequest
1328
        tuple interface{}
1329
        ops   *Operations
1330
}
1331

1332
// NewUpsertRequest returns a new empty UpsertRequest.
1333
func NewUpsertRequest(space interface{}) *UpsertRequest {
19✔
1334
        req := new(UpsertRequest)
19✔
1335
        req.rtype = iproto.IPROTO_UPSERT
19✔
1336
        req.setSpace(space)
19✔
1337
        req.tuple = []interface{}{}
19✔
1338
        return req
19✔
1339
}
19✔
1340

1341
// Tuple sets the tuple for insertion or update by the upsert request.
1342
// Note: default value is empty.
1343
func (req *UpsertRequest) Tuple(tuple interface{}) *UpsertRequest {
9✔
1344
        req.tuple = tuple
9✔
1345
        return req
9✔
1346
}
9✔
1347

1348
// Operations sets operations to be performed on update case by the upsert request.
1349
// Note: default value is empty.
1350
func (req *UpsertRequest) Operations(ops *Operations) *UpsertRequest {
4✔
1351
        req.ops = ops
4✔
1352
        return req
4✔
1353
}
4✔
1354

1355
// Body fills an msgpack.Encoder with the upsert request body.
1356
func (req *UpsertRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
13✔
1357
        spaceEnc, err := newSpaceEncoder(res, req.space)
13✔
1358
        if err != nil {
14✔
1359
                return err
1✔
1360
        }
1✔
1361

1362
        return fillUpsert(enc, spaceEnc, req.tuple, req.ops)
12✔
1363
}
1364

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

1376
// CallRequest helps you to create a call request object for execution
1377
// by a Connection.
1378
type CallRequest struct {
1379
        baseRequest
1380
        function string
1381
        args     interface{}
1382
}
1383

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

1393
// Args sets the args for the call request.
1394
// Note: default value is empty.
1395
func (req *CallRequest) Args(args interface{}) *CallRequest {
62✔
1396
        req.args = args
62✔
1397
        return req
62✔
1398
}
62✔
1399

1400
// Body fills an encoder with the call request body.
1401
func (req *CallRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
146✔
1402
        args := req.args
146✔
1403
        if args == nil {
251✔
1404
                args = []interface{}{}
105✔
1405
        }
105✔
1406
        return fillCall(enc, req.function, args)
146✔
1407
}
1408

1409
// Context sets a passed context to the request.
1410
//
1411
// Pay attention that when using context with request objects,
1412
// the timeout option for Connection does not affect the lifetime
1413
// of the request. For those purposes use context.WithTimeout() as
1414
// the root context.
1415
func (req *CallRequest) Context(ctx context.Context) *CallRequest {
4✔
1416
        req.ctx = ctx
4✔
1417
        return req
4✔
1418
}
4✔
1419

1420
// NewCall16Request returns a new empty Call16Request. It uses request code for
1421
// Tarantool 1.6.
1422
// Deprecated since Tarantool 1.7.2.
1423
func NewCall16Request(function string) *CallRequest {
11✔
1424
        req := NewCallRequest(function)
11✔
1425
        req.rtype = iproto.IPROTO_CALL_16
11✔
1426
        return req
11✔
1427
}
11✔
1428

1429
// NewCall17Request returns a new empty CallRequest. It uses request code for
1430
// Tarantool >= 1.7.
1431
func NewCall17Request(function string) *CallRequest {
16✔
1432
        req := NewCallRequest(function)
16✔
1433
        req.rtype = iproto.IPROTO_CALL
16✔
1434
        return req
16✔
1435
}
16✔
1436

1437
// EvalRequest helps you to create an eval request object for execution
1438
// by a Connection.
1439
type EvalRequest struct {
1440
        baseRequest
1441
        expr string
1442
        args interface{}
1443
}
1444

1445
// NewEvalRequest returns a new empty EvalRequest.
1446
func NewEvalRequest(expr string) *EvalRequest {
94✔
1447
        req := new(EvalRequest)
94✔
1448
        req.rtype = iproto.IPROTO_EVAL
94✔
1449
        req.expr = expr
94✔
1450
        req.args = []interface{}{}
94✔
1451
        return req
94✔
1452
}
94✔
1453

1454
// Args sets the args for the eval request.
1455
// Note: default value is empty.
1456
func (req *EvalRequest) Args(args interface{}) *EvalRequest {
85✔
1457
        req.args = args
85✔
1458
        return req
85✔
1459
}
85✔
1460

1461
// Body fills an msgpack.Encoder with the eval request body.
1462
func (req *EvalRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
88✔
1463
        return fillEval(enc, req.expr, req.args)
88✔
1464
}
88✔
1465

1466
// Context sets a passed context to the request.
1467
//
1468
// Pay attention that when using context with request objects,
1469
// the timeout option for Connection does not affect the lifetime
1470
// of the request. For those purposes use context.WithTimeout() as
1471
// the root context.
1472
func (req *EvalRequest) Context(ctx context.Context) *EvalRequest {
1✔
1473
        req.ctx = ctx
1✔
1474
        return req
1✔
1475
}
1✔
1476

1477
// ExecuteRequest helps you to create an execute request object for execution
1478
// by a Connection.
1479
type ExecuteRequest struct {
1480
        baseRequest
1481
        expr string
1482
        args interface{}
1483
}
1484

1485
// NewExecuteRequest returns a new empty ExecuteRequest.
1486
func NewExecuteRequest(expr string) *ExecuteRequest {
35✔
1487
        req := new(ExecuteRequest)
35✔
1488
        req.rtype = iproto.IPROTO_EXECUTE
35✔
1489
        req.expr = expr
35✔
1490
        req.args = []interface{}{}
35✔
1491
        return req
35✔
1492
}
35✔
1493

1494
// Args sets the args for the execute request.
1495
// Note: default value is empty.
1496
func (req *ExecuteRequest) Args(args interface{}) *ExecuteRequest {
21✔
1497
        req.args = args
21✔
1498
        return req
21✔
1499
}
21✔
1500

1501
// Body fills an msgpack.Encoder with the execute request body.
1502
func (req *ExecuteRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
29✔
1503
        return fillExecute(enc, req.expr, req.args)
29✔
1504
}
29✔
1505

1506
// Context sets a passed context to the request.
1507
//
1508
// Pay attention that when using context with request objects,
1509
// the timeout option for Connection does not affect the lifetime
1510
// of the request. For those purposes use context.WithTimeout() as
1511
// the root context.
1512
func (req *ExecuteRequest) Context(ctx context.Context) *ExecuteRequest {
1✔
1513
        req.ctx = ctx
1✔
1514
        return req
1✔
1515
}
1✔
1516

1517
// Response creates a response for the ExecuteRequest.
1518
func (req *ExecuteRequest) Response(header Header, body io.Reader) (Response, error) {
29✔
1519
        baseResp, err := createBaseResponse(header, body)
29✔
1520
        if err != nil {
29✔
1521
                return nil, err
×
1522
        }
×
1523
        return &ExecuteResponse{baseResponse: baseResp}, nil
29✔
1524
}
1525

1526
// WatchOnceRequest synchronously fetches the value currently associated with a
1527
// specified notification key without subscribing to changes.
1528
type WatchOnceRequest struct {
1529
        baseRequest
1530
        key string
1531
}
1532

1533
// NewWatchOnceRequest returns a new watchOnceRequest.
1534
func NewWatchOnceRequest(key string) *WatchOnceRequest {
9✔
1535
        req := new(WatchOnceRequest)
9✔
1536
        req.rtype = iproto.IPROTO_WATCH_ONCE
9✔
1537
        req.key = key
9✔
1538
        return req
9✔
1539
}
9✔
1540

1541
// Body fills an msgpack.Encoder with the watchOnce request body.
1542
func (req *WatchOnceRequest) Body(res SchemaResolver, enc *msgpack.Encoder) error {
3✔
1543
        return fillWatchOnce(enc, req.key)
3✔
1544
}
3✔
1545

1546
// Context sets a passed context to the request.
1547
func (req *WatchOnceRequest) Context(ctx context.Context) *WatchOnceRequest {
1✔
1548
        req.ctx = ctx
1✔
1549
        return req
1✔
1550
}
1✔
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