32
32
RequestSelect ,
33
33
RequestSubscribe ,
34
34
RequestUpdate ,
35
+ RequestUpsert ,
35
36
RequestAuthenticate )
36
37
37
38
from tarantool .space import Space
@@ -331,7 +332,7 @@ def eval(self, expr, *args):
331
332
def replace (self , space_name , values ):
332
333
'''
333
334
Execute REPLACE request.
334
- It will throw error if there's no tuple with this PK exists
335
+ It won't throw error if there's no tuple with this PK exists
335
336
336
337
:param int space_name: space id to insert a record
337
338
:type space_name: int or str
@@ -347,6 +348,14 @@ def replace(self, space_name, values):
347
348
return self ._send_request (request )
348
349
349
350
def authenticate (self , user , password ):
351
+ '''
352
+ Execute AUTHENTICATE request.
353
+
354
+ :param string user: user to authenticate with
355
+ :param string password: password for the user
356
+
357
+ :rtype: `Response` instance
358
+ '''
350
359
self .user = user
351
360
self .password = password
352
361
if not self ._socket :
@@ -408,7 +417,8 @@ def insert(self, space_name, values):
408
417
def delete (self , space_name , key , ** kwargs ):
409
418
'''
410
419
Execute DELETE request.
411
- Delete single record identified by `key` (using primary index).
420
+ Delete single record identified by `key`. If you're using secondary
421
+ index, it must be unique.
412
422
413
423
:param space_name: space number or name to delete a record
414
424
:type space_name: int or name
@@ -427,25 +437,139 @@ def delete(self, space_name, key, **kwargs):
427
437
request = RequestDelete (self , space_name , index_name , key )
428
438
return self ._send_request (request )
429
439
440
+ def upsert (self , space_name , tuple_value , op_list , ** kwargs ):
441
+ '''
442
+ Execute UPSERT request.
443
+
444
+ If there is an existing tuple which matches the key fields of
445
+ `tuple_value`, then the request has the same effect as UPDATE
446
+ and the [(field_1, symbol_1, arg_1), ...] parameter is used.
447
+
448
+ If there is no existing tuple which matches the key fields of
449
+ `tuple_value`, then the request has the same effect as INSERT
450
+ and the `tuple_value` parameter is used. However, unlike insert
451
+ or update, upsert will not read a tuple and perform error checks
452
+ before returning -- this is a design feature which enhances
453
+ throughput but requires more caution on the part of the user.
454
+
455
+ If you're using secondary index, it must be unique.
456
+
457
+ List of operations allows to update individual fields.
458
+
459
+ *Allowed operations:*
460
+
461
+ (For every operation you must provide field number, to apply this
462
+ operation to)
463
+
464
+ * `+` for addition (values must be numeric)
465
+ * `-` for subtraction (values must be numeric)
466
+ * `&` for bitwise AND (values must be unsigned numeric)
467
+ * `|` for bitwise OR (values must be unsigned numeric)
468
+ * `^` for bitwise XOR (values must be unsigned numeric)
469
+ * `:` for string splice (you must provide `offset`, `count` and `value`
470
+ for this operation)
471
+ * `!` for insertion (provide any element to insert)
472
+ * `=` for assignment (provide any element to assign)
473
+ * `#` for deletion (provide count of fields to delete)
474
+
475
+ :param space_name: space number or name to update a record
476
+ :type space_name: int or str
477
+ :param index: index number or name to update a record
478
+ :type index: int or str
479
+ :param tuple_value: tuple, that
480
+ :type tuple_value:
481
+ :param op_list: list of operations. Each operation
482
+ is tuple of three (or more) values
483
+ :type op_list: a list of the form [(symbol_1, field_1, arg_1),
484
+ (symbol_2, field_2, arg_2_1, arg_2_2, arg_2_3),...]
485
+
486
+ :rtype: `Response` instance
487
+
488
+ Operation examples:
489
+
490
+ .. code-block:: python
491
+
492
+ # 'ADD' 55 to second field
493
+ # Assign 'x' to third field
494
+ [('+', 2, 55), ('=', 3, 'x')]
495
+ # 'OR' third field with '1'
496
+ # Cut three symbols starting from second and replace them with '!!'
497
+ # Insert 'hello, world' field before fifth element of tuple
498
+ [('|', 3, 1), (':', 2, 2, 3, '!!'), ('!', 5, 'hello, world')]
499
+ # Delete two fields starting with second field
500
+ [('#', 2, 2)]
501
+ '''
502
+ index_name = kwargs .get ("index" , 0 )
503
+
504
+ if isinstance (space_name , six .string_types ):
505
+ space_name = self .schema .get_space (space_name ).sid
506
+ if isinstance (index_name , six .string_types ):
507
+ index_name = self .schema .get_index (space_name , index_name ).iid
508
+ request = RequestUpsert (self , space_name , index_name , tuple_value , op_list )
509
+ return self ._send_request (request )
510
+
430
511
def update (self , space_name , key , op_list , ** kwargs ):
431
512
'''
432
513
Execute UPDATE request.
433
- Update single record identified by `key` (using primary index).
514
+
515
+ The `update` function supports operations on fields — assignment,
516
+ arithmetic (if the field is unsigned numeric), cutting and pasting
517
+ fragments of a field, deleting or inserting a field. Multiple
518
+ operations can be combined in a single update request, and in this
519
+ case they are performed atomically and sequentially. Each operation
520
+ requires specification of a field number. When multiple operations are
521
+ present, the field number for each operation is assumed to be relative
522
+ to the most recent state of the tuple, that is, as if all previous
523
+ operations in a multi-operation update have already been applied.
524
+ In other words, it is always safe to merge multiple update invocations
525
+ into a single invocation, with no change in semantics.
526
+
527
+ Update single record identified by `key`.
434
528
435
529
List of operations allows to update individual fields.
436
530
531
+ *Allowed operations:*
532
+
533
+ (For every operation you must provide field number, to apply this
534
+ operation to)
535
+
536
+ * `+` for addition (values must be numeric)
537
+ * `-` for subtraction (values must be numeric)
538
+ * `&` for bitwise AND (values must be unsigned numeric)
539
+ * `|` for bitwise OR (values must be unsigned numeric)
540
+ * `^` for bitwise XOR (values must be unsigned numeric)
541
+ * `:` for string splice (you must provide `offset`, `count` and `value`
542
+ for this operation)
543
+ * `!` for insertion (before) (provide any element to insert)
544
+ * `=` for assignment (provide any element to assign)
545
+ * `#` for deletion (provide count of fields to delete)
546
+
437
547
:param space_name: space number or name to update a record
438
548
:type space_name: int or str
439
549
:param index: index number or name to update a record
440
550
:type index: int or str
441
551
:param key: key that identifies a record
442
552
:type key: int or str
443
553
:param op_list: list of operations. Each operation
444
- is tuple of three values
445
- :type op_list: a list of the form
446
- [(field_1, symbol_1, arg_1), (field_2, symbol_2, arg_2), ...]
554
+ is tuple of three (or more) values
555
+ :type op_list: a list of the form [(symbol_1, field_1, arg_1),
556
+ (symbol_2, field_2, arg_2_1, arg_2_2, arg_2_3), ...]
447
557
448
- :rtype: `Response` instance
558
+ :rtype: ``Response`` instance
559
+
560
+ Operation examples:
561
+
562
+ .. code-block:: python
563
+
564
+ # 'ADD' 55 to second field
565
+ # Assign 'x' to third field
566
+ [('+', 2, 55), ('=', 3, 'x')]
567
+ # 'OR' third field with '1'
568
+ # Cut three symbols starting from second and replace them with '!!'
569
+ # Insert 'hello, world' field before fifth element of tuple
570
+ [('|', 3, 1), (':', 2, 2, 3, '!!'), ('!', 5, 'hello, world')]
571
+ # Delete two fields starting with second field
572
+ [('#', 2, 2)]
449
573
'''
450
574
index_name = kwargs .get ("index" , 0 )
451
575
0 commit comments