From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: "Алексей Гаджиев" <alexey.gadzhiev@corp.mail.ru>, tarantool-patches@freelists.org Cc: Konstantin Osipov <kostja@tarantool.org> Subject: [tarantool-patches] Re: Fwd: [PATCH 1/1] rfc: describe a Tarantool wire protocol Date: Thu, 5 Apr 2018 12:37:50 +0300 [thread overview] Message-ID: <fa3b3810-e2e6-1944-d58e-262ab6ab68f5@tarantool.org> (raw) In-Reply-To: <1522918872.186733999@f420.i.mail.ru> 05.04.2018 12:01, Алексей Гаджиев (Redacted sender alexey.gadzhiev for DMARC) пишет: > Looks cool! Now we can send chunked data! > > I have one question: > Is IPROTO_OK mandatory packet in the response messages sequence? Yes, IPROTO_OK is mandatory. > How can I detect if next push/result_set available if previous > consists only of one chunk without SQL_INFO_HAS_NEXT_CHUNK? See the state machine picture - next chunk is available, if in the header the response type is IPROTO_CHUNK. SQL_INFO_HAS_NEXT_CHUNK just means, that the next chunk is logically linked with the current. And I have 2 better ideas instead of the 'has_next_chunk' flag: 1) Lets instead of SQL_INFO_HAS_NEXT_CHUNK, that is placed in body, introduce a header flag: IPROTO_CHUNK_IS_CHAIN. When a several chunks are logically linked (for example, they are parts of the same result set), all of them, except last, contains this flag. I think, that 'Chain' term is more easy to understand, than 'HAS_NEXT_CHUNK'. Moreover, HAS_NEXT_CHUNK can be false, but a client must read more responses, if the message does not contain IPROTO_OK - it confuses. Actually IPROTO_CHUNK in the header is the single sign, that more responses are available. The sample of responses: IPROTO_CHUNK | IPROTO_CHUNK, IS_CHAIN | +--IPROTO_CHUNK, IS_CHAIN | +--IPROTO_CHUNK, IS_CHAIN | +--IPROTO_CHUNK | IPROTO_CHUNK | ... | IPROTO_OK/ERROR 2) The similar idea - instead of IPROTO_CHUNK_IS_CHAIN lest introduce IPROTO_CHAIN_ID - it is an identifier, that is unique for each chunks sequence. And I like this variant most, because in a future it can be extended to allow mixing different chains. The sample of responses: IPROTO_CHUNK | IPROTO_CHUNK, CHAIN_ID = 1 | +--IPROTO_CHUNK, CHAIN_ID = 1 | +--IPROTO_CHUNK, CHAIN_ID = 1 | IPROTO_CHUNK | IPROTO_CHUNK, CHAIN_ID = 2 | +--IPROTO_CHUNK, CHAIN_ID = 2 | +--IPROTO_CHUNK, CHAIN_ID = 2 | IPROTO_CHUNK | ... | IPROTO_OK/ERROR > > With best regards, > Alex > > > Четверг, 5 апреля 2018, 9:32 +03:00 от Alexey Gadzhiev > <alg1973@gmail.com>: > > > ---------- Forwarded message ---------- > From: *Vladislav Shpilevoy* <v.shpilevoy@tarantool.org > <//e.mail.ru/compose/?mailto=mailto%3av.shpilevoy@tarantool.org>> > Date: Thu, Apr 5, 2018 at 12:22 AM > Subject: [PATCH 1/1] rfc: describe a Tarantool wire protocol > To: tarantool-patches@freelists.org > <//e.mail.ru/compose/?mailto=mailto%3atarantool%2dpatches@freelists.org> > Cc: kostja@tarantool.org > <//e.mail.ru/compose/?mailto=mailto%3akostja@tarantool.org>, > alg1973@gmail.com > <//e.mail.ru/compose/?mailto=mailto%3aalg1973@gmail.com>, > Vladislav Shpilevoy <v.shpilevoy@tarantool.org > <//e.mail.ru/compose/?mailto=mailto%3av.shpilevoy@tarantool.org>> > > > --- > Original: > https://github.com/tarantool/tarantool/blob/sql-proto-rfc/doc/RFC/wire_protocol.md > > doc/RFC/wire_protocol.md <http://wire_protocol.md> | 214 > +++++++++++++++++++++++++++++++++++++++++ > doc/RFC/wire_protocol_img1.png | Bin 0 -> 48970 bytes > 2 files changed, 214 insertions(+) > create mode 100644 doc/RFC/wire_protocol.md <http://wire_protocol.md> > create mode 100644 doc/RFC/wire_protocol_img1.png > > diff --git a/doc/RFC/wire_protocol.md <http://wire_protocol.md> > b/doc/RFC/wire_protocol.md <http://wire_protocol.md> > new file mode 100644 > index 000000000..d1fc1329c > --- /dev/null > +++ b/doc/RFC/wire_protocol.md <http://wire_protocol.md> > @@ -0,0 +1,214 @@ > +# Tarantool Wire protocol > + > +* **Status**: In progress > +* **Start date**: 04-04-2018 > +* **Authors**: Vladislav Shpilevoy @Gerold103 > v.shpilevoy@tarantool.org > <//e.mail.ru/compose/?mailto=mailto%3av.shpilevoy@tarantool.org>, > Konstantin Osipov @kostja kostja@tarantool.org > <//e.mail.ru/compose/?mailto=mailto%3akostja@tarantool.org>, > Alexey Gadzhiev @alg1973 alg1973@gmail.com > <//e.mail.ru/compose/?mailto=mailto%3aalg1973@gmail.com> > +* **Issues**: > [#2677](https://github.com/tarantool/tarantool/issues/2677), > [#2620](https://github.com/tarantool/tarantool/issues/2620), > [#2618](https://github.com/tarantool/tarantool/issues/2618) > + > +## Summary > + > +Tarantool wire protocol is a convention how to encode and send > results of execution of SQL, Lua and C stored functions, DML (Data > Manipulation Language), DDL (Data Definition Language), DQL (Data > Query Language) requests to remote clients via network. The > protocol is unified for all request types. For a single request > multiple responses of different types can be sent. > + > +## Background and motivation > + > +Tarantool wire protocol is called **IProto**, and is used by > database connectors written on different languages and working on > remote clients. The protocol describes how to distinguish > different message types and what data can be stored in each > message. Tarantool has the following response types: > +* A response, that finalizes a request, and has just data - > tuples array, or scalar values, or mixed. It has no any metadata. > This response type incorporates results of any pure Lua and C > calls including stored procedures, space and index methods. Such > response is single per request; > +* A response with just data, but with no request finalization - > it is so called push-message. During single request execution > multiple pushes can be sent, and they do not finalize the request > - a client must be ready to receive more responses; > +* A formatted response, that is sent on SQL DQL and does not > finalize a request. Such response contains metadata with result > set column names, types, flags etc; > +* A response with metadata only, that is sent on SQL DDL/DML > requests, and contains affected row count, last autoincrement > column value, flags; > +* A response with error message and code, that finalizes a request. > + > +In supporting this responses set 2 main challenges appear: > +1. How to unify responses; > +2. How to support multiple messages inside a single request. > + > +To understand how a single request can produce multiple > responses, consider the stored procedure (do not pay attention to > the syntax - it does not matter here): > +```SQL > +FUNCTION my_sql_func(a1, a2, a3, a4) BEGIN > + SELECT my_lua_func(a1); > + SELECT * FROM table1; > + SELECT my_c_func(a2); > + INSERT INTO table1 VALUES (1, 2, 3); > + RETURN a4; > +END > +``` > +, where `my_lua_func()` is the function, written in Lua and > sending its own push-messages: > +```Lua > +function my_lua_func(arg) > + box.session.push(arg) > + return arg > +end > +``` > +and `my_c_func()` is the function, written in C and returning > some raw data: > +```C > +int > +my_c_func(box_function_ctx_t *ctx) { > + box_tuple_t *tuple; > + /* Fill a tuple with any data. */ > + return box_return_tuple(ctx, tuple); > +} > +``` > +Consider each statement: > +* `SELECT FROM` can split a big result set in multiple messages; > +* `SELECT my_lua_func()` produces 2 messages: one is the > push-message generated in `my_lua_func` and another is the result > of `SELECT` itself; > +* `INSERT` creates 1 message with metadata; > +* `RETURN` creates a final response message. > + > +Of course, some of messages, or even all of them can be batched > and send as a single TCP packet, but it does not matter for the > wire protocol. > + > +In the next section it is described, how the Tarantool wire > protocol deals with this mess. > + > +For the protocol details - code values, all header and body keys > - see Tarantool [website](tarantool.io <http://tarantool.io>). > + > +## Detailed design > + > +Tarantool response consists of a body and a header. Header is > used to store response code and some internal metainfo such as > schema version, request id (called **sync** in Tarantool). Body is > used to store result data and request-dependent metainfo. > + > +### Header > + > +There are 3 response codes in header: > +* `IPROTO_OK` - the last response in a request, that is finished > successfully; > +* `IPROTO_CHUNK` - non-final response. One request can generate > multuple chunk messages; > +* `IPROTO_ERROR | error code` - the last response in a request, > that is finished with an error. > + > +`IPROTO_ERROR` response is trivial, and consists just of code and > message. It is no considered further. > +`IPROTO_OK` and `IPROTO_CHUNK` have the same body format. The > only exception between them is that `IPROTO_OK` finalizes the > request. In the next subsection the body format is presented. > + > +### Body > + > +The common body structure: > +``` > ++----------------------------------------------+ > +| IPROTO_BODY: { | > +| IPROTO_METADATA: [ | > +| { | > +| IPROTO_FIELD_NAME: string, | > +| IPROTO_FIELD_TYPE: number, | > +| IPROTO_FIELD_FLAGS: number, | > +| }, | > +| ... | > +| ], | > +| | > +| IPROTO_SQL_INFO: { | > +| SQL_INFO_ROW_COUNT: number, | > +| SQL_INFO_LAST_ID: number, | > +| SQL_INFO_FLAGS: number, | > +| ... | > +| }, | > +| | > +| IPROTO_DATA: [ | > +| tuple/scalar, | > +| ... | > +| ] | > +| } | > ++----------------------------------------------+ > +``` > +For a while the single `SQL_INFO_FLAGS` value is available: > `SQL_INFO_HAS_NEXT_CHUNK` - a response having this flag means, > that the current result set is not fully read - more responses are > available. For example, it could be big `SELECT FROM` sent in > multiple chunks. > + > +Consider, how different responses use the body, and how they can > be distinguished. > + > +_A non formatted response_ has only `IPROTO_DATA` key in a body. > It is the result of Lua and C DML, DDL, DQL, stored procedures > calls, push messages. Such response is never linked with next or > previous messages of the same request. > + > +_A non formatted response with metadata_ has only > `IPROTO_SQL_INFO` and it is always result of DDL/DML executed via > SQL. As well as the previous type, this response is all-independent. > + > +_A formatted response_ always has `IPROTO_DATA`, and can have > both `IPROTO_SQL_INFO` and `IPROTO_METADATA`. It is always result > of SQL DQL (`SELECT`). The response can be part of a continuous > sequence of responses. A first message of the sequence always > contains `IPROTO_METADATA`, while all non-last ones always contain > `IPROTO_SQL_INFO` with `SQL_INFO_HAS_NEXT_CHUNK` flag. The last > message has only `IPROTO_DATA` or nothing. > + > +On the picture the state machine of the protocol is showed: > +![alt > text](https://raw.githubusercontent.com/tarantool/tarantool/sql-proto-rfc/doc/RFC/wire_protocol_img1.png) > + > +For the `FUNCTION my_sql_func` call the following responses are sent: > +``` > +/* Push from my_lua_func(a1). */ > ++----------------------------------------------+ > +| HEADER: IPROTO_CHUNK | > ++- - - - - - - - - - - - - - - - - - - - - - - + > +| BODY: { | > +| IPROTO_DATA: [ a1 ] | > +| } | > ++----------------------------------------------+ > + > +/* Result of SELECT my_lua_func(a1). */ > ++----------------------------------------------+ > +| HEADER: IPROTO_CHUNK | > ++- - - - - - - - - - - - - - - - - - - - - - - + > +| BODY: { | > +| IPROTO_DATA: [ [ a1 ] ], | > +| IPROTO_METADATA: [ | > +| { /* field name, type ... */ } | > +| ] | > +| } | > ++----------------------------------------------+ > + > +/* First chunk of SELECT * FROM table1. */ > ++----------------------------------------------+ > +| HEADER: IPROTO_CHUNK | > ++- - - - - - - - - - - - - - - - - - - - - - - + > +| BODY: { | > +| IPROTO_DATA: [ tuple1, tuple2, ... ] | > +| IPROTO_METADATA: [ | > +| { /* field1 name, type ... */ }, | > +| { /* field2 name, type ... */ }, | > +| ... | > +| ], | > +| IPROTO_SQL_INFO: { | > +| SQL_INFO_FLAGS: | > +| SQL_INFO_HAS_NEXT_CHUNK | > +| } | > +| } | > ++----------------------------------------------+ > + > + /* From second to next to last chunk. */ > + +----------------------------------------------+ > + | HEADER: IPROTO_CHUNK | > + +- - - - - - - - - - - - - - - - - - - - - - - + > + | BODY: { | > + | IPROTO_DATA: [ tuple1, tuple2, ... ], | > + | IPROTO_SQL_INFO: { | > + | SQL_INFO_FLAGS: | > + | SQL_INFO_HAS_NEXT_CHUNK | > + | } | > + | } | > + +----------------------------------------------+ > + > + /* Last chunk. */ > + +----------------------------------------------+ > + | HEADER: IPROTO_CHUNK | > + +- - - - - - - - - - - - - - - - - - - - - - - + > + | BODY: { | > + | IPROTO_DATA: [ tuple1, tuple2, ... ] | > + | } | > + +----------------------------------------------+ > + > +/* Result of SELECT my_c_func(a2). */ > ++----------------------------------------------+ > +| HEADER: IPROTO_CHUNK | > ++- - - - - - - - - - - - - - - - - - - - - - - + > +| BODY: { | > +| IPROTO_DATA: [ [ tuple ] ], | > +| IPROTO_METADATA: [ | > +| { /* field name, type ... */ } | > +| ] | > +| } | > ++----------------------------------------------+ > + > +/* Result of INSERT INTO table1 VALUES (1, 2, 3). */ > ++----------------------------------------------+ > +| HEADER: IPROTO_CHUNK | > ++- - - - - - - - - - - - - - - - - - - - - - - + > +| BODY: { | > +| IPROTO_SQL_INFO: { | > +| SQL_INFO_ROW_COUNT: number, | > +| SQL_INFO_LAST_ID: number, | > +| } | > +| } | > ++----------------------------------------------+ > + > +/* Result of RETURN a4 */ > ++----------------------------------------------+ > +| HEADER: IPROTO_OK | > ++- - - - - - - - - - - - - - - - - - - - - - - + > +| BODY: { | > +| IPROTO_DATA: [ a4 ] | > +| } | > ++----------------------------------------------+ > +``` > -- > 2.14.3 (Apple Git-98) > > > > > -- >
next prev parent reply other threads:[~2018-04-05 9:37 UTC|newest] Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-04-04 21:22 [tarantool-patches] " Vladislav Shpilevoy 2018-04-05 8:25 ` [tarantool-patches] " Konstantin Osipov 2018-04-09 15:31 ` [tarantool-patches] " Vladislav Shpilevoy 2018-06-28 11:45 ` [tarantool-patches] " Konstantin Osipov [not found] ` <CAFoyxqh0QqNBVr7tuFF_uoUw-CvBKOVA3FCyWvixikberOxP9w@mail.gmail.com> 2018-04-05 9:01 ` [tarantool-patches] Re: Fwd: " Алексей Гаджиев 2018-04-05 9:37 ` Vladislav Shpilevoy [this message] 2018-04-05 10:03 ` Konstantin Osipov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=fa3b3810-e2e6-1944-d58e-262ab6ab68f5@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=alexey.gadzhiev@corp.mail.ru \ --cc=kostja@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: Fwd: [PATCH 1/1] rfc: describe a Tarantool wire protocol' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox