Skip to content

Overview

CBOR protocol

SurrealDB extends the CBOR protocol with a number of custom tags to support the full range of data types available in SurrealDB. This document provides an overview of the custom tags and their respective values.

The figure below follows some values through these tags, and through the JSON that the HTTP /sql endpoint returns instead.

A table follows eight SurrealQL values through CBOR and through JSON. In CBOR each value carries a tag that names its type: tag 8 for the record ID person:tobie, tag 10 for a decimal, tag 12 for a datetime as seconds and nanoseconds, tag 14 for a duration, tag 37 for a UUID, tag 56 for a set and tag 6 for NONE. The JavaScript SDK turns these into RecordId, Decimal, DateTime, Duration, Uuid, Set and undefined. The JSON from the HTTP /sql endpoint writes the record ID, decimal, datetime, duration and UUID as plain strings, the set as an array, and NONE as null, the same as NULL, so the type is no longer part of the value.A table follows eight SurrealQL values through CBOR and through JSON. In CBOR each value carries a tag that names its type: tag 8 for the record ID person:tobie, tag 10 for a decimal, tag 12 for a datetime as seconds and nanoseconds, tag 14 for a duration, tag 37 for a UUID, tag 56 for a set and tag 6 for NONE. The JavaScript SDK turns these into RecordId, Decimal, DateTime, Duration, Uuid, Set and undefined. The JSON from the HTTP /sql endpoint writes the record ID, decimal, datetime, duration and UUID as plain strings, the set as an array, and NONE as null, the same as NULL, so the type is no longer part of the value.

A datetime represented in an RFC 3339 string.

Adopted from the Iana Specification.

Available since: v4.0.0

From 4.0, SurrealDB refuses this tag in requests. Send a datetime as Tag 12, which SurrealDB also always sends back.

Represents a NONE value. The value passed to the tagged value is null, as it cannot be empty. From 4.0, any other content under this tag is refused.

A table name, represented as a string.

A Record ID, represented as a two-value array, containing a table part (string) and an id part (string, number, object or array).

Instead of a two-value array, SurrealDB also accepts a string with a string-formatted Record ID. A string Record ID will never be sent back from SurrealDB, however.

A UUID represented in a string format.

Available since: v4.0.0

From 4.0, SurrealDB refuses this tag in requests. Send a UUID as Tag 37, which SurrealDB also always sends back.

A Decimal represented in a string format.

A Datetime represented in a two-value array, containing seconds (number) and optionally nanoseconds (number).

A Duration represented in a string format.

Available since: v4.0.0

From 4.0, SurrealDB refuses this tag in requests. Send a duration as Tag 14, which SurrealDB also always sends back.

A Duration represented in a two-value array, containing optionally seconds (number) and optionally nanoseconds (number). An empty array will be considered a duration of 0.

A Future represented as a string containing the uncomputed SurrealQL query or expression. The value must be sent as an Object wrapped in {}, which is also the format SurrealDB returns it in. This allows it to be computed when it is accessed or used within a query.

A UUID represented in a binary format. Please reference (https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.as_bytes).

Adopted from the Iana Specification.

A Range represented as a two-value array containing optional bounds. Each bound can be either null (for unbounded), or a tagged value using either Tag 50 (included bound) or Tag 51 (excluded bound).

The bounds follow SurrealQL's range syntax where .. represents a range, >.. represents an excluded lower bound, and ..= represents an included upper bound.

An included bound value used within Range bounds. The tagged value represents an inclusive boundary (equivalent to ..= for upper bounds in SurrealQL range syntax).

An excluded bound value used within Range bounds. The tagged value represents an exclusive boundary (equivalent to >.. for lower bounds in SurrealQL range syntax).

A file pointer represented as a two-value array containing the bucket name (string) and the file key (string). The file pointer f"avatars:/users/tobie.png" is the array ["avatars", "/users/tobie.png"].

A Set represented as an array of its values, each encoded in the same way as any other value. SurrealDB sorts the values and removes duplicates when it decodes the set, so the order of the array in a request does not matter.

A Geometry Point represented by a two-value array containing a longitude (float) and latitude (float).

A Geometry Line represented by an array with two or more points (Tag 88).

A Geometry Polygon represented by an array with one or more closed lines (Tag 89).

If a line is not closed, meaning that its first and last points are not equal, SurrealDB automatically appends the line's first point to its end.

A Geometry MultiPoint represented by an array with one or more points (Tag 88).

A Geometry MultiLine represented by an array with one or more lines (Tag 89).

A Geometry MultiPolygon represented by an array with one or more polygons (Tag 90).

A Geometry Collection represented by an array with one or more geometry values (Tag 88, Tag 89, Tag 90, Tag 91, Tag 92, Tag 93 or Tag 94).

Available since: v4.0.0

From 4.0, SurrealDB refuses a request that contains any of the following:

  • Tag 0, Tag 9 or Tag 13. Send Tag 12, Tag 37 or Tag 14 instead.

  • An integer outside the signed 64-bit range.

  • A map with the same key more than once.

  • Tag 6 with content other than null.

  • A tag that SurrealDB does not know.

A refused request fails with a parse error whose message names the problem, such as CBOR tag 0 (a datetime as text) is not accepted: send tag 12 [seconds, nanos]. Every server since 1.5.0 reads tags 12, 37 and 14, so a client that sends only those works with every server version.

The same rules apply to encoding::cbor::decode.

Available since: v4.0.0

SurrealDB 4.0 adds sized number types such as i32 and f32. Plain CBOR (application/cbor, WebSocket subprotocol cbor) sends these as ordinary CBOR integers and floats, so the size is lost. A u64 above 9223372036854775807 is sent as a decimal (tag 10) instead. To keep the size, use CBOR v2: the application/cbor; v=2 content type over HTTP, or the cbor.2 WebSocket subprotocol. CBOR v2 tags each sized number:

TagType
180i8
181u8
182i16
183u16
184i32
185u32
186u64
187f16
188f32

Plain CBOR refuses tags 180 to 188 in requests.

Available since: v4.0.0

CBOR v2 also has tags for the date, time, timestamp and interval types, for bigdecimal and for regexes. Plain CBOR has no tag for these types, so it sends most of them in a form that loses the type, and it cannot send a regex at all:

TagTypeContentPlain CBOR sends
100dateThe number of days since 1970-01-01, as an integer, as defined in RFC 8943A datetime (tag 12) at midnight UTC
189timeThe number of nanoseconds since midnight, as an unsigned integerA duration (tag 14)
190timestampA two-value array of seconds and nanoseconds since 1970-01-01T00:00:00, with no time zoneA datetime (tag 12)
191intervalA three-value array of months, days and microsecondsThe interval as text, such as 'P1M2D'
192bigdecimalThe number as textA decimal (tag 10) when the value fits one, and otherwise the number as text
193regexThe pattern as textNothing: the response fails, because plain CBOR cannot encode a regex

A bigdecimal whose value fits a decimal is sent as tag 10 in CBOR v2 as well, so a client can receive tag 10 for a field whose type is bigdecimal.

The pattern under tag 193 uses SurrealQL's own regex syntax, so SurrealDB does not use the standard CBOR tag 35, which names PCRE and ECMAScript syntax. A client that receives tag 193 must not assume that its own language's regex engine reads the pattern in the same way. A pattern that does not compile is refused with Expected a valid regex under tag 193, followed by the reason.

Was this page helpful?