Type Descriptors

This section describes how type information for query input and results is encoded. Specifically, this is needed to decode the server response to the DescribeStatement message.

The type descriptor is essentially a list of type information blocks:

  • each block encodes one type;

  • blocks can reference other blocks.

While parsing the blocks, a database driver can assemble an encoder or a decoder of the EdgeDB binary data.

An encoder is used to encode objects, native to the driver’s runtime, to binary data that EdegDB can decode and work with.

A decoder is used to decode data from EdgeDB native format to data types native to the driver.

There is one special type with type id of zero: 00000000-0000-0000-0000-000000000000. The describe result of this type contains zero blocks. It’s used when a statement returns no meaningful results, e.g. the CREATE DATABASE example statement.

Copy
struct SetDescriptor {
    // Indicates that this is a Set value descriptor.
    uint8   type = 0;

    // Descriptor ID.
    uuid    id;

    // Set element type descriptor index.
    uint16  type_pos;
};

Set values are encoded on the wire as single-dimensional arrays.

Copy
struct ObjectShapeDescriptor {
    // Indicates that this is an
    // Object Shape descriptor.
    uint8           type = 1;

    // Descriptor ID.
    uuid            id;

    // Number of elements in shape.
    uint16          element_count;

    ShapeElement    elements[element_count];
};

struct ShapeElement {
    // Field flags:
    //   1 << 0: the field is implicit
    //   1 << 1: the field is a link property
    //   1 << 2: the field is a link
    uint8           flags;

    // Field name.
    string          name;

    // Field type descriptor index.
    uint16          type_pos;
};

Objects are encoded on the wire as tuples.

Copy
struct BaseScalarTypeDescriptor {
    // Indicates that this is an
    // Base Scalar Type descriptor.
    uint8           type = 2;

    // Descriptor ID.
    uuid            id;
};

The descriptor IDs for base scalar types are constant. The following table lists all EdgeDB base types descriptor IDs:

ID

Type

00000000-0000-0000-0000-000000000100

std::uuid

00000000-0000-0000-0000-000000000101

std::str

00000000-0000-0000-0000-000000000102

std::bytes

00000000-0000-0000-0000-000000000103

std::int16

00000000-0000-0000-0000-000000000104

std::int32

00000000-0000-0000-0000-000000000105

std::int64

00000000-0000-0000-0000-000000000106

std::float32

00000000-0000-0000-0000-000000000107

std::float64

00000000-0000-0000-0000-000000000108

std::decimal

00000000-0000-0000-0000-000000000109

std::bool

00000000-0000-0000-0000-00000000010A

std::datetime

00000000-0000-0000-0000-00000000010E

std::duration

00000000-0000-0000-0000-00000000010F

std::json

00000000-0000-0000-0000-00000000010B

cal::local_datetime

00000000-0000-0000-0000-00000000010C

cal::local_date

00000000-0000-0000-0000-00000000010D

cal::local_time

00000000-0000-0000-0000-000000000110

std::bigint

00000000-0000-0000-0000-000000000111

cal::relative_duration

Copy
struct ScalarTypeDescriptor {
    // Indicates that this is a
    // Scalar Type descriptor.
    uint8           type = 3;

    // Descriptor ID.
    uuid            id;

    // Parent type descriptor index.
    uint16          base_type_pos;
};
Copy
struct TupleTypeDescriptor {
    // Indicates that this is a
    // Tuple Type descriptor.
    uint8     type = 4;

    // Descriptor ID.
    uuid      id;

    // The number of elements in tuple.
    uint16    element_count;

    // Indexes of element type descriptors.
    uint16    element_types[element_count];
};

An empty tuple type descriptor has an ID of 00000000-0000-0000-0000-0000000000FF.

Copy
struct NamedTupleTypeDescriptor {
    // Indicates that this is a
    // Named Tuple Type descriptor.
    uint8        type = 5;

    // Descriptor ID.
    uuid         id;

    // The number of elements in tuple.
    uint16       element_count;

    // Indexes of element type descriptors.
    TupleElement elements[element_count];
};

struct TupleElement {
    // Field name.
    string  name;

    // Field type descriptor index.
    int16   type_pos;
};
Copy
struct ArrayTypeDescriptor {
    // Indicates that this is an
    // Array Type descriptor.
    uint8        type = 6;

    // Descriptor ID.
    uuid         id;

    // Element type descriptor index.
    uint16       type_pos;

    // The number of array dimensions, at least 1.
    uint16       dimension_count;

    // Sizes of array dimensions, -1 indicates
    // unbound dimension.
    uint32       dimensions[dimension_count];
};
Copy
struct EnumerationTypeDescriptor {
    // Indicates that this is an
    // Enumeration Type descriptor.
    uint8        type = 7;

    // Descriptor ID.
    uuid         id;

    // The number of enumeration members.
    uint16       member_count;

    // Names of enumeration members.
    string       members[member_count];
};

Part of the type descriptor when the Prepare client message has the INLINE_TYPENAMES header set. Every non-builtin base scalar type and all enum types would have their full schema name provided via this annotation.

Copy
struct TypeAnnotationDescriptor {
    uint8        type = 0xff;

    // ID of the scalar type.
    uuid         id;

    // Type name.
    string       type_name;
};

Drivers must ignore unknown type annotations.

Copy
struct TypeAnnotationDescriptor {
    // Indicates that this is an
    // Type Annotation descriptor.
    uint8        type = 0x80..0xfe;

    // ID of the descriptor the
    // annotation is for.
    uuid         id;

    // Annotation text.
    string       annotation;
};
Light
Dark
System