Catalog Format
This page documents how schema metadata is persisted in the system catalog.
Where Catalog Metadata Lives
- The system catalog itself is a B-tree (
src/schema/catalog.rs). - The root page id of that B-tree is stored in the main DB header field
catalog_root. - Catalog keys are UTF-8 bytes; values are binary-serialized structs.
Key namespace:
table:<table_name>-> serializedTableDefindex:<index_name>-> serializedIndexDef
TableDef Value Format
TableDef::serialize / deserialize in src/schema/catalog.rs.
Layout (length-prefixed, little-endian integers):
name_len: u16name: [u8; name_len](UTF-8)column_count: u16- Repeated
column_counttimes:col_blob_len: u16col_blob: [u8; col_blob_len](ColumnDefpayload)
pk_tag: u8- Primary-key names by
pk_tag:0: no PK names1: single-column PK:pk_len: u16pk_name: [u8; pk_len]
2: composite PK:pk_count: u16- repeated
pk_counttimes:pk_len: u16+pk_name
data_btree_root: u64next_rowid: i64(optional tail; defaults to0if absent)row_format_version: u8(optional tail; defaults to0if absent)stats_row_count: u64(optional tail; defaults to0if absent)
Unknown pk_tag causes decode failure.
ColumnDef Embedded Blob Format
ColumnDef::serialize / deserialize in src/schema/column.rs.
Layout:
name_len: u16name: [u8; name_len](UTF-8)type_byte: u8flags: u8- Optional
size: u32only when type isVARCHAR/VARBINARY default_tag: u8+ optional default payloadcheck_len: u16+ optional check expression bytes
type_byte mapping:
1BIGINT2VARCHAR3VARBINARY4TINYINT5SMALLINT6INT7TEXT8FLOAT9DOUBLE10DATE11DATETIME12TIMESTAMP
Flag bits:
0x01primary key0x02unique0x04nullable0x08hidden0x10auto_increment
default_tag mapping:
0no default1NULL2integer (i64)3string (u16length + bytes)4float (f64)
Unknown type_byte or default_tag causes decode failure.
IndexDef Value Format
IndexDef::serialize / deserialize in src/schema/index.rs.
Layout:
name_len: u16+nametable_len: u16+table_namefirst_col_len: u16+first_column_name(legacy position)index_type: u8(1BTree,2Fulltext)is_unique: u8(0/1)btree_root: u64extra_col_count: u16- Repeated extra columns:
col_len: u16+col_name stats_distinct_keys: u64(optional tail; default0)- Numeric-bounds extension (optional):
stats_num_bounds_known: u8stats_num_min: i64stats_num_max: i64
- FULLTEXT stop-filter extension (optional):
fts_stop_filter: u8fts_stop_df_ratio_ppm: u32
- Histogram extension (optional):
hist_bin_count: u16- repeated
hist_bin_counttimes:u32
Unknown index_type causes decode failure.
Compatibility Policy in Code
Current decode strategy is append-only/tolerant:
- New fields are generally appended at the tail.
- Older records are accepted by defaulting missing tail fields.
- Some old layouts are explicitly recognized (for example
IndexDefstats tails). - Truncated/corrupt payloads fail decode (
None) or ignore incomplete optional tails (histogram extension inIndexDef).
Executable Spec (Tests)
Primary roundtrip tests:
src/schema/catalog.rs(test_table_def_roundtrip)src/schema/column.rs(test_column_roundtrip_all_types)src/schema/index.rs(test_composite_index_roundtrip)
Backward-compat/malformed behavior:
src/schema/index.rs(test_deserialize_old_layout_keeps_fts_settings)src/schema/index.rs(test_deserialize_truncated_index_returns_none)