Skip to content

Commit c6df537

Browse files
committed
Initial schema support
1 parent fe15fc5 commit c6df537

File tree

13 files changed

+633
-267
lines changed

13 files changed

+633
-267
lines changed

doc/api/class-connection.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ class :class:`Connection`
77
.. autoclass:: Connection
88
:members: close, ping, space
99

10-
.. automethod:: call(func_name, *args [, field_types [, return_tuple]])
10+
.. automethod:: call(func_name, *args [, return_tuple])

doc/api/class-schema.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
.. currentmodule:: tarantool.schema
3+
4+
class :class:`Schema`
5+
--------------------
6+
7+
.. autoclass:: Schema
8+
:members:
9+
:undoc-members:

doc/guide.en.rst

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,42 +40,58 @@ It is much easier to use native types for python developer:
4040
For raw binary data ``bytes`` should be used
4141
(in this case the type casting is not performed).
4242

43-
Pass field types using argument ``field_types`` for automatic type casting::
43+
Tarantool data types corresponds to the following Python types:
44+
• ``RAW`` - ``bytes``
45+
• ``STR`` - ``unicode`` (``str`` for Python 3.x)
46+
• ``NUM`` - ``int``
47+
• ``NUM64`` - ``int`` or ``long`` (``int`` for Python 3.x)
4448

45-
>>> demo = connection.space(0, field_types=(int, unicode))
46-
>>> demo.insert((0, u'this is unicode string'))
47-
>>> demo.select(0)
48-
[(0, u'this is unicode string')]
49-
50-
As you can see, a tuple of types is passed with ``field_types``.
51-
Original "raw" fields will be casted to these native types.
52-
53-
Tarantool's tuple can contain any number of fields.
49+
Please define spaces schema to enable automatic type casting:
5450

55-
If the tuple contains more fields than types listed in ``field_types``,
56-
the latest type from ``field_types`` will be applied to all the remaining fields of the tuple.
57-
58-
Example::
59-
60-
>>> demo = connection.space(0, field_types=(int, unicode))
61-
>>> demo.insert((0, u'I am the Alpha (Α) and Omega (Ω)', b'AAAA', b'BBBB', b'CCCC', b'DDDD'))
51+
>>> import tarantool
52+
>>> schema = {
53+
0: { # Space description
54+
'name': 'users', # Space name
55+
'default_type': tarantool.STR, # Type that used to decode fields that are not listed below
56+
'fields': {
57+
0: ('numfield', tarantool.NUM), # (field name, field type)
58+
1: ('num64field', tarantool.NUM64),
59+
2: ('strfield', tarantool.STR),
60+
#2: { 'name': 'strfield', 'type': tarantool.STR }, # Alternative syntax
61+
#2: tarantool.STR # Alternative syntax
62+
},
63+
'indexes': {
64+
0: ('pk', [0]), # (name, [field_no])
65+
#0: { 'name': 'pk', 'fields': [0]}, # Alternative syntax
66+
#0: [0], # Alternative syntax
67+
}
68+
}
69+
}
70+
>>> connection = tarantool.connect(host = 'localhost', port=33013, schema = schema)
71+
>>> demo = connection.space('users')
72+
>>> demo.insert((0, 12, u'this is unicode string'))
6273
>>> demo.select(0)
63-
[(0, u'I am the Α and Ω', u'AAAA', u'BBBB', u'CCCC', u'DDDD')]
74+
[(0, 12, u'this is unicode string')]
6475

65-
As you can see, all values was converted to unicode-strings.
66-
67-
To prevent such implicit type casting it is enough to add ``bytes``
68-
as the last element of ``field_types`` tuple::
69-
70-
>>> demo = connection.space(0, field_types=(int, unicode, bytes))
71-
>>> demo.insert((0, u'I am the Alpha (Α) and Omega (Ω)', b'AAAA', b'BBBB', b'CCCC', b'DDDD'))
72-
>>> demo.select(0)
73-
[(0, u'I am the Α and Ω', 'AAAA', 'BBBB', 'CCCC', 'DDDD')]
76+
As you can see, original "raw" fields were casted to native types as defined in the schema.
7477

78+
Tarantool's tuple can contain any number of fields.
79+
If some fields are not defined then ``default_type`` will be used.
7580

81+
To prevent implicit type casting for strings use ``RAW`` type.
7682
Raw byte fields should be used if the application uses binary data
7783
(eg, images or python objects packed with ``picke``).
7884

85+
You can also specify schema for CALL results:
86+
87+
>>> ...
88+
# Copy schema decription from 'users' space
89+
>>> connection.call("box.select", '0', '0', 0L, space_name='users');
90+
[(0, 12, u'this is unicode string')]
91+
# Provide schema description explicitly
92+
>>> field_defs = [('numfield', tarantool.NUM), ('num64field', tarantool.NUM)]
93+
>>> connection.call("box.select", '0', '1', 184L, field_defs = field_defs, default_type = tarantool.STR);
94+
[(0, 12, u'this is unicode string')]
7995

8096
.. note::
8197

@@ -250,16 +266,7 @@ Select data on cities in Texas::
250266
.. rubric:: Select records explicitly specifying field types
251267

252268
Tarantool has no strict schema so all fields are raw binary byte arrays.
253-
You can specify field types in directly in
254-
:meth:`Space.select() <tarantool.space.Space.select>` method
255-
using ``field_types`` keyword argument::
256-
257-
>>> world.select(3800, field_types=(bytes, str, str, str, bytes))
258-
[('\xd8\x0e\x00\x00', 'USA', 'Texas', 'Dallas', '\xe4"\x12\x00')]
259-
260-
As you can see, ``3800`` returned
261-
as 4-byte array (string) instead of integer.
262-
269+
You can specify field types in the ``schema`` parameter to a connection.
263270

264271
Call server-side functions
265272
--------------------------

doc/guide.ru.rst

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -40,46 +40,60 @@ Tarantool поддерживает три типа полей: ``STR``, ``NUM``
4040
Для бинарных данных следует использовать тип ``bytes``
4141
(в этом случае приведение типов не производится).
4242

43-
Для автоматического приведения типов необходимо передать типы полей в параметре ``field_types``::
43+
Типы данных Tarantool соответствуют следующим типам Python:
44+
• ``RAW`` - ``bytes``
45+
• ``STR`` - ``unicode`` (``str`` for Python 3.x)
46+
• ``NUM`` - ``int``
47+
• ``NUM64`` - ``int`` or ``long`` (``int`` for Python 3.x)
4448

45-
>>> demo = connection.space(0, field_types=(int, unicode))
46-
>>> demo.insert((0, u'this is unicode string'))
47-
>>> demo.select(0)
48-
[(0, u'this is unicode string')]
49-
50-
Как видно из примера, в аргументе ``field_types`` передается кортеж типов.
51-
Исходные "сырые" поля будут приводиться к этим типам.
52-
53-
В Tarantool кортеж может содержать произвольное количество полей.
54-
55-
Если полей в кортеже больше, чем перечислено типов в ``field_types``,
56-
то последний тип из ``field_types`` применяется ко всем оставшимся полям кортежа.
57-
58-
Пример::
59-
60-
>>> demo = connection.space(0, field_types=(int, unicode))
61-
>>> demo.insert((0, u'I am the Alpha (Α) and Omega (Ω)', b'AAAA', b'BBBB', b'CCCC', b'DDDD'))
49+
Для автоматического приведения типов необходимо объявить схему:
50+
>>> import tarantool
51+
>>> schema = {
52+
0: { # Space description
53+
'name': 'users', # Space name
54+
'default_type': tarantool.STR, # Type that used to decode fields that are not listed below
55+
'fields': {
56+
0: ('user_id', tarantool.NUM), # (field name, field type)
57+
1: ('num64field', tarantool.NUM64),
58+
2: ('strfield', tarantool.STR),
59+
#2: { 'name': 'strfield', 'type': tarantool.STR }, # Alternative syntax
60+
#2: tarantool.STR # Alternative syntax
61+
},
62+
'indexes': {
63+
0: ('pk', [0]), # (name, [field_no])
64+
#0: { 'name': 'pk', 'fields': [0]}, # Alternative syntax
65+
#0: [0], # Alternative syntax
66+
}
67+
}
68+
}
69+
>>> connection = tarantool.connect(host = 'localhost', port=33013, schema = schema)
70+
>>> demo = connection.space('users')
71+
>>> demo.insert((0, 12, u'this is unicode string'))
6272
>>> demo.select(0)
63-
[(0, u'I am the Α and Ω', u'AAAA', u'BBBB', u'CCCC', u'DDDD')]
73+
[(0, 12, u'this is unicode string')]
6474

65-
Как видно из примера, все значения были преобразованы в unicode-строки.
66-
67-
Чтобы запретить такое неявное преобразование, достаточно в кортеже типов ``field_types``
68-
последним указать тип ``bytes``::
69-
70-
>>> demo = connection.space(0, field_types=(int, unicode, bytes))
71-
>>> demo.insert((0, u'I am the Alpha (Α) and Omega (Ω)', b'AAAA', b'BBBB', b'CCCC', b'DDDD'))
72-
>>> demo.select(0)
73-
[(0, u'I am the Α and Ω', 'AAAA', 'BBBB', 'CCCC', 'DDDD')]
75+
Как видно из примера, все значения были преобразованы в Python-типы в соответствии со схемой.
7476

77+
Кортеж Tarantool может содержать произвольное количество полей.
78+
Если какие-то поля не объявлены в схеме, то ``default_type`` будет использован для конвертации.
7579

7680
Поля с "сырыми" байтами следует использовать, если приложение работает с
7781
двоичными данными (например, изображения или python-объекты, сохраненные с помощью ``picke``).
7882

83+
Возможно также указать тип для CALL запросов:
84+
85+
>>> ...
86+
# Copy schema decription from 'users' space
87+
>>> connection.call("box.select", '0', '0', 0L, space_name='users');
88+
[(0, 12, u'this is unicode string')]
89+
# Provide schema description explicitly
90+
>>> field_defs = [('numfield', tarantool.NUM), ('num64field', tarantool.NUM)]
91+
>>> connection.call("box.select", '0', '1', 184L, field_defs = field_defs, default_type = tarantool.STR);
92+
[(0, 12, u'this is unicode string')]
7993

8094
.. note::
8195

82-
Python 2.6 adds :class:`bytes` as a synonym for the :class:`str` type, and it also supports the ``b''`` notation.
96+
Python 2.6 добавляет синоним :class:`bytes` к типу :class:`str` (также поддерживается синтаксис ``b''``).
8397

8498

8599
.. note:: Для преобразования между ``bytes`` и ``unicode`` всегда используется **utf-8**
@@ -250,16 +264,7 @@ Tarantool поддерживает следующие операции обно
250264
.. rubric:: Запрос с явным указанием типов полей
251265

252266
Tarantool не имеет строгой схемы и поля кортежей являются просто байтовыми массивами.
253-
Можно указать типа полей непосредственно в
254-
методе :meth:`Space.select() <tarantool.space.Space.select>`
255-
при помощи ``field_types`` keyword argument::
256-
257-
>>> world.select(3800, field_types=(bytes, str, str, str, bytes))
258-
[('\xd8\x0e\x00\x00', 'USA', 'Texas', 'Dallas', '\xe4"\x12\x00')]
259-
260-
Как видно из примера, значение ``3800`` возвращается
261-
в виде 4-байтного массива (строки) вместо целого значения.
262-
267+
Можно указать типа полей непосредственно в параметре ``schema`` для ```Connection``
263268

264269
Вызов хранимых функций
265270
----------------------

doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ API Reference
4040

4141
api/module-tarantool.rst
4242
api/class-connection.rst
43+
api/class-schema.rst
4344
api/class-space.rst
4445
api/class-response.rst
4546

doc/index.ru.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
api/module-tarantool.rst
4242
api/class-connection.rst
43+
api/class-schema.rst
4344
api/class-space.rst
4445
api/class-response.rst
4546

src/tarantool/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@
66
from tarantool.connection import Connection
77
from tarantool.const import *
88
from tarantool.error import *
9+
from tarantool.schema import *
910

10-
def connect(host="localhost", port=33013):
11+
def connect(host="localhost", port=33013, schema=None):
1112
'''\
1213
Create a connection to the Tarantool server.
1314
1415
:param str host: Server hostname or IP-address
1516
:param int port: Server port
16-
17+
:param schema: Data schema (see Developer guide and :class:`~tarantool.schema.Schema`)
18+
:type schema: :class:`~tarantool.schema.Schema` or dict
19+
1720
:rtype: :class:`~tarantool.connection.Connection`
1821
:raise: `NetworkError`
1922
'''
@@ -22,4 +25,5 @@ def connect(host="localhost", port=33013):
2225
socket_timeout=SOCKET_TIMEOUT,
2326
reconnect_max_attempts=RECONNECT_MAX_ATTEMPTS,
2427
reconnect_delay=RECONNECT_DELAY,
25-
connect_now=True)
28+
connect_now=True,
29+
schema = schema)

0 commit comments

Comments
 (0)