Skip to content

Commit 318b91f

Browse files
api: any msgpack supported type as a request key
Inserting a tuple with connector does not have any type restrictions on its contents: any MessagePack supported type is allowed. If there are any type violations on the Tarantool side, server would return the corresponding error. There is no reason to do any explicit type checks for request keys. This patch fixed using extended types as keys. Tarantool 2.10 does not support indexing intervals, so there are no tests for INTERVAL extension type. Closes #240
1 parent 10adf37 commit 318b91f

File tree

6 files changed

+64
-21
lines changed

6 files changed

+64
-21
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
146146

147147
### Fixed
148148
- Package build (#238).
149+
- Allow any MessagePack supported type as a request key (#240).
149150

150151
## 0.9.0 - 2022-06-20
151152

Diff for: tarantool/connection.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@
8686
)
8787
from tarantool.schema import Schema
8888
from tarantool.utils import (
89-
check_key,
9089
greeting_decode,
9190
version_id,
91+
wrap_key,
9292
ENCODING_DEFAULT,
9393
)
9494

@@ -1220,7 +1220,7 @@ def delete(self, space_name, key, *, index=0):
12201220
.. _delete: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/delete/
12211221
"""
12221222

1223-
key = check_key(key)
1223+
key = wrap_key(key)
12241224
if isinstance(space_name, str):
12251225
space_name = self.schema.get_space(space_name).sid
12261226
if isinstance(index, str):
@@ -1349,7 +1349,7 @@ def update(self, space_name, key, op_list, *, index=0):
13491349
.. _update: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/update/
13501350
"""
13511351

1352-
key = check_key(key)
1352+
key = wrap_key(key)
13531353
if isinstance(space_name, str):
13541354
space_name = self.schema.get_space(space_name).sid
13551355
if isinstance(index, str):
@@ -1534,7 +1534,7 @@ def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, i
15341534

15351535
# Perform smart type checking (scalar / list of scalars / list of
15361536
# tuples)
1537-
key = check_key(key, select=True)
1537+
key = wrap_key(key, select=True)
15381538

15391539
if isinstance(space_name, str):
15401540
space_name = self.schema.get_space(space_name).sid

Diff for: tarantool/utils.py

+12-17
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import sys
22
import uuid
33

4-
supported_types = (int, str, bytes, float,)
5-
64
ENCODING_DEFAULT = "utf-8"
75

86
from base64 import decodebytes as base64_decode
@@ -22,33 +20,30 @@ def strxor(rhs, lhs):
2220

2321
return bytes([x ^ y for x, y in zip(rhs, lhs)])
2422

25-
def check_key(*args, **kwargs):
23+
def wrap_key(*args, first=True, select=False):
2624
"""
27-
Validate request key types and map.
25+
Wrap request key in list, if needed.
2826
2927
:param args: Method args.
3028
:type args: :obj:`tuple`
3129
32-
:param kwargs: Method kwargs.
33-
:type kwargs: :obj:`dict`
30+
:param first: ``True`` if this is the first recursion iteration.
31+
:type first: :obj:`bool`
32+
33+
:param select: ``True`` if wrapping SELECT request key.
34+
:type select: :obj:`bool`
3435
3536
:rtype: :obj:`list`
3637
"""
3738

38-
if 'first' not in kwargs:
39-
kwargs['first'] = True
40-
if 'select' not in kwargs:
41-
kwargs['select'] = False
42-
if len(args) == 0 and kwargs['select']:
39+
if len(args) == 0 and select:
4340
return []
4441
if len(args) == 1:
45-
if isinstance(args[0], (list, tuple)) and kwargs['first']:
46-
kwargs['first'] = False
47-
return check_key(*args[0], **kwargs)
48-
elif args[0] is None and kwargs['select']:
42+
if isinstance(args[0], (list, tuple)) and first:
43+
return wrap_key(*args[0], first=False, select=select)
44+
elif args[0] is None and select:
4945
return []
50-
for key in args:
51-
assert isinstance(key, supported_types)
46+
5247
return list(args)
5348

5449

Diff for: test/suites/test_datetime.py

+15
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ def setUpClass(self):
3232
parts = {1, 'string'},
3333
unique = true})
3434
35+
pcall(function()
36+
box.schema.space.create('test_pk')
37+
box.space['test_pk']:create_index('primary', {
38+
type = 'tree',
39+
parts = {1, 'datetime'},
40+
unique = true})
41+
end)
42+
3543
box.schema.user.create('test', {password = 'test', if_not_exists = true})
3644
box.schema.user.grant('test', 'read,write,execute', 'universe')
3745
@@ -528,6 +536,13 @@ def test_tarantool_datetime_addition_winter_time_switch(self):
528536
[case['res']])
529537

530538

539+
@skip_or_run_datetime_test
540+
def test_primary_key(self):
541+
data = [tarantool.Datetime(year=1970, month=1, day=1), 'content']
542+
543+
self.assertSequenceEqual(self.con.insert('test_pk', data), [data])
544+
self.assertSequenceEqual(self.con.select('test_pk', data[0]), [data])
545+
531546
@classmethod
532547
def tearDownClass(self):
533548
self.con.close()

Diff for: test/suites/test_decimal.py

+16
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ def setUpClass(self):
3131
parts = {1, 'string'},
3232
unique = true})
3333
34+
pcall(function()
35+
box.schema.space.create('test_pk')
36+
box.space['test_pk']:create_index('primary', {
37+
type = 'tree',
38+
parts = {1, 'decimal'},
39+
unique = true})
40+
end)
41+
3442
box.schema.user.create('test', {password = 'test', if_not_exists = true})
3543
box.schema.user.grant('test', 'read,write,execute', 'universe')
3644
""")
@@ -421,6 +429,14 @@ def test_tarantool_encode_with_precision_loss(self):
421429
self.assertSequenceEqual(self.con.eval(lua_eval), [True])
422430

423431

432+
@skip_or_run_decimal_test
433+
def test_primary_key(self):
434+
data = [decimal.Decimal('0'), 'content']
435+
436+
self.assertSequenceEqual(self.con.insert('test_pk', data), [data])
437+
self.assertSequenceEqual(self.con.select('test_pk', data[0]), [data])
438+
439+
424440
@classmethod
425441
def tearDownClass(self):
426442
self.con.close()

Diff for: test/suites/test_uuid.py

+16
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ def setUpClass(self):
3131
parts = {1, 'string'},
3232
unique = true})
3333
34+
pcall(function()
35+
box.schema.space.create('test_pk')
36+
box.space['test_pk']:create_index('primary', {
37+
type = 'tree',
38+
parts = {1, 'uuid'},
39+
unique = true})
40+
end)
41+
3442
box.schema.user.create('test', {password = 'test', if_not_exists = true})
3543
box.schema.user.grant('test', 'read,write,execute', 'universe')
3644
""")
@@ -125,6 +133,14 @@ def test_tarantool_encode(self):
125133
self.assertSequenceEqual(self.con.eval(lua_eval), [True])
126134

127135

136+
@skip_or_run_UUID_test
137+
def test_primary_key(self):
138+
data = [uuid.UUID('ae28d4f6-076c-49dd-8227-7f9fae9592d0'), 'content']
139+
140+
self.assertSequenceEqual(self.con.insert('test_pk', data), [data])
141+
self.assertSequenceEqual(self.con.select('test_pk', data[0]), [data])
142+
143+
128144
@classmethod
129145
def tearDownClass(self):
130146
self.con.close()

0 commit comments

Comments
 (0)