1- .. _internals-msgpack_ext :
2-
3- .. _msgpack_ext-decimal :
1+ .. _internals-msgpack_ext :
42
53----------------------------
64MessagePack extensions
75----------------------------
86
97Tarantool 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*******************************
1617The DECIMAL type
@@ -19,19 +20,19 @@ The DECIMAL type
1920The 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 >`_
2526defines 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
3233The 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.
6162The first byte of the ``BCD `` array contains the first digit of the number,
6263represented 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:
7071The last byte of the ``BCD `` array contains the last digit of the number and the
7172final ``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
8586The 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
9394will 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**********************************
104105The UUID type
@@ -107,31 +108,35 @@ The UUID type
107108The 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
130135Some of the functions in :ref: `Module uuid <uuid-module >` can produce values
131136which are compatible with the UUID data type.
132137For 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****************************************************
151156The ERROR type
152157****************************************************
153158
154159Since 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 >`.
157162This is a "compatible" enhancement, because clients that expect old-style
158163server responses should ignore map components that they do not recognize.
159164Notice, 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 |
204211the 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 >`.
0 commit comments