3232 RequestSelect ,
3333 RequestSubscribe ,
3434 RequestUpdate ,
35+ RequestUpsert ,
3536 RequestAuthenticate )
3637
3738from tarantool .space import Space
@@ -331,7 +332,7 @@ def eval(self, expr, *args):
331332 def replace (self , space_name , values ):
332333 '''
333334 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
335336
336337 :param int space_name: space id to insert a record
337338 :type space_name: int or str
@@ -347,6 +348,14 @@ def replace(self, space_name, values):
347348 return self ._send_request (request )
348349
349350 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+ '''
350359 self .user = user
351360 self .password = password
352361 if not self ._socket :
@@ -408,7 +417,8 @@ def insert(self, space_name, values):
408417 def delete (self , space_name , key , ** kwargs ):
409418 '''
410419 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.
412422
413423 :param space_name: space number or name to delete a record
414424 :type space_name: int or name
@@ -427,25 +437,139 @@ def delete(self, space_name, key, **kwargs):
427437 request = RequestDelete (self , space_name , index_name , key )
428438 return self ._send_request (request )
429439
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+
430511 def update (self , space_name , key , op_list , ** kwargs ):
431512 '''
432513 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`.
434528
435529 List of operations allows to update individual fields.
436530
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+
437547 :param space_name: space number or name to update a record
438548 :type space_name: int or str
439549 :param index: index number or name to update a record
440550 :type index: int or str
441551 :param key: key that identifies a record
442552 :type key: int or str
443553 :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), ...]
447557
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)]
449573 '''
450574 index_name = kwargs .get ("index" , 0 )
451575
0 commit comments