Live tables
Upsert Arrow record batches by key. Views sort and filter the rows, groups aggregate them, and both follow every change incrementally instead of being recomputed.
- Batches are kept as they arrive, shared rather than copied
- Filters follow SQL's three-valued logic: comparisons with null are unknown
- Reading a view never allocates; the grid shows it directly
- Grouped count, sum, min, max and mean, exact for integers and decimals
- Model-based tests check every view and group against a full recomputation
use densa_data::{
Aggregate, CompareOp, Filter, GroupSpec, LiveTable, Order, Scalar, ViewSpec,
};
let mut table = LiveTable::new(schema, "symbol")?;
let movers = table.add_view(
ViewSpec::new()
.filter(Filter::compare("volume", CompareOp::Gt, Scalar::Int(1_000)))
.sort_by("change_pct", Order::Descending),
)?;
let sectors = table.add_groups(
GroupSpec::new().group_by("sector").aggregate(Aggregate::sum("volume")),
)?;
table.upsert(ticks)?; // new symbols insert, known ones update
table.delete(&delisted)?; // an array of keys
let view = table.view(movers).unwrap(); // in order, after every change
let totals = table.groups(sectors).unwrap().to_batch()?; // one row per sector