Skip to content

Commit cd6e436

Browse files
authored
MessagePack extensions for the datetime and interval types (#3077)
* Add datetime and interval types * Update translation
1 parent ba0399a commit cd6e436

File tree

4 files changed

+248
-74
lines changed

4 files changed

+248
-74
lines changed

doc/book/box/data_model.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ In this case, the number will be stored as `cdata`_.
304304

305305
.. _index-box_decimal:
306306

307-
**decimal**. The Tarantool decimal type is stored as a MsgPack ext (Extension).
307+
**decimal**. The Tarantool decimal type is stored as a :ref:`MsgPack ext <msgpack_ext-decimal>` (Extension).
308308
Values with the decimal type are not floating-point values although
309309
they may contain decimal points.
310310
They are exact with up to 38 digits of precision.
@@ -315,7 +315,7 @@ Example: a value returned by a function in the :ref:`decimal <decimal>` module.
315315
**datetime**. Introduced in :tarantool-release:`2.10.0`.
316316
The Tarantool ``datetime`` type facilitates operations with date and time,
317317
accounting for leap years or the varying number of days in a month.
318-
It is stored as a MsgPack ext (Extension).
318+
It is stored as a :ref:`MsgPack ext <msgpack_ext-datetime>` (Extension).
319319
Operations with this data type use code from `c-dt <https://github.com/tarantool/c-dt>`_, a third-party library.
320320

321321
For more information, see :doc:`Module datetime </reference/reference_lua/datetime>`.
@@ -326,7 +326,7 @@ For more information, see :doc:`Module datetime </reference/reference_lua/dateti
326326
The Tarantool ``interval`` type represents periods of time.
327327
They can be added to or subtracted from ``datetime`` values or each other.
328328
Operations with this data type use code from `c-dt <https://github.com/tarantool/c-dt>`_, a third-party library.
329-
329+
The type is stored as a :ref:`MsgPack ext <msgpack_ext-interval>` (Extension).
330330
For more information, see :doc:`Module datetime </reference/reference_lua/datetime>`.
331331

332332
.. _index-box_string:
@@ -356,7 +356,7 @@ Example: ``"\65 \66 \67"``.
356356
**uuid**. The Tarantool uuid type is used for
357357
:ref:`Universally Unique Identifiers <uuid-module>`.
358358
Since version :doc:`2.4.1 </release/2.4.1>` Tarantool stores
359-
``uuid`` values as a MsgPack ext (Extension).
359+
``uuid`` values as a :ref:`MsgPack ext <msgpack_ext-uuid>` (Extension).
360360

361361
Example: ``64d22e4d-ac92-4a23-899a-e5934af5479``.
362362

doc/dev_guide/internals/msgpack_extensions.rst

Lines changed: 183 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
.. _internals-msgpack_ext:
2-
3-
.. _msgpack_ext-decimal:
1+
.. _internals-msgpack_ext:
42

53
----------------------------
64
MessagePack extensions
75
----------------------------
86

97
Tarantool uses predefined MessagePack extension types to represent some
10-
of the special values. Extension types include ``MP_DECIMAL``, ``MP_UUID``
11-
and ``MP_ERROR``. These types require special attention from the connector
12-
developers, as they must be treated separately from the default MessagePack
13-
types, and correctly mapped to programming language types.
8+
of the special values. Extension types include ``MP_DECIMAL``, ``MP_UUID``,
9+
``MP_ERROR``, ``MP_DATETIME``, and ``MP_INTERVAL``.
10+
These types require special attention from the connector developers,
11+
as they must be treated separately from the default MessagePack types,
12+
and correctly mapped to programming language types.
13+
14+
.. _msgpack_ext-decimal:
1415

1516
*******************************
1617
The DECIMAL type
@@ -19,19 +20,19 @@ The DECIMAL type
1920
The MessagePack EXT type ``MP_EXT`` together with the extension type
2021
``MP_DECIMAL`` is a header for values of the DECIMAL type.
2122

22-
MP_DECIMAL is 1.
23+
``MP_DECIMAL`` type is 1.
2324

24-
`MessagePack spec <https://github.com/msgpack/msgpack/blob/master/spec.md>`_
25+
`MessagePack specification <https://github.com/msgpack/msgpack/blob/master/spec.md>`_
2526
defines two kinds of types:
2627

27-
* ``fixext 1/2/4/8/16`` types have fixed length so the length is not encoded explicitly;
28+
* ``fixext 1/2/4/8/16`` types have fixed length so the length is not encoded explicitly.
2829
* ``ext 8/16/32`` types require the data length to be encoded.
2930

3031
``MP_EXP`` + optional ``length`` imply using one of these types.
3132

3233
The decimal MessagePack representation looks like this:
3334

34-
.. code-block:: none
35+
.. code-block:: none
3536
3637
+--------+-------------------+------------+===============+
3738
| MP_EXT | length (optional) | MP_DECIMAL | PackedDecimal |
@@ -42,7 +43,7 @@ Here ``length`` is the length of ``PackedDecimal`` field, and it is of type
4243

4344
``PackedDecimal`` has the following structure:
4445

45-
.. code-block:: none
46+
.. code-block:: none
4647
4748
<--- length bytes -->
4849
+-------+=============+
@@ -61,7 +62,7 @@ The rightmost digit in the array is the least significant.
6162
The first byte of the ``BCD`` array contains the first digit of the number,
6263
represented as follows:
6364

64-
.. code-block:: none
65+
.. code-block:: none
6566
6667
| 4 bits | 4 bits |
6768
= 0x = the 1st digit
@@ -70,7 +71,7 @@ represented as follows:
7071
The last byte of the ``BCD`` array contains the last digit of the number and the
7172
final ``nibble``, represented as follows:
7273

73-
.. code-block:: none
74+
.. code-block:: none
7475
7576
| 4 bits | 4 bits |
7677
= the last digit = nibble
@@ -84,21 +85,21 @@ The final ``nibble`` represents the number's sign:
8485

8586
The decimal ``-12.34`` will be encoded as ``0xd6,0x01,0x02,0x01,0x23,0x4d``:
8687

87-
.. code-block:: none
88+
.. code-block:: none
8889
8990
|MP_EXT (fixext 4) | MP_DECIMAL | scale | 1 | 2,3 | 4 (minus) |
9091
| 0xd6 | 0x01 | 0x02 | 0x01 | 0x23 | 0x4d |
9192
9293
The decimal 0.000000000000000000000000000000000010
9394
will be encoded as ``0xc7,0x03,0x01,0x24,0x01,0x0c``:
9495

95-
.. code-block:: none
96+
.. code-block:: none
9697
9798
| MP_EXT (ext 8) | length | MP_DECIMAL | scale | 1 | 0 (plus) |
9899
| 0xc7 | 0x03 | 0x01 | 0x24 | 0x01 | 0x0c |
99100
100101
101-
.. _msgpack_ext-uuid:
102+
.. _msgpack_ext-uuid:
102103

103104
**********************************
104105
The UUID type
@@ -107,31 +108,35 @@ The UUID type
107108
The MessagePack EXT type ``MP_EXT`` together with the extension type
108109
``MP_UUID`` for values of the UUID type. Since version :doc:`2.4.1 </release/2.4.1>`.
109110

110-
MP_UUID is 2.
111+
``MP_UUID`` type is 2.
111112

112-
The `MessagePack spec <https://github.com/msgpack/msgpack/blob/master/spec.md>`_
113-
defines ``d8`` to mean fixext with size 16, and a uuid's size is always 16.
114-
So the uuid MessagePack representation looks like this:
113+
The `MessagePack specification <https://github.com/msgpack/msgpack/blob/master/spec.md>`_
114+
defines ``d8`` to mean ``fixext`` with size 16, and a UUID's size is always 16.
115+
So the UUID MessagePack representation looks like this:
115116

116-
.. code-block:: none
117+
.. code-block:: none
117118
118119
+--------+------------+-----------------+
119120
| MP_EXT | MP_UUID | UuidValue |
120121
| = d8 | = 2 | = 16-byte value |
121122
+--------+------------+-----------------+
122123
123-
124124
The 16-byte value has 2 digits per byte.
125-
Typically it consists of 11 fields, which are encoded as big endian
126-
unsigned integers in the following order: time_low (4 bytes), time_mid
127-
(2 bytes), time_hi_and_version (2 bytes), clock_seq_hi_and_reserved (1
128-
byte), clock_seq_low (1 byte), node[0], ..., node[5] (1 byte each).
125+
Typically, it consists of 11 fields, which are encoded as big-endian
126+
unsigned integers in the following order:
127+
128+
* ``time_low`` (4 bytes)
129+
* ``time_mid`` (2 bytes)
130+
* ``time_hi_and_version`` (2 bytes)
131+
* ``clock_seq_hi_and_reserved`` (1 byte)
132+
* ``clock_seq_low`` (1 byte)
133+
* ``node[0]``, ..., ``node[5]`` (1 byte each)
129134

130135
Some of the functions in :ref:`Module uuid <uuid-module>` can produce values
131136
which are compatible with the UUID data type.
132137
For example, after
133138

134-
.. code-block:: none
139+
.. code-block:: none
135140
136141
uuid = require('uuid')
137142
box.schema.space.create('t')
@@ -141,26 +146,28 @@ For example, after
141146
142147
a peek at the server response packet will show that it contains
143148

144-
.. code-block:: none
149+
.. code-block:: none
145150
146151
d8 02 f6 42 3b df b4 9e 49 13 b3 61 07 40 c9 70 2e 4b
147152
148-
.. _msgpack_ext-error:
153+
.. _msgpack_ext-error:
149154

150155
****************************************************
151156
The ERROR type
152157
****************************************************
153158

154159
Since version :doc:`2.4.1 </release/2.4.1>`, responses for errors have extra information
155-
following what was described in :ref:`Box protocol -- responses for errors
156-
<box_protocol-responses_error>`.
160+
following what was described in
161+
:ref:`Box protocol -- responses for errors <box_protocol-responses_error>`.
157162
This is a "compatible" enhancement, because clients that expect old-style
158163
server responses should ignore map components that they do not recognize.
159164
Notice, however, that there has been a renaming of a constant:
160-
formerly IPROTO_ERROR in ./box/iproto_constants.h was 0x31,
161-
now IPROTO_ERROR is 0x52 and IPROTO_ERROR_24 is 0x31.
165+
formerly ``IPROTO_ERROR`` in :file:`./box/iproto_constants.h` was ``0x31``,
166+
now ``IPROTO_ERROR`` is ``0x52`` and ``IPROTO_ERROR_24`` is ``0x31``.
162167

163-
.. code-block:: none
168+
``MP_ERROR`` type is 3.
169+
170+
.. code-block:: none
164171
165172
++=========================+============================+
166173
|| | |
@@ -170,8 +177,8 @@ now IPROTO_ERROR is 0x52 and IPROTO_ERROR_24 is 0x31.
170177
++=========================+============================+
171178
MP_MAP
172179
173-
The extra information, most of which is also in :doc:`error object
174-
</reference/reference_lua/box_error/new>` fields, is:
180+
The extra information, most of which is also in
181+
:doc:`error object </reference/reference_lua/box_error/new>` fields, is:
175182

176183
``MP_ERROR_TYPE`` (0x00) (MP_STR) Type that implies source, as in :samp:`{error_object}.base_type`, for example "ClientError".
177184

@@ -203,7 +210,7 @@ For example, in version 2.4.1 or later, if we try to create a duplicate space wi
203210
``conn:eval([[box.schema.space.create('_space');]])`` |br|
204211
the server response will look like this:
205212

206-
.. code-block:: none
213+
.. code-block:: none
207214
208215
ce 00 00 00 88 MP_UINT = HEADER + BODY SIZE
209216
83 MP_MAP, size 3 (i.e. 3 items in header)
@@ -233,3 +240,141 @@ the server response will look like this:
233240
00 MP_UINT = error number
234241
05 MP_ERROR_ERRCODE
235242
0a MP_UINT = eror code ER_SPACE_EXISTS
243+
244+
245+
.. _msgpack_ext-datetime:
246+
247+
**********************************
248+
The DATETIME type
249+
**********************************
250+
251+
Since version :doc:`2.10.0 </release/2.10.0>`.
252+
The MessagePack EXT type ``MP_EXT`` together with the extension type
253+
``MP_DATETIME`` is a header for values of the DATETIME type.
254+
It creates a container with a payload of 8 or 16 bytes.
255+
256+
``MP_DATETIME`` type is 4.
257+
258+
The `MessagePack specification <https://github.com/msgpack/msgpack/blob/master/spec.md>`_
259+
defines ``d7`` to mean ``fixext`` with size 8 or ``d8`` to mean ``fixext`` with size 16.
260+
261+
So the datetime MessagePack representation looks like this:
262+
263+
.. code-block:: none
264+
265+
+---------+----------------+==========+-----------------+
266+
| MP_EXT | MP_DATETIME | seconds | nsec; tzoffset; |
267+
| = d7/d8 | = 4 | | tzindex; |
268+
+---------+----------------+==========+-----------------+
269+
270+
MessagePack data contains:
271+
272+
* Seconds (8 bytes) as an unencoded 64-bit signed integer stored in the little-endian order.
273+
274+
* The optional fields (8 bytes), if any of them have a non-zero value.
275+
The fields include ``nsec``, ``tzoffset``, and ``tzindex`` packed in the little-endian order.
276+
277+
For more information about the datetime type, see :ref:`datetime field type details <index-box_datetime>`
278+
and :doc:`reference for the datetime module </reference/reference_lua/datetime>`.
279+
280+
.. _msgpack_ext-interval:
281+
282+
**********************************
283+
The INTERVAL type
284+
**********************************
285+
286+
Since version :doc:`2.10.0 </release/2.10.0>`.
287+
The MessagePack EXT type ``MP_EXT`` together with the extension type
288+
``MP_INTERVAL`` is a header for values of the INTERVAL type.
289+
290+
``MP_INTERVAL`` type is 6.
291+
292+
The interval is saved as a variant of a map with a predefined number of known attribute names.
293+
If some attributes are undefined, they are omitted from the generated payload.
294+
295+
The interval MessagePack representation looks like this:
296+
297+
.. code-block:: none
298+
299+
+--------+-------------------------+-------------+----------------+
300+
| MP_EXT | Size of packed interval | MP_INTERVAL | PackedInterval |
301+
+--------+-------------------------+-------------+----------------+
302+
303+
Packed interval consists of:
304+
305+
* Packed number of non-zero fields.
306+
* Packed non-null fields.
307+
308+
Each packed field has the following structure:
309+
310+
.. code-block:: none
311+
312+
+----------+=====================+
313+
| field ID | field value |
314+
+----------+=====================+
315+
316+
The number of defined (non-null) fields can be zero.
317+
In this case, the packed interval will be encoded as integer 0.
318+
319+
List of the field IDs:
320+
321+
* 0 -- year
322+
* 1 -- month
323+
* 2 -- week
324+
* 3 -- day
325+
* 4 -- hour
326+
* 5 -- minute
327+
* 6 -- second
328+
* 7 -- nanosecond
329+
* 8 -- adjust
330+
331+
**Example**
332+
333+
Interval value ``1 years, 200 months, -77 days`` is encoded in the following way:
334+
335+
.. code-block:: tarantoolsession
336+
337+
tarantool> I = datetime.interval.new{year = 1, month = 200, day = -77}
338+
---
339+
...
340+
341+
tarantool> I
342+
---
343+
- +1 years, 200 months, -77 days
344+
...
345+
346+
tarantool> M = msgpack.encode(I)
347+
---
348+
...
349+
350+
tarantool> M
351+
---
352+
- !!binary xwsGBAABAczIA9CzCAE=
353+
...
354+
355+
tarantool> tohex = function(s) return (s:gsub('.', function(c) return string.format('%02X ', string.byte(c)) end)) end
356+
---
357+
...
358+
359+
tarantool> tohex(M)
360+
---
361+
- 'C7 0B 06 04 00 01 01 CC C8 03 D0 B3 08 01 '
362+
...
363+
364+
Where:
365+
366+
* C7 -- MP_EXT
367+
* 0B -- size of a packed interval value (11 bytes)
368+
* 06 -- MP_INTERVAL type
369+
* 04 -- number of defined fields
370+
* 00 -- field ID (year)
371+
* 01 -- packed value ``1``
372+
* 01 -- field ID (month)
373+
* CCC8 -- packed value ``200``
374+
* 03 -- field ID (day)
375+
* D0B3 -- packed value ``-77``
376+
* 08 -- field ID (adjust)
377+
* 01 -- packed value ``1`` (DT_LIMIT)
378+
379+
For more information about the interval type, see :ref:`interval field type details <index-box_interval>`
380+
and :doc:`description of the datetime module </reference/reference_lua/datetime>`.

locale/ru/LC_MESSAGES/book/box/data_model.po

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -531,12 +531,12 @@ msgstr ""
531531
msgid ""
532532
"**uuid**. The Tarantool uuid type is used for :ref:`Universally Unique "
533533
"Identifiers <uuid-module>`. Since version :doc:`2.4.1 </release/2.4.1>` "
534-
"Tarantool stores ``uuid`` values as a MsgPack ext (Extension)."
534+
"Tarantool stores ``uuid`` values as a :ref:`MsgPack ext <msgpack_ext-uuid>` (Extension)."
535535
msgstr ""
536536
"**uuid**. Тип uuid в Tarantool используется для :ref:`универсальных "
537537
"уникальных идентификаторов (UUID) <uuid-module>`. Начиная с версии "
538-
":doc:`2.4.1 </release/2.4.1>` Tarantool хранит значения ``uuid`` в формате "
539-
"MsgPack ext (Extension)."
538+
":doc:`2.4.1 </release/2.4.1>`, Tarantool хранит значения ``uuid`` в формате "
539+
":ref:`MsgPack ext <msgpack_ext-uuid>` (Extension)."
540540

541541
msgid "Example: ``64d22e4d-ac92-4a23-899a-e5934af5479``."
542542
msgstr "Пример: ``64d22e4d-ac92-4a23-899a-e5934af5479``."

0 commit comments

Comments
 (0)