Tarantool/Box IPROTO protocol.
;
; The latest version of this document can be found in
; tarantool source tree, doc/box-protocol.txt
;
; IPROTO is a binary request/response protocol that features a
; complete access to Tarantool functionality, including:
; - request multiplexing, e.g. ability to asynchronously issue
;   multiple requests via the same connection
; - response format that supports zero-copy writes
;
; The atoms of representation in the protocol include:
;
; int8 - a single 8-bit byte (i.e. an octet)
;
; int32 - a 32-bit integer in little-endian format (Intel x86)

; int64 - a 64-bit integer in little-endian format (Intel x86)
;
; int32_varint - a 1 to 5 byte representation of an integer
;
; This is what Perl's "pack" function calls "BER compressed 
; integer (BER stands for Basic Encoding Rules, but in reality it
; has little to do with ASN.1 standard). 
; See http://en.wikipedia.org/wiki/LEB128
; for encoding description, or core/pickle.m for implementation
; in Tarantool.

; All requests and responses utilize the same basic structure:

<packet> ::= <request> | <response>

<request> ::= <header><request_body>

; If <return_code> is non-zero, the rest of server
; response is an error message.
;

<response> ::= <header><return_code>{<response_body>}

;
; <header> has a fixed structure of three 4-byte integers (12 bytes):

<header> ::= <type><body_length><request_id>

; <type> represents a request type, a single server command,
; such as PING, SELECT, UPDATE, DELETE, INSERT, etc.
; <type> is replicated intact in the response header.
; The currently supported types are:
; - 13    -- <insert>
; - 17    -- <select>
; - 19    -- <update>
; - 21    -- <delete>
; - 22    -- <call>
; - 65280 -- <ping>
; This list is sparse since a number of old commands
; were deprecated and removed.

<type> ::= <int32>

;
; <body_length> tells the sender or receiver the length of data
; that follows the header. If there is no data, <body_length> is 0.
; However, <request_body> is always present.
;
; The only exception is <ping>: its request body is empty, and
; so is response. In other words, <ping> request packet
; consists solely of a 12-byte header (65280, 0, 0)
; and gets the same 12-byte header in response.

<body_length> ::= <int32>

;
; <request_id> is a unique request identifier set by the client,
; The identifier is necessary to allow request multiplexing --
; i.e. sending multiple requests through the same connection
; before fetching a response to any of them.
; The value of the identifier currently bears no meaning to the
; server. Similarly to request <type>, it's simply copied to the
; response header as-is.
; Consequently, <request_id> can be 0 or two requests
; can have an identical id.

<request_id> ::= <int32>

; <request_body> holds actual command data.
; Its format and interpretation are defined by the value of
; request <type>.

<request_body> ::= <select_request_body> |
                   <insert_request_body> |
                   <update_request_body> |
                   <delete_request_body> |
                   <call_request_body>

;
; <response_body> carries command reply
; It is only present if <return_code> is 0 (success).
; <call_response_body> can be arbitrary, it purely depends
; on what your procedure does.
; 

<response_body> ::= <select_response_body> |
                    <insert_response_body> |
                    <update_response_body> |
                    <delete_response_body>

; <select_request_body> (required <header> <type> is 17):
;
; Specify which space to query, which index in the space
; to use, offset in the resulting tuple set (set to 0 for no offset),
; a limit (set to 4294967295 for no limit), and one or several
; keys to use in lookup. When more than one key is given, they
; specify a disjunctive search condition (key1 or key2 or ...).
;
; Note, that <tuple> is mandatory, and tuple <count>
; must be non-zero.
;

<select_request_body> ::= <space_no><index_no>
                          <offset><limit><count><tuple>+

; Space number is a non-negative integer, starting from 0.
; All spaces are defined in the server configuration file,
; and then referred to by numeric id.

<space_no> ::= <int32>

; Tarantool supports HASH and TREE indexes. Indexes are
; enumerated similarly to spaces, starting from 0.
; Each space has at least index #0, which defines
; the primary key.

<index_no> ::= <int32>

; offset in the result set

<offset> ::= <int32>

; limit for the result set

<limit> ::= <int32>

; key count in the conjunctive set. Tarantool will
; consequently return tuples that match the first key,
; then the second, and so on. If a tuple matches
; more than one key, it's returned twice. <limit> 
; thus limits the total number of returned tuples,
; which are not necessarily distinct.

<count> ::= <int32>

;
; A tuple that represents a search key simply lists all key
; fields, preceded with key cardinality (number of list
; elements). Each key in <select_request_body> can have a
; different cardinality.

<tuple> ::= <cardinality><field>+

;
; If a key is not fully specified, i.e. has smaller cardinality
; than the corresponding index, each unspecified field is treated
; as a wildcard.
;

<cardinality> ::= <int32>

;
; A field represents a single atom of storage. In key/value
; paradigm, Tarantool's "value" is a sequence of fields.
; A single unit of storage, therefore, must contain all fields
; of all (possibly multipart) keys and zero or more fields
; treated as "data". To do a <select> the user only needs to
; define fields of the key used for search.
;

<field> ::= <int32_varint><data>

; Tarantool understands only 3 field types: unsigned 4-byte
; int, unsigned 8-byte int and an octet string.
; Even this type awareness is very limited: it's only used when
; the field participates in an index. For example, when a numeric
; 32-bit index is defined on a field, and a non-32-bit value
; is supplied for that field, an ER_BAD_PARAMS
; is returned.
;

<data> ::= <int8>+

;
; Compressed integer
;

<int32_varint> ::= <int8>+
;
; SELECT may return zero, one or several tuples.
; CALL response is identical to one for SELECT.
; <select_response_body> starts with the number of found
; tuples:
;

<select_response_body> ::= <count><fq_tuple>*

;
; Tuples returned by the server (we call them "fully qualified")
; are always preceded with calculated information:
; total size of the tuple and number of fields in it.
; This is how the tuple is stored on server side.
; While this information can be often derived from body length,
; it allows the recipient to simplify memory allocation and tuple
; decoding. Certain requests, such as
; <select>, can return more than one tuple. In that case
; fully qualified tuples are also used to identify tuple
; boundaries: in Tarantool, tuples have variable cardinality.
;

<fq_tuple> ::= <size><tuple>

; length of the variable part of the tuple (all tuple fields)
<size> ::= <int32>

;
; It is not possible to insert more than one tuple at a time.
; Thus <insert_request_body> (<header> <type> = 13) simply
; holds one tuple, and which space to put it into.
;

<insert_request_body> ::= <space_no><flags><tuple>

; Flag BOX_RETURN_TUPLE (0x01) indicates
; that it is required to return the inserted tuple back:
; Flag BOX_ADD (0x02) requests that no tuple with the same primary
; key exists in the space. I.e. it turns INSERT into INSERT,
; without this flag INSERT behaves like REPLACE: replaces
; an existing tuple if it is found.
; Flag BOX_REPLACE (0x04) requests that a tuple with the same
; primary key is present in the space.

<flags> ::= <int32>

;
; A tuple may already exist. In that case INSERT
; returns 0 for tuple count in response. If BOX_RETURN_TUPLE
; is set, the inserted tuple will be sent back:

<insert_response_body> ::= <count> | <count><fq_tuple>

; <update> request, <type> = 19 is similar to <insert>:
; - <space_no>: same as in <select> or <insert>
; - <flags>, <tuple>: same as in <insert>
; Index number for tuple lookup does not need to be provided,
; since only primary key updates are allowed.
; - <count> specifies possibly zero operation count
;

<update_request_body> ::= <space_no><flags><tuple><count><operation>+

;
; Operations are optional and exist solely to allow
; updates of individual fields.
;

<operation> ::= <field_no><op_code><op_arg>

;
; Field index, specifies argument(s) of the operation
;

<field_no> ::= <int32>

;
; The operation(s) below operate on fields of arbitrary types:
; 0 - assign operation argument to field <field_no>;
;     will extend the tuple if <field_no> == <max_field_no> + 1
;
; The following operation(s) are only defined for integer
; types (32 and 64 bit):
; 1 - add argument to field <field_no>, both arguments
; are treated as signed 32 or 64 -bit ints
; 2 - bitwise AND of argument and field <field_no>
; 3 - bitwise XOR of argument and field <field_no>
; 4 - bitwise OR of argument and field <field_no>
; For arithmetic operations, size of the argument must be
; less or equal to the size of the field: it's possible
; to add 32-bit ints to 32- and 64- bit fields, but
; 64-bit ints can be added only to 64-bit fields.
; Tarantool 1.3.5 features one more command, which operates
; on strings:
; 5 - implementation of Perl 'splice' command
;
; The operation(s) below operate on fields of arbitrary types:
; 6 - delete <field_no>
; 7 - insert before <field_no>

<op_code> ::= <int8> # 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7

;
; It's an error to specify an argument of a type that
; differs from expected type.
;
<op_arg> ::= <field>

; For simple operations <op_arg> field contains either a string
; to assign, a number to add or subtract.
; When <op_code> is splice, <field> has to carry not one argument,
; but 3: offset in the target field, number of bytes to remove,
; string argument to inject. Since <op_arg> is always a <field>,
; field data in case of splice argument contains 3 nested <field>
; objects, which store the arguments:

<splice_field_data> ::= <offset><length><string>

<offset> ::= <field>
<length> ::= <field>
<string> ::= <field>

;

<update_response_body> ::= <insert_response_body>

;
; <delete>, request <type> = 21
; Similarly to updates, <delete> always uses the
; primary key.
;

<delete_request_body> ::= <space_no><flags><tuple>

;
; <delete> returns the number of deleted tuples.
; Currently it's always either 0 or 1.
; If BOX_RETURN_TUPLE is specified, and there is an old
; tuple, (count > 0), DELETE returns the deleted tuple.
;

<delete_response_body> ::= <count> | <count><fq_tuple>

;
; CALL request body contains <flags>, <proc_name>
; the number of procedure args, and the arguments themselves,
; which are passed into the procedure as Lua strings.
;
<call_request_body> ::= <flags><proc_name><tuple>

;
; <proc_name> is a valid Lua identifier, something like
; 'type', or 'box.process'.
;

<proc_name> ::= <field>

;
; In case of an error, <call_response_body> always contains
; <return_code>. If it's not 0, it is followed by an
; error message. Otherwise, the response, just like in case of
; SELECT, is a sequence of <fq_tuple>s.
<call_response_body> ::= <select_response_body>

;
; The server response, in addition to response header and body,
; contains a return code. It's a 4-byte integer, which has
; a lower 1-byte completion status part, and a higher 3-byte
; error code part.
;

<return_code> ::= <int32>

; The completion status is complementary:
; it can be deduced from the error code. There are only
; 3 completion status codes in use:
; 0  - success; The only possible error code with this status is
       0, ER_OK
; 1  - try again; An indicator of an intermittent error.
;      Usually is returned when two clients attempt to change
;      the same tuple simultaneously.
;      (<update> is not always done atomically)
; 2  - error
;
; The error code holds the actual error. Existing error codes include:
;
;  Completion status 0 (success)
;  -----------------------------
;  0x00000000 -- ER_OK
;
;  Completion status 1 (try again)
;  -------------------------------
;  0x00000401 -- ER_TUPLE_IS_RO
;                The requested data is blocked from modification
;
;  0x00000601 -- ER_TUPLE_IS_LOCKED
;                The requested data is not available
;
;  0x00000701 -- ER_MEMORY_ISSUE
;                An error occurred when allocating memory
;
;  Completion status 2 (error)
;  ---------------------------
;
;  0x00000102 -- ER_NONMASTER
;                An attempt was made to change data on a read-only port
;
;  0x00000202 -- ER_ILLEGAL_PARAMS
;                Malformed query
;
;  0x00000a02 -- ER_UNSUPPORTED_COMMAND
;                The query is not recognized
;
;  0x00001e02 -- ER_WRONG_FIELD
;                An unknown field was requested
;
;  0x00001f02 -- ER_WRONG_NUMBER
;                An out-of-range numeric value was included in the query
;
;  0x00002002 -- ER_DUPLICATE
;                An attempt was made to create an object with an existing key.
;
;  0x00002602 -- ER_WRONG_VERSION
;                The protocol version is not supported
;
;  0x00002702 -- ER_WAL_IO
;                WAL I/O error
;
; Convenience macros which define hexadecimal constants for
; <int32> return codes (completion status + code) can be found
; in include/iproto.h.
;
; vim: syntax=bnf
