Rindle docs and package mapSkip to main content

Module value

Module value 

Expand description

The value vocabulary — moved to the dependency-free rindle-value crate and re-exported here, so rindle::value::… is unchanged for every consumer. Crates that need only cells (the write plane, the CDC apply plane) depend on rindle-value directly and therefore cannot reach the engine at all. The canonical value/row model — the union that graduates into 01-foundations §2–§3, refined by the SQLite step-buffer lifetime (the forcing function). One model serves BOTH leaf backends:

  • the borrowed-step-buffer rusqlite cursor (sqlite.rs), whose column pointers are valid only until the next step, and
  • the held-Rc crate::btree::BTreeCursor, which vends a row borrowed from an Rc<BNode> snapshot it owns.

Three things are encoded structurally:

  1. A borrowed Value<'a> (zero-copy, Copy) split from an owned OwnedValue. The transient cursor path flows Value<'a>; the only heap allocation is Value::to_owned, at the well-defined escape points the borrow checker forces (and the JS already copies at).
  2. Str/Json carry bytes (&[u8]), not &str. SQLite’s default BINARY collation is a bytewise memcmp, so the comparator needs no UTF-8 validation; the fallible, scanning &[u8]&str step is deferred to the app escape (to_owned). This is a deliberate refinement of foundations §2.2 (which wrote &'a str) driven by the SQLite reality: TEXT is not guaranteed UTF-8, and the validation scan is pure waste on the pass-through path.
  3. Two distinct, undirivable comparators. compare_values treats null == null (sorting); values_equal treats null != null (join matching, SQL semantics). Deriving Ord/PartialEq would make calling the wrong one trivially easy; named free functions make that bug hard to write. (Maps to zql/src/ivm/data.ts compareValues vs valuesEqual.)

Structs§

OwnedRow
An owned row: an index-addressed, immutable, cheaply-clonable value sequence, stored as one flat allocation (205-FLAT-ROW-SINGLE-BUFFER-DESIGN.md). Cloning a row into an overlay / the view / a heap is a refcount bump, not a deep copy (shared-row aliasing is pervasive) — exactly as when this was Arc<[OwnedValue]>, but the cells now live inline in the row’s own buffer (no per-Str-cell Arc<str> block), so materializing a row is one allocation instead of 2 + k_text.
RelDef
A declared outgoing relationship on a table Schema (slot = index in Schema::relationships). Carries the public name the View surfaces (09) and, when known, the target Schema the relationship points at — the hierarchical SourceSchema the production ArrayView (09) navigates to sort child entries. child is None for a join-only RelDef (name resolution alone — the join already holds the child schema separately); the View requires Some.
RelId
A resolved relationship slot — the index of a relationship in its parent table’s Schema::relationships. Relationship names are resolved to a RelId once, at build time (Schema::rel_slot); the hot path (Change::Child``.rel, Relationship``.slot) carries the index, never a string (foundations §3.4, “never a string map”). A distinct newtype from ColId so the two index spaces can’t be confused.
ScalarProjection
A scalar projection annotation on a relationship slot (REDUCE-DESIGN.md §9, Tier 1). A relationship aggregate — issue { commentCount: count(comments) } — lives in the engine tree as an ordinary singular one-row relationship whose child is the synthetic aggregate row [group_key…, agg]. This annotation tells the presentation boundary (the View marshaller and every wire receiver) to unwrap that one-row child into a plain scalar field named after the relationship: instead of commentCount: [{ issueID: 1, count: 5 }] the consumer sees commentCount: 5. It is purely a result-shape concern — the dataflow and the reconstructed tree stay a plural relationship of one row.
Schema
The view / pipeline schema: a table’s columns + key + sort plus the per-query relationship slots and .one() shape the dataflow and materialized view carry. A source table is registered with the lighter SourceSchema (no relationships, no singular); the build path widens that to a Schema and fills relationships from the query AST — never from a source declaration, of which there are none.
SourceSchema
Static, user-declared source table metadata: columns, primary key, and the table’s default sort. This is the table-registration boundary type — what Graph::add_source and the builder’s resolve callback speak.

Enums§

OwnedValue
Owned counterpart, used wherever a value must outlive the cursor step that produced it: overlays, the memory store (the COW B+tree), the view, and operator-buffered state (Take/Exists, merge-heap heads).
Value
A cell value as seen while streaming. Str/Json borrow raw bytes from the underlying buffer — a SQLite column-text pointer (valid only until the next step) or the bytes inside an owned row — so the whole value is valid only for 'a.
ValueType
The logical type of a column (or a literal), mirroring the JS ValueType (zero-schema/table-schema.ts): the five types Zero stores, plus the opt-in exact-integer plane (design 226). It drives the SQLite value boundary — to_sqlite_param (boolean→0/1, json→serialized TEXT) and from_sqlite (ty-directed col() conversion, the number safe-int bound check). The leaf maps each to a crate::value storage class.

Traits§

RowRef
A borrowed view of one row; columns addressed by ColId. The returned Value borrows self, so it is valid only as long as the row reference — for the SQLite leaf that means until the next next_row.
RowStream
A lending stream of rows. next_row reborrows self, so the row it returns is invalidated by the next call — exactly the SQLite cursor contract, now a compile-time invariant. This is the leaf source’s output shape; it is not std::iter::Iterator (which hands out owned items and cannot express the borrow). GAT-based lending, stable since Rust 1.65.

Functions§

compare_int_f64
Exact IntFloat comparison (design 226 §5.1): compare mathematical values, with the two total_cmp placements preserved bit-for-bit so no existing data reorders — Int(i) carries +0.0’s sign (Int(0) > Float(-0.0)), and NaNs keep their total_cmp positions (-NaN below every Int, +NaN above).
compare_rows
Compare two owned rows under a sort spec (asc/desc per column). The common short sorts (one/two columns) are unrolled to drop iterator overhead on the hottest path. Each cell is borrowed via as_ref() and fed to the Value<'_> comparator — no allocation.
compare_values
SORT / identity-of-storage comparison. null == null (Equal). Total order: null < everything. Floats use total_cmp (NOT subtraction — avoids the JS a - b overflow/NaN trap). Strings/json compare bytewise == SQLite BINARY collation. Int/Float are the same JS number domain and compare by widening to f64 (JS has no int/float split — the distinction is a Rust-port artifact, so a mixed pair is not a type error). It arises in practice when an AST paging bound — integral literals lower to Int — is sorted against a Number column that vends as Float (e.g. a SQLite leaf). A pair of genuinely different JS types (number vs string, …) is still a builder bug and panics, mirroring the JS oracle’s compareValues throw.
float_int_class
The §5.4 canonical numeric class: Some(i) iff Float(f) is exactly equal to Int(i) under compare_int_f64 — finite, integral, in i64 range, and not -0.0 (which total_cmp orders below +0.0/Int(0) and so keeps float identity). Joint with the exact comparator this makes numeric equality an equivalence relation a Hash + Eq key can represent: Float(2^53) shares Int(2^53)’s class, while Int(2^53 + 1) keeps all 64 bits.
owned_row
Build an OwnedRow from a vec literal (test/util convenience).
same_pk
True if rows share the same primary key (PK columns are non-null, so values_equal behaves like identity here).
values_equal
JOIN / equality comparison. null != null (any null operand ⇒ not equal) — the opposite of compare_values. Required for correct join semantics.
values_identical
PREDICATE identity comparison — the third comparator (07 §4.2/§8.1). A compiled where predicate’s = / != / IN evaluates with this, NOT with values_equal: a filter treats null as identical to null (so col = null matches a null cell), the opposite of join semantics. It is distinct from all three of:

Type Aliases§

ColId
A column index into a row. Names are resolved to indices once, at pipeline-build time; the hot path never sees a string.
Sort
(column, ascending) — sort spec resolved to indices at build time.