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 CommandDataDescription 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. It is also used to represent the input descriptor when a query does not receive any arguments, or the state descriptor for an empty/default state.

Set Descriptor

  1. struct SetDescriptor {
  2. // Indicates that this is a Set value descriptor.
  3. uint8 type = 0;
  4. // Descriptor ID.
  5. uuid id;
  6. // Set element type descriptor index.
  7. uint16 type_pos;
  8. };

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

Object Shape Descriptor

  1. struct ObjectShapeDescriptor {
  2. // Indicates that this is an
  3. // Object Shape descriptor.
  4. uint8 type = 1;
  5. // Descriptor ID.
  6. uuid id;
  7. // Number of elements in shape.
  8. uint16 element_count;
  9. ShapeElement elements[element_count];
  10. };
  11. struct ShapeElement {
  12. // Field flags:
  13. // 1 << 0: the field is implicit
  14. // 1 << 1: the field is a link property
  15. // 1 << 2: the field is a link
  16. uint32 flags;
  17. uint8<Cardinality> cardinality;
  18. // Field name.
  19. string name;
  20. // Field type descriptor index.
  21. uint16 type_pos;
  22. };
  1. enum Cardinality {
  2. NO_RESULT = 0x6e;
  3. AT_MOST_ONE = 0x6f;
  4. ONE = 0x41;
  5. MANY = 0x6d;
  6. AT_LEAST_ONE = 0x4d;
  7. };

Objects are encoded on the wire as tuples.

Base Scalar Type Descriptor

  1. struct BaseScalarTypeDescriptor {
  2. // Indicates that this is an
  3. // Base Scalar Type descriptor.
  4. uint8 type = 2;
  5. // Descriptor ID.
  6. uuid id;
  7. };

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

00000000-0000-0000-0000-000000000130

cfg::memory

Scalar Type Descriptor

  1. struct ScalarTypeDescriptor {
  2. // Indicates that this is a
  3. // Scalar Type descriptor.
  4. uint8 type = 3;
  5. // Descriptor ID.
  6. uuid id;
  7. // Parent type descriptor index.
  8. uint16 base_type_pos;
  9. };

Tuple Type Descriptor

  1. struct TupleTypeDescriptor {
  2. // Indicates that this is a
  3. // Tuple Type descriptor.
  4. uint8 type = 4;
  5. // Descriptor ID.
  6. uuid id;
  7. // The number of elements in tuple.
  8. uint16 element_count;
  9. // Indexes of element type descriptors.
  10. uint16 element_types[element_count];
  11. };

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

Named Tuple Type Descriptor

  1. struct NamedTupleTypeDescriptor {
  2. // Indicates that this is a
  3. // Named Tuple Type descriptor.
  4. uint8 type = 5;
  5. // Descriptor ID.
  6. uuid id;
  7. // The number of elements in tuple.
  8. uint16 element_count;
  9. // Indexes of element type descriptors.
  10. TupleElement elements[element_count];
  11. };
  12. struct TupleElement {
  13. // Field name.
  14. string name;
  15. // Field type descriptor index.
  16. int16 type_pos;
  17. };

Array Type Descriptor

  1. struct ArrayTypeDescriptor {
  2. // Indicates that this is an
  3. // Array Type descriptor.
  4. uint8 type = 6;
  5. // Descriptor ID.
  6. uuid id;
  7. // Element type descriptor index.
  8. uint16 type_pos;
  9. // The number of array dimensions, at least 1.
  10. uint16 dimension_count;
  11. // Sizes of array dimensions, -1 indicates
  12. // unbound dimension.
  13. uint32 dimensions[dimension_count];
  14. };

Enumeration Type Descriptor

  1. struct EnumerationTypeDescriptor {
  2. // Indicates that this is an
  3. // Enumeration Type descriptor.
  4. uint8 type = 7;
  5. // Descriptor ID.
  6. uuid id;
  7. // The number of enumeration members.
  8. uint16 member_count;
  9. // Names of enumeration members.
  10. string members[member_count];
  11. };

Input Shape Descriptor

  1. struct InputShapeDescriptor {
  2. // Indicates that this is an
  3. // Object Shape descriptor.
  4. uint8 type = 8;
  5. // Descriptor ID.
  6. uuid id;
  7. // Number of elements in shape.
  8. uint16 element_count;
  9. ShapeElement elements[element_count];
  10. };

Input objects are encoded on the wire as sparse objects.

Range Type Descriptor

  1. struct RangeTypeDescriptor {
  2. // Indicates that this is a
  3. // Range Type descriptor.
  4. uint8 type = 9;
  5. // Descriptor ID.
  6. uuid id;
  7. // Range type descriptor index.
  8. uint16 type_pos;
  9. };

Ranges are encoded on the wire as ranges.

Scalar Type Name Annotation

Part of the type descriptor when the Execute 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.

  1. struct TypeAnnotationDescriptor {
  2. uint8 type = 0xff;
  3. // ID of the scalar type.
  4. uuid id;
  5. // Type name.
  6. string type_name;
  7. };

Type Annotation Descriptor

Drivers must ignore unknown type annotations.

  1. struct TypeAnnotationDescriptor {
  2. // Indicates that this is an
  3. // Type Annotation descriptor.
  4. uint8 type = 0x80..0xfe;
  5. // ID of the descriptor the
  6. // annotation is for.
  7. uuid id;
  8. // Annotation text.
  9. string annotation;
  10. };