Structured DB
The cobble-data-structure crate provides typed wrappers over raw byte columns.
Current supported structured types are:
Bytes(default for all columns)List(with list-specific merge semantics)
More types are planned for the future. It does not provide arbitrary POJO/struct auto-mapping. You configure column types with StructuredSchema, then read/write StructuredColumnValue.
StructuredDb::open(...) and StructuredSingleDb::open(...) open without schema arguments. They start with default schema (all columns Bytes), then evolve schema via current_schema() + update_schema() ... commit().
StructuredSingleDb
use bytes::Bytes;
use cobble::{Config, VolumeDescriptor};
use cobble_data_structure::{
ListConfig, ListRetainMode, StructuredColumnValue, StructuredSingleDb,
};
let mut config = Config::default();
config.num_columns = 2;
config.total_buckets = 1;
config.volumes = VolumeDescriptor::single_volume("file:///tmp/cobble-structured-single");
let mut db = StructuredSingleDb::open(config)?;
db.update_schema()
.add_list_column(1, ListConfig {
max_elements: Some(100),
retain_mode: ListRetainMode::Last,
preserve_element_ttl: false,
})
.commit()?;
// bytes column
db.put(0, b"k1", 0, StructuredColumnValue::Bytes(Bytes::from_static(b"v0")))?;
// list column (append via merge)
db.merge(0, b"k1", 1, StructuredColumnValue::List(vec![
Bytes::from_static(b"a"),
Bytes::from_static(b"b"),
]))?;
let row = db.get(0, b"k1")?.unwrap();
StructuredDb (Distributed shard writer)
use cobble::{Config, VolumeDescriptor};
use cobble_data_structure::{ListConfig, ListRetainMode, StructuredDb};
let mut config = Config::default();
config.num_columns = 2;
config.total_buckets = 1024;
config.volumes = VolumeDescriptor::single_volume("file:///tmp/cobble-structured-dist");
let mut db = StructuredDb::open(config, vec![0u16..=1023u16])?;
db.update_schema()
.add_list_column(1, ListConfig {
max_elements: Some(100),
retain_mode: ListRetainMode::Last,
preserve_element_ttl: false,
})
.commit()?;
let snap = db.snapshot()?;
let shard_input = db.shard_snapshot_input(snap)?;
Snapshot/coordinator flow is the same as raw Db, but values are encoded/decoded with the structured schema.
Schema Management APIs
Both StructuredDb and StructuredSingleDb expose:
current_schema()— returns current structured schemaupdate_schema()— returns a schema builder that directly holds and mutates innercobble::SchemaBuilder- builder
.commit()— persists and applies schema changes reload_schema()— reloads from persisted underlying cobble schema
Builder methods are applied incrementally to the inner schema builder (matching core schema-builder semantics):
add_bytes_column(column)— set column type back toBytesadd_list_column(column, config)— set column type toListdelete_column(column)— remove structured typing for this column (fallback toBytes)
StructuredReader and StructuredReadOnlyDb
Corresponding structured wrappers are provided for Reader and ReadOnlyDb:
use cobble::{Config, ReaderConfig, VolumeDescriptor};
use cobble_data_structure::{StructuredReader, StructuredReadOnlyDb};
let read_config = ReaderConfig {
volumes: VolumeDescriptor::single_volume("file:///tmp/my-db"),
total_buckets: 1024,
..ReaderConfig::default()
};
let mut reader = StructuredReader::open_current(read_config)?;
let row = reader.get(0, b"k1")?;
reader.refresh()?;
let mut config = Config::default();
config.num_columns = 2;
config.total_buckets = 1024;
config.volumes = VolumeDescriptor::single_volume("file:///tmp/my-db");
let ro = StructuredReadOnlyDb::open(config, snapshot_id, db_id)?;
let row2 = ro.get(0, b"k1")?;
Structured Distributed Scan
use cobble::ScanOptions;
use cobble_data_structure::StructuredScanPlan;
let plan = StructuredScanPlan::new(global_manifest);
for split in plan.splits() {
let scanner = split.create_scanner(config.clone(), &ScanOptions::default())?;
for row in scanner {
let (key, columns) = row?;
// columns: Vec<Option<StructuredColumnValue>>
}
}
Projection Notes
ReadOptions/ScanOptions projection is supported. The structured wrappers remap schema indices correctly for projected columns, so decoded values match the projected column order.