mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-22 14:22:23 +00:00
844 lines
41 KiB
Protocol Buffer
844 lines
41 KiB
Protocol Buffer
////////////////////////////////////////////////////////////////////////////////
|
|
// THE HIGH-LEVEL VIEW //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Process: When you first open a connection, send the magic number
|
|
// for the version of the protobuf you're targeting (in the [Version]
|
|
// enum). This should **NOT** be sent as a protobuf; just send the
|
|
// little-endian 32-bit integer over the wire raw. This number should
|
|
// only be sent once per connection.
|
|
|
|
// The magic number shall be followed by an authorization key. The
|
|
// first 4 bytes are the length of the key to be sent as a little-endian
|
|
// 32-bit integer, followed by the key string. Even if there is no key,
|
|
// an empty string should be sent (length 0 and no data).
|
|
|
|
// Following the authorization key, the client shall send a magic number
|
|
// for the communication protocol they want to use (in the [Protocol]
|
|
// enum). This shall be a little-endian 32-bit integer.
|
|
|
|
// The server will then respond with a NULL-terminated string response.
|
|
// "SUCCESS" indicates that the connection has been accepted. Any other
|
|
// response indicates an error, and the response string should describe
|
|
// the error.
|
|
|
|
// Next, for each query you want to send, construct a [Query] protobuf
|
|
// and serialize it to a binary blob. Send the blob's size to the
|
|
// server encoded as a little-endian 32-bit integer, followed by the
|
|
// blob itself. You will recieve a [Response] protobuf back preceded
|
|
// by its own size, once again encoded as a little-endian 32-bit
|
|
// integer. You can see an example exchange below in **EXAMPLE**.
|
|
|
|
// A query consists of a [Term] to evaluate and a unique-per-connection
|
|
// [token].
|
|
|
|
// Tokens are used for two things:
|
|
// * Keeping track of which responses correspond to which queries.
|
|
// * Batched queries. Some queries return lots of results, so we send back
|
|
// batches of <1000, and you need to send a [CONTINUE] query with the same
|
|
// token to get more results from the original query.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
message VersionDummy { // We need to wrap it like this for some
|
|
// non-conforming protobuf libraries
|
|
// This enum contains the magic numbers for your version. See **THE HIGH-LEVEL
|
|
// VIEW** for what to do with it.
|
|
enum Version {
|
|
V0_1 = 0x3f61ba36;
|
|
V0_2 = 0x723081e1; // Authorization key during handshake
|
|
V0_3 = 0x5f75e83e; // Authorization key and protocol during handshake
|
|
V0_4 = 0x400c2d20; // Queries execute in parallel
|
|
V1_0 = 0x34c2bdc3; // Users and permissions
|
|
}
|
|
|
|
// The protocol to use after the handshake, specified in V0_3
|
|
enum Protocol {
|
|
PROTOBUF = 0x271ffc41;
|
|
JSON = 0x7e6970c7;
|
|
}
|
|
}
|
|
|
|
// You send one of:
|
|
// * A [START] query with a [Term] to evaluate and a unique-per-connection token.
|
|
// * A [CONTINUE] query with the same token as a [START] query that returned
|
|
// [SUCCESS_PARTIAL] in its [Response].
|
|
// * A [STOP] query with the same token as a [START] query that you want to stop.
|
|
// * A [NOREPLY_WAIT] query with a unique per-connection token. The server answers
|
|
// with a [WAIT_COMPLETE] [Response].
|
|
// * A [SERVER_INFO] query. The server answers with a [SERVER_INFO] [Response].
|
|
message Query {
|
|
enum QueryType {
|
|
START = 1; // Start a new query.
|
|
CONTINUE = 2; // Continue a query that returned [SUCCESS_PARTIAL]
|
|
// (see [Response]).
|
|
STOP = 3; // Stop a query partway through executing.
|
|
NOREPLY_WAIT = 4; // Wait for noreply operations to finish.
|
|
SERVER_INFO = 5; // Get server information.
|
|
}
|
|
optional QueryType type = 1;
|
|
// A [Term] is how we represent the operations we want a query to perform.
|
|
optional Term query = 2; // only present when [type] = [START]
|
|
optional int64 token = 3;
|
|
// This flag is ignored on the server. `noreply` should be added
|
|
// to `global_optargs` instead (the key "noreply" should map to
|
|
// either true or false).
|
|
optional bool OBSOLETE_noreply = 4 [default = false];
|
|
|
|
// If this is set to [true], then [Datum] values will sometimes be
|
|
// of [DatumType] [R_JSON] (see below). This can provide enormous
|
|
// speedups in languages with poor protobuf libraries.
|
|
optional bool accepts_r_json = 5 [default = false];
|
|
|
|
message AssocPair {
|
|
optional string key = 1;
|
|
optional Term val = 2;
|
|
}
|
|
repeated AssocPair global_optargs = 6;
|
|
}
|
|
|
|
// A backtrace frame (see `backtrace` in Response below)
|
|
message Frame {
|
|
enum FrameType {
|
|
POS = 1; // Error occurred in a positional argument.
|
|
OPT = 2; // Error occurred in an optional argument.
|
|
}
|
|
optional FrameType type = 1;
|
|
optional int64 pos = 2; // The index of the positional argument.
|
|
optional string opt = 3; // The name of the optional argument.
|
|
}
|
|
message Backtrace {
|
|
repeated Frame frames = 1;
|
|
}
|
|
|
|
// You get back a response with the same [token] as your query.
|
|
message Response {
|
|
enum ResponseType {
|
|
// These response types indicate success.
|
|
SUCCESS_ATOM = 1; // Query returned a single RQL datatype.
|
|
SUCCESS_SEQUENCE = 2; // Query returned a sequence of RQL datatypes.
|
|
SUCCESS_PARTIAL = 3; // Query returned a partial sequence of RQL
|
|
// datatypes. If you send a [CONTINUE] query with
|
|
// the same token as this response, you will get
|
|
// more of the sequence. Keep sending [CONTINUE]
|
|
// queries until you get back [SUCCESS_SEQUENCE].
|
|
WAIT_COMPLETE = 4; // A [NOREPLY_WAIT] query completed.
|
|
SERVER_INFO = 5; // The data for a [SERVER_INFO] request. This is
|
|
// the same as `SUCCESS_ATOM` except that there will
|
|
// never be profiling data.
|
|
|
|
// These response types indicate failure.
|
|
CLIENT_ERROR = 16; // Means the client is buggy. An example is if the
|
|
// client sends a malformed protobuf, or tries to
|
|
// send [CONTINUE] for an unknown token.
|
|
COMPILE_ERROR = 17; // Means the query failed during parsing or type
|
|
// checking. For example, if you pass too many
|
|
// arguments to a function.
|
|
RUNTIME_ERROR = 18; // Means the query failed at runtime. An example is
|
|
// if you add together two values from a table, but
|
|
// they turn out at runtime to be booleans rather
|
|
// than numbers.
|
|
}
|
|
optional ResponseType type = 1;
|
|
|
|
// If `ResponseType` is `RUNTIME_ERROR`, this may be filled in with more
|
|
// information about the error.
|
|
enum ErrorType {
|
|
INTERNAL = 1000000;
|
|
RESOURCE_LIMIT = 2000000;
|
|
QUERY_LOGIC = 3000000;
|
|
NON_EXISTENCE = 3100000;
|
|
OP_FAILED = 4100000;
|
|
OP_INDETERMINATE = 4200000;
|
|
USER = 5000000;
|
|
PERMISSION_ERROR = 6000000;
|
|
}
|
|
optional ErrorType error_type = 7;
|
|
|
|
// ResponseNotes are used to provide information about the query
|
|
// response that may be useful for people writing drivers or ORMs.
|
|
// Currently all the notes we send indicate that a stream has certain
|
|
// special properties.
|
|
enum ResponseNote {
|
|
// The stream is a changefeed stream (e.g. `r.table('test').changes()`).
|
|
SEQUENCE_FEED = 1;
|
|
// The stream is a point changefeed stream
|
|
// (e.g. `r.table('test').get(0).changes()`).
|
|
ATOM_FEED = 2;
|
|
// The stream is an order_by_limit changefeed stream
|
|
// (e.g. `r.table('test').order_by(index: 'id').limit(5).changes()`).
|
|
ORDER_BY_LIMIT_FEED = 3;
|
|
// The stream is a union of multiple changefeed types that can't be
|
|
// collapsed to a single type
|
|
// (e.g. `r.table('test').changes().union(r.table('test').get(0).changes())`).
|
|
UNIONED_FEED = 4;
|
|
// The stream is a changefeed stream and includes notes on what state
|
|
// the changefeed stream is in (e.g. objects of the form `{state:
|
|
// 'initializing'}`).
|
|
INCLUDES_STATES = 5;
|
|
}
|
|
repeated ResponseNote notes = 6;
|
|
|
|
optional int64 token = 2; // Indicates what [Query] this response corresponds to.
|
|
|
|
// [response] contains 1 RQL datum if [type] is [SUCCESS_ATOM] or
|
|
// [SERVER_INFO]. [response] contains many RQL data if [type] is
|
|
// [SUCCESS_SEQUENCE] or [SUCCESS_PARTIAL]. [response] contains 1
|
|
// error message (of type [R_STR]) in all other cases.
|
|
repeated Datum response = 3;
|
|
|
|
// If [type] is [CLIENT_ERROR], [TYPE_ERROR], or [RUNTIME_ERROR], then a
|
|
// backtrace will be provided. The backtrace says where in the query the
|
|
// error occurred. Ideally this information will be presented to the user as
|
|
// a pretty-printed version of their query with the erroneous section
|
|
// underlined. A backtrace is a series of 0 or more [Frame]s, each of which
|
|
// specifies either the index of a positional argument or the name of an
|
|
// optional argument. (Those words will make more sense if you look at the
|
|
// [Term] message below.)
|
|
optional Backtrace backtrace = 4; // Contains n [Frame]s when you get back an error.
|
|
|
|
// If the [global_optargs] in the [Query] that this [Response] is a
|
|
// response to contains a key "profile" which maps to a static value of
|
|
// true then [profile] will contain a [Datum] which provides profiling
|
|
// information about the execution of the query. This field should be
|
|
// returned to the user along with the result that would normally be
|
|
// returned (a datum or a cursor). In official drivers this is accomplished
|
|
// by putting them inside of an object with "value" mapping to the return
|
|
// value and "profile" mapping to the profile object.
|
|
optional Datum profile = 5;
|
|
}
|
|
|
|
// A [Datum] is a chunk of data that can be serialized to disk or returned to
|
|
// the user in a Response. Currently we only support JSON types, but we may
|
|
// support other types in the future (e.g., a date type or an integer type).
|
|
message Datum {
|
|
enum DatumType {
|
|
R_NULL = 1;
|
|
R_BOOL = 2;
|
|
R_NUM = 3; // a double
|
|
R_STR = 4;
|
|
R_ARRAY = 5;
|
|
R_OBJECT = 6;
|
|
// This [DatumType] will only be used if [accepts_r_json] is
|
|
// set to [true] in [Query]. [r_str] will be filled with a
|
|
// JSON encoding of the [Datum].
|
|
R_JSON = 7; // uses r_str
|
|
}
|
|
optional DatumType type = 1;
|
|
optional bool r_bool = 2;
|
|
optional double r_num = 3;
|
|
optional string r_str = 4;
|
|
|
|
repeated Datum r_array = 5;
|
|
message AssocPair {
|
|
optional string key = 1;
|
|
optional Datum val = 2;
|
|
}
|
|
repeated AssocPair r_object = 6;
|
|
}
|
|
|
|
// A [Term] is either a piece of data (see **Datum** above), or an operator and
|
|
// its operands. If you have a [Datum], it's stored in the member [datum]. If
|
|
// you have an operator, its positional arguments are stored in [args] and its
|
|
// optional arguments are stored in [optargs].
|
|
//
|
|
// A note about type signatures:
|
|
// We use the following notation to denote types:
|
|
// arg1_type, arg2_type, argrest_type... -> result_type
|
|
// So, for example, if we have a function `avg` that takes any number of
|
|
// arguments and averages them, we might write:
|
|
// NUMBER... -> NUMBER
|
|
// Or if we had a function that took one number modulo another:
|
|
// NUMBER, NUMBER -> NUMBER
|
|
// Or a function that takes a table and a primary key of any Datum type, then
|
|
// retrieves the entry with that primary key:
|
|
// Table, DATUM -> OBJECT
|
|
// Some arguments must be provided as literal values (and not the results of sub
|
|
// terms). These are marked with a `!`.
|
|
// Optional arguments are specified within curly braces as argname `:` value
|
|
// type (e.x `{noreply:BOOL}`)
|
|
// Many RQL operations are polymorphic. For these, alterantive type signatures
|
|
// are separated by `|`.
|
|
//
|
|
// The RQL type hierarchy is as follows:
|
|
// Top
|
|
// DATUM
|
|
// NULL
|
|
// BOOL
|
|
// NUMBER
|
|
// STRING
|
|
// OBJECT
|
|
// SingleSelection
|
|
// ARRAY
|
|
// Sequence
|
|
// ARRAY
|
|
// Stream
|
|
// StreamSelection
|
|
// Table
|
|
// Database
|
|
// Function
|
|
// Ordering - used only by ORDER_BY
|
|
// Pathspec -- an object, string, or array that specifies a path
|
|
// Error
|
|
message Term {
|
|
enum TermType {
|
|
// A RQL datum, stored in `datum` below.
|
|
DATUM = 1;
|
|
|
|
MAKE_ARRAY = 2; // DATUM... -> ARRAY
|
|
// Evaluate the terms in [optargs] and make an object
|
|
MAKE_OBJ = 3; // {...} -> OBJECT
|
|
|
|
// * Compound types
|
|
|
|
// Takes an integer representing a variable and returns the value stored
|
|
// in that variable. It's the responsibility of the client to translate
|
|
// from their local representation of a variable to a unique _non-negative_
|
|
// integer for that variable. (We do it this way instead of letting
|
|
// clients provide variable names as strings to discourage
|
|
// variable-capturing client libraries, and because it's more efficient
|
|
// on the wire.)
|
|
VAR = 10; // !NUMBER -> DATUM
|
|
// Takes some javascript code and executes it.
|
|
JAVASCRIPT = 11; // STRING {timeout: !NUMBER} -> DATUM |
|
|
// STRING {timeout: !NUMBER} -> Function(*)
|
|
UUID = 169; // () -> DATUM
|
|
|
|
// Takes an HTTP URL and gets it. If the get succeeds and
|
|
// returns valid JSON, it is converted into a DATUM
|
|
HTTP = 153; // STRING {data: OBJECT | STRING,
|
|
// timeout: !NUMBER,
|
|
// method: STRING,
|
|
// params: OBJECT,
|
|
// header: OBJECT | ARRAY,
|
|
// attempts: NUMBER,
|
|
// redirects: NUMBER,
|
|
// verify: BOOL,
|
|
// page: FUNC | STRING,
|
|
// page_limit: NUMBER,
|
|
// auth: OBJECT,
|
|
// result_format: STRING,
|
|
// } -> STRING | STREAM
|
|
|
|
// Takes a string and throws an error with that message.
|
|
// Inside of a `default` block, you can omit the first
|
|
// argument to rethrow whatever error you catch (this is most
|
|
// useful as an argument to the `default` filter optarg).
|
|
ERROR = 12; // STRING -> Error | -> Error
|
|
// Takes nothing and returns a reference to the implicit variable.
|
|
IMPLICIT_VAR = 13; // -> DATUM
|
|
|
|
// * Data Operators
|
|
// Returns a reference to a database.
|
|
DB = 14; // STRING -> Database
|
|
// Returns a reference to a table.
|
|
TABLE = 15; // Database, STRING, {read_mode:STRING, identifier_format:STRING} -> Table
|
|
// STRING, {read_mode:STRING, identifier_format:STRING} -> Table
|
|
// Gets a single element from a table by its primary or a secondary key.
|
|
GET = 16; // Table, STRING -> SingleSelection | Table, NUMBER -> SingleSelection |
|
|
// Table, STRING -> NULL | Table, NUMBER -> NULL |
|
|
GET_ALL = 78; // Table, DATUM..., {index:!STRING} => ARRAY
|
|
|
|
// Simple DATUM Ops
|
|
EQ = 17; // DATUM... -> BOOL
|
|
NE = 18; // DATUM... -> BOOL
|
|
LT = 19; // DATUM... -> BOOL
|
|
LE = 20; // DATUM... -> BOOL
|
|
GT = 21; // DATUM... -> BOOL
|
|
GE = 22; // DATUM... -> BOOL
|
|
NOT = 23; // BOOL -> BOOL
|
|
// ADD can either add two numbers or concatenate two arrays.
|
|
ADD = 24; // NUMBER... -> NUMBER | STRING... -> STRING
|
|
SUB = 25; // NUMBER... -> NUMBER
|
|
MUL = 26; // NUMBER... -> NUMBER
|
|
DIV = 27; // NUMBER... -> NUMBER
|
|
MOD = 28; // NUMBER, NUMBER -> NUMBER
|
|
|
|
FLOOR = 183; // NUMBER -> NUMBER
|
|
CEIL = 184; // NUMBER -> NUMBER
|
|
ROUND = 185; // NUMBER -> NUMBER
|
|
|
|
// DATUM Array Ops
|
|
// Append a single element to the end of an array (like `snoc`).
|
|
APPEND = 29; // ARRAY, DATUM -> ARRAY
|
|
// Prepend a single element to the end of an array (like `cons`).
|
|
PREPEND = 80; // ARRAY, DATUM -> ARRAY
|
|
//Remove the elements of one array from another array.
|
|
DIFFERENCE = 95; // ARRAY, ARRAY -> ARRAY
|
|
|
|
// DATUM Set Ops
|
|
// Set ops work on arrays. They don't use actual sets and thus have
|
|
// performance characteristics you would expect from arrays rather than
|
|
// from sets. All set operations have the post condition that they
|
|
// array they return contains no duplicate values.
|
|
SET_INSERT = 88; // ARRAY, DATUM -> ARRAY
|
|
SET_INTERSECTION = 89; // ARRAY, ARRAY -> ARRAY
|
|
SET_UNION = 90; // ARRAY, ARRAY -> ARRAY
|
|
SET_DIFFERENCE = 91; // ARRAY, ARRAY -> ARRAY
|
|
|
|
SLICE = 30; // Sequence, NUMBER, NUMBER -> Sequence
|
|
SKIP = 70; // Sequence, NUMBER -> Sequence
|
|
LIMIT = 71; // Sequence, NUMBER -> Sequence
|
|
OFFSETS_OF = 87; // Sequence, DATUM -> Sequence | Sequence, Function(1) -> Sequence
|
|
CONTAINS = 93; // Sequence, (DATUM | Function(1))... -> BOOL
|
|
|
|
// Stream/Object Ops
|
|
// Get a particular field from an object, or map that over a
|
|
// sequence.
|
|
GET_FIELD = 31; // OBJECT, STRING -> DATUM
|
|
// | Sequence, STRING -> Sequence
|
|
// Return an array containing the keys of the object.
|
|
KEYS = 94; // OBJECT -> ARRAY
|
|
// Return an array containing the values of the object.
|
|
VALUES = 186; // OBJECT -> ARRAY
|
|
// Creates an object
|
|
OBJECT = 143; // STRING, DATUM, ... -> OBJECT
|
|
// Check whether an object contains all the specified fields,
|
|
// or filters a sequence so that all objects inside of it
|
|
// contain all the specified fields.
|
|
HAS_FIELDS = 32; // OBJECT, Pathspec... -> BOOL
|
|
// x.with_fields(...) <=> x.has_fields(...).pluck(...)
|
|
WITH_FIELDS = 96; // Sequence, Pathspec... -> Sequence
|
|
// Get a subset of an object by selecting some attributes to preserve,
|
|
// or map that over a sequence. (Both pick and pluck, polymorphic.)
|
|
PLUCK = 33; // Sequence, Pathspec... -> Sequence | OBJECT, Pathspec... -> OBJECT
|
|
// Get a subset of an object by selecting some attributes to discard, or
|
|
// map that over a sequence. (Both unpick and without, polymorphic.)
|
|
WITHOUT = 34; // Sequence, Pathspec... -> Sequence | OBJECT, Pathspec... -> OBJECT
|
|
// Merge objects (right-preferential)
|
|
MERGE = 35; // OBJECT... -> OBJECT | Sequence -> Sequence
|
|
|
|
// Sequence Ops
|
|
// Get all elements of a sequence between two values.
|
|
// Half-open by default, but the openness of either side can be
|
|
// changed by passing 'closed' or 'open for `right_bound` or
|
|
// `left_bound`.
|
|
BETWEEN_DEPRECATED = 36; // Deprecated version of between, which allows `null` to specify unboundedness
|
|
// With the newer version, clients should use `r.minval` and `r.maxval` for unboundedness
|
|
BETWEEN = 182; // StreamSelection, DATUM, DATUM, {index:!STRING, right_bound:STRING, left_bound:STRING} -> StreamSelection
|
|
REDUCE = 37; // Sequence, Function(2) -> DATUM
|
|
MAP = 38; // Sequence, Function(1) -> Sequence
|
|
// The arity of the function should be
|
|
// Sequence..., Function(sizeof...(Sequence)) -> Sequence
|
|
|
|
FOLD = 187; // Sequence, Datum, Function(2), {Function(3), Function(1)
|
|
|
|
// Filter a sequence with either a function or a shortcut
|
|
// object (see API docs for details). The body of FILTER is
|
|
// wrapped in an implicit `.default(false)`, and you can
|
|
// change the default value by specifying the `default`
|
|
// optarg. If you make the default `r.error`, all errors
|
|
// caught by `default` will be rethrown as if the `default`
|
|
// did not exist.
|
|
FILTER = 39; // Sequence, Function(1), {default:DATUM} -> Sequence |
|
|
// Sequence, OBJECT, {default:DATUM} -> Sequence
|
|
// Map a function over a sequence and then concatenate the results together.
|
|
CONCAT_MAP = 40; // Sequence, Function(1) -> Sequence
|
|
// Order a sequence based on one or more attributes.
|
|
ORDER_BY = 41; // Sequence, (!STRING | Ordering)..., {index: (!STRING | Ordering)} -> Sequence
|
|
// Get all distinct elements of a sequence (like `uniq`).
|
|
DISTINCT = 42; // Sequence -> Sequence
|
|
// Count the number of elements in a sequence, or only the elements that match
|
|
// a given filter.
|
|
COUNT = 43; // Sequence -> NUMBER | Sequence, DATUM -> NUMBER | Sequence, Function(1) -> NUMBER
|
|
IS_EMPTY = 86; // Sequence -> BOOL
|
|
// Take the union of multiple sequences (preserves duplicate elements! (use distinct)).
|
|
UNION = 44; // Sequence... -> Sequence
|
|
// Get the Nth element of a sequence.
|
|
NTH = 45; // Sequence, NUMBER -> DATUM
|
|
// do NTH or GET_FIELD depending on target object
|
|
BRACKET = 170; // Sequence | OBJECT, NUMBER | STRING -> DATUM
|
|
// OBSOLETE_GROUPED_MAPREDUCE = 46;
|
|
// OBSOLETE_GROUPBY = 47;
|
|
|
|
INNER_JOIN = 48; // Sequence, Sequence, Function(2) -> Sequence
|
|
OUTER_JOIN = 49; // Sequence, Sequence, Function(2) -> Sequence
|
|
// An inner-join that does an equality comparison on two attributes.
|
|
EQ_JOIN = 50; // Sequence, !STRING, Sequence, {index:!STRING} -> Sequence
|
|
ZIP = 72; // Sequence -> Sequence
|
|
RANGE = 173; // -> Sequence [0, +inf)
|
|
// NUMBER -> Sequence [0, a)
|
|
// NUMBER, NUMBER -> Sequence [a, b)
|
|
|
|
// Array Ops
|
|
// Insert an element in to an array at a given index.
|
|
INSERT_AT = 82; // ARRAY, NUMBER, DATUM -> ARRAY
|
|
// Remove an element at a given index from an array.
|
|
DELETE_AT = 83; // ARRAY, NUMBER -> ARRAY |
|
|
// ARRAY, NUMBER, NUMBER -> ARRAY
|
|
// Change the element at a given index of an array.
|
|
CHANGE_AT = 84; // ARRAY, NUMBER, DATUM -> ARRAY
|
|
// Splice one array in to another array.
|
|
SPLICE_AT = 85; // ARRAY, NUMBER, ARRAY -> ARRAY
|
|
|
|
// * Type Ops
|
|
// Coerces a datum to a named type (e.g. "bool").
|
|
// If you previously used `stream_to_array`, you should use this instead
|
|
// with the type "array".
|
|
COERCE_TO = 51; // Top, STRING -> Top
|
|
// Returns the named type of a datum (e.g. TYPE_OF(true) = "BOOL")
|
|
TYPE_OF = 52; // Top -> STRING
|
|
|
|
// * Write Ops (the OBJECTs contain data about number of errors etc.)
|
|
// Updates all the rows in a selection. Calls its Function with the row
|
|
// to be updated, and then merges the result of that call.
|
|
UPDATE = 53; // StreamSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT |
|
|
// SingleSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT |
|
|
// StreamSelection, OBJECT, {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT |
|
|
// SingleSelection, OBJECT, {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT
|
|
// Deletes all the rows in a selection.
|
|
DELETE = 54; // StreamSelection, {durability:STRING, return_changes:BOOL} -> OBJECT | SingleSelection -> OBJECT
|
|
// Replaces all the rows in a selection. Calls its Function with the row
|
|
// to be replaced, and then discards it and stores the result of that
|
|
// call.
|
|
REPLACE = 55; // StreamSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT | SingleSelection, Function(1), {non_atomic:BOOL, durability:STRING, return_changes:BOOL} -> OBJECT
|
|
// Inserts into a table. If `conflict` is replace, overwrites
|
|
// entries with the same primary key. If `conflict` is
|
|
// update, does an update on the entry. If `conflict` is
|
|
// error, or is omitted, conflicts will trigger an error.
|
|
INSERT = 56; // Table, OBJECT, {conflict:STRING, durability:STRING, return_changes:BOOL} -> OBJECT | Table, Sequence, {conflict:STRING, durability:STRING, return_changes:BOOL} -> OBJECT
|
|
|
|
// * Administrative OPs
|
|
// Creates a database with a particular name.
|
|
DB_CREATE = 57; // STRING -> OBJECT
|
|
// Drops a database with a particular name.
|
|
DB_DROP = 58; // STRING -> OBJECT
|
|
// Lists all the databases by name. (Takes no arguments)
|
|
DB_LIST = 59; // -> ARRAY
|
|
// Creates a table with a particular name in a particular
|
|
// database. (You may omit the first argument to use the
|
|
// default database.)
|
|
TABLE_CREATE = 60; // Database, STRING, {primary_key:STRING, shards:NUMBER, replicas:NUMBER, primary_replica_tag:STRING} -> OBJECT
|
|
// Database, STRING, {primary_key:STRING, shards:NUMBER, replicas:OBJECT, primary_replica_tag:STRING} -> OBJECT
|
|
// STRING, {primary_key:STRING, shards:NUMBER, replicas:NUMBER, primary_replica_tag:STRING} -> OBJECT
|
|
// STRING, {primary_key:STRING, shards:NUMBER, replicas:OBJECT, primary_replica_tag:STRING} -> OBJECT
|
|
// Drops a table with a particular name from a particular
|
|
// database. (You may omit the first argument to use the
|
|
// default database.)
|
|
TABLE_DROP = 61; // Database, STRING -> OBJECT
|
|
// STRING -> OBJECT
|
|
// Lists all the tables in a particular database. (You may
|
|
// omit the first argument to use the default database.)
|
|
TABLE_LIST = 62; // Database -> ARRAY
|
|
// -> ARRAY
|
|
// Returns the row in the `rethinkdb.table_config` or `rethinkdb.db_config` table
|
|
// that corresponds to the given database or table.
|
|
CONFIG = 174; // Database -> SingleSelection
|
|
// Table -> SingleSelection
|
|
// Returns the row in the `rethinkdb.table_status` table that corresponds to the
|
|
// given table.
|
|
STATUS = 175; // Table -> SingleSelection
|
|
// Called on a table, waits for that table to be ready for read/write operations.
|
|
// Called on a database, waits for all of the tables in the database to be ready.
|
|
// Returns the corresponding row or rows from the `rethinkdb.table_status` table.
|
|
WAIT = 177; // Table -> OBJECT
|
|
// Database -> OBJECT
|
|
// Generates a new config for the given table, or all tables in the given database
|
|
// The `shards` and `replicas` arguments are required. If `emergency_repair` is
|
|
// specified, it will enter a completely different mode of repairing a table
|
|
// which has lost half or more of its replicas.
|
|
RECONFIGURE = 176; // Database|Table, {shards:NUMBER, replicas:NUMBER [,
|
|
// dry_run:BOOLEAN]
|
|
// } -> OBJECT
|
|
// Database|Table, {shards:NUMBER, replicas:OBJECT [,
|
|
// primary_replica_tag:STRING,
|
|
// nonvoting_replica_tags:ARRAY,
|
|
// dry_run:BOOLEAN]
|
|
// } -> OBJECT
|
|
// Table, {emergency_repair:STRING, dry_run:BOOLEAN} -> OBJECT
|
|
// Balances the table's shards but leaves everything else the same. Can also be
|
|
// applied to an entire database at once.
|
|
REBALANCE = 179; // Table -> OBJECT
|
|
// Database -> OBJECT
|
|
|
|
// Ensures that previously issued soft-durability writes are complete and
|
|
// written to disk.
|
|
SYNC = 138; // Table -> OBJECT
|
|
|
|
// Set global, database, or table-specific permissions
|
|
GRANT = 188; // -> OBJECT
|
|
// Database -> OBJECT
|
|
// Table -> OBJECT
|
|
|
|
// * Secondary indexes OPs
|
|
// Creates a new secondary index with a particular name and definition.
|
|
INDEX_CREATE = 75; // Table, STRING, Function(1), {multi:BOOL} -> OBJECT
|
|
// Drops a secondary index with a particular name from the specified table.
|
|
INDEX_DROP = 76; // Table, STRING -> OBJECT
|
|
// Lists all secondary indexes on a particular table.
|
|
INDEX_LIST = 77; // Table -> ARRAY
|
|
// Gets information about whether or not a set of indexes are ready to
|
|
// be accessed. Returns a list of objects that look like this:
|
|
// {index:STRING, ready:BOOL[, progress:NUMBER]}
|
|
INDEX_STATUS = 139; // Table, STRING... -> ARRAY
|
|
// Blocks until a set of indexes are ready to be accessed. Returns the
|
|
// same values INDEX_STATUS.
|
|
INDEX_WAIT = 140; // Table, STRING... -> ARRAY
|
|
// Renames the given index to a new name
|
|
INDEX_RENAME = 156; // Table, STRING, STRING, {overwrite:BOOL} -> OBJECT
|
|
|
|
// * Control Operators
|
|
// Calls a function on data
|
|
FUNCALL = 64; // Function(*), DATUM... -> DATUM
|
|
// Executes its first argument, and returns its second argument if it
|
|
// got [true] or its third argument if it got [false] (like an `if`
|
|
// statement).
|
|
BRANCH = 65; // BOOL, Top, Top -> Top
|
|
// Returns true if any of its arguments returns true (short-circuits).
|
|
OR = 66; // BOOL... -> BOOL
|
|
// Returns true if all of its arguments return true (short-circuits).
|
|
AND = 67; // BOOL... -> BOOL
|
|
// Calls its Function with each entry in the sequence
|
|
// and executes the array of terms that Function returns.
|
|
FOR_EACH = 68; // Sequence, Function(1) -> OBJECT
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////// Special Terms
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// An anonymous function. Takes an array of numbers representing
|
|
// variables (see [VAR] above), and a [Term] to execute with those in
|
|
// scope. Returns a function that may be passed an array of arguments,
|
|
// then executes the Term with those bound to the variable names. The
|
|
// user will never construct this directly. We use it internally for
|
|
// things like `map` which take a function. The "arity" of a [Function] is
|
|
// the number of arguments it takes.
|
|
// For example, here's what `_X_.map{|x| x+2}` turns into:
|
|
// Term {
|
|
// type = MAP;
|
|
// args = [_X_,
|
|
// Term {
|
|
// type = Function;
|
|
// args = [Term {
|
|
// type = DATUM;
|
|
// datum = Datum {
|
|
// type = R_ARRAY;
|
|
// r_array = [Datum { type = R_NUM; r_num = 1; }];
|
|
// };
|
|
// },
|
|
// Term {
|
|
// type = ADD;
|
|
// args = [Term {
|
|
// type = VAR;
|
|
// args = [Term {
|
|
// type = DATUM;
|
|
// datum = Datum { type = R_NUM;
|
|
// r_num = 1};
|
|
// }];
|
|
// },
|
|
// Term {
|
|
// type = DATUM;
|
|
// datum = Datum { type = R_NUM; r_num = 2; };
|
|
// }];
|
|
// }];
|
|
// }];
|
|
FUNC = 69; // ARRAY, Top -> ARRAY -> Top
|
|
|
|
// Indicates to ORDER_BY that this attribute is to be sorted in ascending order.
|
|
ASC = 73; // !STRING -> Ordering
|
|
// Indicates to ORDER_BY that this attribute is to be sorted in descending order.
|
|
DESC = 74; // !STRING -> Ordering
|
|
|
|
// Gets info about anything. INFO is most commonly called on tables.
|
|
INFO = 79; // Top -> OBJECT
|
|
|
|
// `a.match(b)` returns a match object if the string `a`
|
|
// matches the regular expression `b`.
|
|
MATCH = 97; // STRING, STRING -> DATUM
|
|
|
|
// Change the case of a string.
|
|
UPCASE = 141; // STRING -> STRING
|
|
DOWNCASE = 142; // STRING -> STRING
|
|
|
|
// Select a number of elements from sequence with uniform distribution.
|
|
SAMPLE = 81; // Sequence, NUMBER -> Sequence
|
|
|
|
// Evaluates its first argument. If that argument returns
|
|
// NULL or throws an error related to the absence of an
|
|
// expected value (for instance, accessing a non-existent
|
|
// field or adding NULL to an integer), DEFAULT will either
|
|
// return its second argument or execute it if it's a
|
|
// function. If the second argument is a function, it will be
|
|
// passed either the text of the error or NULL as its
|
|
// argument.
|
|
DEFAULT = 92; // Top, Top -> Top
|
|
|
|
// Parses its first argument as a json string and returns it as a
|
|
// datum.
|
|
JSON = 98; // STRING -> DATUM
|
|
// Returns the datum as a JSON string.
|
|
// N.B.: we would really prefer this be named TO_JSON and that exists as
|
|
// an alias in Python and JavaScript drivers; however it conflicts with the
|
|
// standard `to_json` method defined by Ruby's standard json library.
|
|
TO_JSON_STRING = 172; // DATUM -> STRING
|
|
|
|
// Parses its first arguments as an ISO 8601 time and returns it as a
|
|
// datum.
|
|
ISO8601 = 99; // STRING -> PSEUDOTYPE(TIME)
|
|
// Prints a time as an ISO 8601 time.
|
|
TO_ISO8601 = 100; // PSEUDOTYPE(TIME) -> STRING
|
|
|
|
// Returns a time given seconds since epoch in UTC.
|
|
EPOCH_TIME = 101; // NUMBER -> PSEUDOTYPE(TIME)
|
|
// Returns seconds since epoch in UTC given a time.
|
|
TO_EPOCH_TIME = 102; // PSEUDOTYPE(TIME) -> NUMBER
|
|
|
|
// The time the query was received by the server.
|
|
NOW = 103; // -> PSEUDOTYPE(TIME)
|
|
// Puts a time into an ISO 8601 timezone.
|
|
IN_TIMEZONE = 104; // PSEUDOTYPE(TIME), STRING -> PSEUDOTYPE(TIME)
|
|
// a.during(b, c) returns whether a is in the range [b, c)
|
|
DURING = 105; // PSEUDOTYPE(TIME), PSEUDOTYPE(TIME), PSEUDOTYPE(TIME) -> BOOL
|
|
// Retrieves the date portion of a time.
|
|
DATE = 106; // PSEUDOTYPE(TIME) -> PSEUDOTYPE(TIME)
|
|
// x.time_of_day == x.date - x
|
|
TIME_OF_DAY = 126; // PSEUDOTYPE(TIME) -> NUMBER
|
|
// Returns the timezone of a time.
|
|
TIMEZONE = 127; // PSEUDOTYPE(TIME) -> STRING
|
|
|
|
// These access the various components of a time.
|
|
YEAR = 128; // PSEUDOTYPE(TIME) -> NUMBER
|
|
MONTH = 129; // PSEUDOTYPE(TIME) -> NUMBER
|
|
DAY = 130; // PSEUDOTYPE(TIME) -> NUMBER
|
|
DAY_OF_WEEK = 131; // PSEUDOTYPE(TIME) -> NUMBER
|
|
DAY_OF_YEAR = 132; // PSEUDOTYPE(TIME) -> NUMBER
|
|
HOURS = 133; // PSEUDOTYPE(TIME) -> NUMBER
|
|
MINUTES = 134; // PSEUDOTYPE(TIME) -> NUMBER
|
|
SECONDS = 135; // PSEUDOTYPE(TIME) -> NUMBER
|
|
|
|
// Construct a time from a date and optional timezone or a
|
|
// date+time and optional timezone.
|
|
TIME = 136; // NUMBER, NUMBER, NUMBER, STRING -> PSEUDOTYPE(TIME) |
|
|
// NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, NUMBER, STRING -> PSEUDOTYPE(TIME) |
|
|
|
|
// Constants for ISO 8601 days of the week.
|
|
MONDAY = 107; // -> 1
|
|
TUESDAY = 108; // -> 2
|
|
WEDNESDAY = 109; // -> 3
|
|
THURSDAY = 110; // -> 4
|
|
FRIDAY = 111; // -> 5
|
|
SATURDAY = 112; // -> 6
|
|
SUNDAY = 113; // -> 7
|
|
|
|
// Constants for ISO 8601 months.
|
|
JANUARY = 114; // -> 1
|
|
FEBRUARY = 115; // -> 2
|
|
MARCH = 116; // -> 3
|
|
APRIL = 117; // -> 4
|
|
MAY = 118; // -> 5
|
|
JUNE = 119; // -> 6
|
|
JULY = 120; // -> 7
|
|
AUGUST = 121; // -> 8
|
|
SEPTEMBER = 122; // -> 9
|
|
OCTOBER = 123; // -> 10
|
|
NOVEMBER = 124; // -> 11
|
|
DECEMBER = 125; // -> 12
|
|
|
|
// Indicates to MERGE to replace, or remove in case of an empty literal, the
|
|
// other object rather than merge it.
|
|
LITERAL = 137; // -> Merging
|
|
// JSON -> Merging
|
|
|
|
// SEQUENCE, STRING -> GROUPED_SEQUENCE | SEQUENCE, FUNCTION -> GROUPED_SEQUENCE
|
|
GROUP = 144;
|
|
SUM = 145;
|
|
AVG = 146;
|
|
MIN = 147;
|
|
MAX = 148;
|
|
|
|
// `str.split()` splits on whitespace
|
|
// `str.split(" ")` splits on spaces only
|
|
// `str.split(" ", 5)` splits on spaces with at most 5 results
|
|
// `str.split(nil, 5)` splits on whitespace with at most 5 results
|
|
SPLIT = 149; // STRING -> ARRAY | STRING, STRING -> ARRAY | STRING, STRING, NUMBER -> ARRAY | STRING, NULL, NUMBER -> ARRAY
|
|
|
|
UNGROUP = 150; // GROUPED_DATA -> ARRAY
|
|
|
|
// Takes a range of numbers and returns a random number within the range
|
|
RANDOM = 151; // NUMBER, NUMBER {float:BOOL} -> DATUM
|
|
|
|
CHANGES = 152; // TABLE -> STREAM
|
|
ARGS = 154; // ARRAY -> SPECIAL (used to splice arguments)
|
|
|
|
// BINARY is client-only at the moment, it is not supported on the server
|
|
BINARY = 155; // STRING -> PSEUDOTYPE(BINARY)
|
|
|
|
GEOJSON = 157; // OBJECT -> PSEUDOTYPE(GEOMETRY)
|
|
TO_GEOJSON = 158; // PSEUDOTYPE(GEOMETRY) -> OBJECT
|
|
POINT = 159; // NUMBER, NUMBER -> PSEUDOTYPE(GEOMETRY)
|
|
LINE = 160; // (ARRAY | PSEUDOTYPE(GEOMETRY))... -> PSEUDOTYPE(GEOMETRY)
|
|
POLYGON = 161; // (ARRAY | PSEUDOTYPE(GEOMETRY))... -> PSEUDOTYPE(GEOMETRY)
|
|
DISTANCE = 162; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) {geo_system:STRING, unit:STRING} -> NUMBER
|
|
INTERSECTS = 163; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) -> BOOL
|
|
INCLUDES = 164; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) -> BOOL
|
|
CIRCLE = 165; // PSEUDOTYPE(GEOMETRY), NUMBER {num_vertices:NUMBER, geo_system:STRING, unit:STRING, fill:BOOL} -> PSEUDOTYPE(GEOMETRY)
|
|
GET_INTERSECTING = 166; // TABLE, PSEUDOTYPE(GEOMETRY) {index:!STRING} -> StreamSelection
|
|
FILL = 167; // PSEUDOTYPE(GEOMETRY) -> PSEUDOTYPE(GEOMETRY)
|
|
GET_NEAREST = 168; // TABLE, PSEUDOTYPE(GEOMETRY) {index:!STRING, max_results:NUM, max_dist:NUM, geo_system:STRING, unit:STRING} -> ARRAY
|
|
POLYGON_SUB = 171; // PSEUDOTYPE(GEOMETRY), PSEUDOTYPE(GEOMETRY) -> PSEUDOTYPE(GEOMETRY)
|
|
|
|
// Constants for specifying key ranges
|
|
MINVAL = 180;
|
|
MAXVAL = 181;
|
|
}
|
|
optional TermType type = 1;
|
|
|
|
// This is only used when type is DATUM.
|
|
optional Datum datum = 2;
|
|
|
|
repeated Term args = 3; // Holds the positional arguments of the query.
|
|
message AssocPair {
|
|
optional string key = 1;
|
|
optional Term val = 2;
|
|
}
|
|
repeated AssocPair optargs = 4; // Holds the optional arguments of the query.
|
|
// (Note that the order of the optional arguments doesn't matter; think of a
|
|
// Hash.)
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// EXAMPLE //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// ```ruby
|
|
// r.table('tbl', {:read_mode => 'outdated'}).insert([{:id => 0}, {:id => 1}])
|
|
// ```
|
|
// Would turn into:
|
|
// Term {
|
|
// type = INSERT;
|
|
// args = [Term {
|
|
// type = TABLE;
|
|
// args = [Term {
|
|
// type = DATUM;
|
|
// datum = Datum { type = R_STR; r_str = "tbl"; };
|
|
// }];
|
|
// optargs = [["read_mode",
|
|
// Term {
|
|
// type = DATUM;
|
|
// datum = Datum { type = R_STR; r_bool = "outdated"; };
|
|
// }]];
|
|
// },
|
|
// Term {
|
|
// type = MAKE_ARRAY;
|
|
// args = [Term {
|
|
// type = DATUM;
|
|
// datum = Datum { type = R_OBJECT; r_object = [["id", 0]]; };
|
|
// },
|
|
// Term {
|
|
// type = DATUM;
|
|
// datum = Datum { type = R_OBJECT; r_object = [["id", 1]]; };
|
|
// }];
|
|
// }]
|
|
// }
|
|
// And the server would reply:
|
|
// Response {
|
|
// type = SUCCESS_ATOM;
|
|
// token = 1;
|
|
// response = [Datum { type = R_OBJECT; r_object = [["inserted", 2]]; }];
|
|
// }
|
|
// Or, if there were an error:
|
|
// Response {
|
|
// type = RUNTIME_ERROR;
|
|
// token = 1;
|
|
// response = [Datum { type = R_STR; r_str = "The table `tbl` doesn't exist!"; }];
|
|
// backtrace = [Frame { type = POS; pos = 0; }, Frame { type = POS; pos = 0; }];
|
|
// }
|