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.
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.
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.
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 |
---|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
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;
};
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
.
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;
};
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];
};
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.
struct TypeAnnotationDescriptor {
uint8 type = 0xff;
// ID of the scalar type.
uuid id;
// Type name.
string type_name;
};