Expand description
Backend-agnostic source machinery, shared by the memory (BTree) and SQLite
leaves. This module references no BTree, no rusqlite, AND no Node —
it is generic over S: RowStream and deals only in rows (OwnedRow) and
source changes (SourceChange). It is the seam the spec calls source_common
(04 §4.6): the two leaves differ only in the concrete S they pass in.
A source emits rows, not nodes. The overlay splice, the start/constraint/
filter chain, the k-way merge, and the push/edit-split orchestration here all
operate on rows. A row becomes a Node (row + lazily
attached relationships) only at the connection boundary — Graph::fetch
on a SourceConn wraps each emitted row in a leaf node on the read path, and
the SourceConn’s push driver wraps each SourceChange into a node-bearing
Change on the write path. Downstream joins then attach relationships. So
the Node concept lives entirely above this module.
What lives here (faithful ports of memory-source.ts, which is the JS root
even though 05/TableSource consume it verbatim):
- the epoch-gated overlay splice — ordered (
generate_with_overlay) and unordered (generate_with_overlay_unordered) — plus the pure overlay narrowers (compute_overlays,overlays_for_constraint, …); - the post-scan row chain (
generate_with_start,generate_with_constraint,generate_with_filter); - the k-way
merge_sorted_streams(binary min-heap,Drop-clean); - the predicate-filtered push (
filter_push, edit-splitting by predicate); - the eager push orchestration (
gen_push_and_write_with_split_edit): edit-split detection, per-connection fan-out with the live overlay + epoch gate, and the deferred write-after-drain.
The connection/overlay types (Connection, ConnectionFilters,
Overlay, Overlays, RowPredicate) live here too because their shape
is identical across backends (04 §4.1, §4.2).
Structs§
- Conn
Table - A source’s connection registry: the
Connections plus a generational free-list, so a torn-down connection’s slot is RECYCLED rather than leaked under query churn (the source-side analogue of the graph arena’s node/storage reuse). Shared by bothSourcebackends (the memoryBTreeleaf and the SQLiteTableSource) so the reuse logic — and its stale-ConnIdfail-fast — lives in exactly one place and the two backends cannot drift apart. - Connection
- One connection (one downstream output). Self-joins make two. Mirrors
Connection(memory-source.ts:75). IDENTICAL shape to05’s so this module stays backend-agnostic. The mutable bits areCellso they bump during a push without a&mutborrow held across a vend (foundations §6.2). - Connection
Filters - The fully-pushed-down filter + the precomputed PK constraint. The memory leaf
only evaluates
predicate;pk_constraintis hoisted from the condition at connect time (the JS recomputes it per fetch viaprimaryKeyConstraintFrom Filters— we hoist since the condition is fixed per connection).fully_ appliedmirrorsSourceInput.fullyAppliedFilters(memory-source.ts:180). - Overlay
- The single in-flight source change, epoch-tagged. Rows are OWNED (overlays are
materialized — foundations §3.3). Mirrors
Overlay(memory-source.ts:59); IDENTICAL to05’s (it lives here). - Overlays
- The narrowed add/remove pair fed to the splice (
Overlays,memory-source.ts:64). Both owned.
Enums§
- Operand
- One side of a
SqlCondition::Simple. AColumnlowers to its quoted identifier (resolved from the schema at build time); aLiterallowers to a bound?param (query-builder.tsvaluePositionToSQL). - SqlCondition
- A filter condition lowered to a backend-neutral AST — the input the SQLite
leaf’s
build_select_querywalks to emit the SELECTWHERE(port of query-builder.tsNoSubqueryCondition, subqueries already stripped). Pure data, norusqlite: the memory backend ignores it entirely (it filters viaRowPredicate); only the SQLite leaf lowers it to SQL text, leaving thepredicateto narrow only the (not-in-SQL) overlay rows. Column operands are already-resolvedColIds; a literal operand’sOwnedValuevariant selects its SQLite storage form (the JSgetJsType→toSQLiteType). - SqlOp
- Comparison / membership operators (query-builder.ts
simpleConditionToSQL). Most lower to their raw SQL spelling verbatim;In/NotInlower to ajson_each(?)subquery over a JSON-array literal (query-builder.ts:196-205); theLikefamily appendsESCAPE '\'andIlikelowers both sides throughlower(...)(query-builder.tslikeConditionToSQL).Is/IsNotare the NULL-aware equality operators in the JSSimpleOperatorset (ast.ts:37): they reach theWHEREverbatim (a user.where(c, 'IS', null), and the engine’sNOT EXISTS→field IS NOT literalrewrite, resolve-scalar-subqueries.ts:176). Distinct from the start-bound’s nullable-aware=/ISchoice (§3.7), which is a SEPARATE code path keyed on column optionality, not a user operator.
Functions§
- compare_
rows_ rev reverse=false⇒compare_rows(sort, a, b);reverse=true⇒ its negation. Defined ONCE so the cursor seek direction, the overlay-add splice position, the remove-suppress equality, the start gate, and the k-way merge all agree.- compute_
overlays - The full ordered narrowing pipeline: startAt → constraint → each non-empty
multiConstraint → filter (
computeOverlays,memory-source.ts:722). Pure — no leaf access.gate_sort/reverseare the connection comparator — the one the downstream start gate (generate_with_start) applies — NOT the scan’s constrained index sort (seeoverlays_for_start_at’s comparator invariant; the splice’s interleaving comparator is a separate parameter ofgenerate_with_overlay). - generate_
with_ constraint - Trim trailing rows once the constraint stops matching — a
break, NOT a filter (generateWithConstraint,memory-source.ts:505). Valid because the chosen index is sorted by the constraint columns first, so once the scan passes the last matching row every subsequent row fails (§3.1). - generate_
with_ filter - Drop rows failing the predicate (
generateWithFilter,memory-source.ts:517). - generate_
with_ overlay - Drive a leaf cursor through the epoch-gated, narrowed, ordered overlay splice
(
generateWithOverlay,memory-source.ts:697). Generic over the leafS: RowStream— the seam both backends feed. Two comparators, one per job:sortis the index comparator the splice interleaves under (thebreak-safety dependency, §3.1 — it must match the scan order ofrows);gate_sortis the connection comparator thestart_atnarrowing compares under (it must match the downstreamgenerate_with_startgate — seeoverlays_for_start_at’s comparator invariant). They coincide except on a constrained scan, where the index sort leads with the constraint columns.start_at,constraint,predicate,multi_constraintsnarrow the overlay only (the committed rows are filtered later bygenerate_with_filter). - generate_
with_ overlay_ checked - generate_
with_ overlay_ inner - Splice already-computed
overlaysinto an ordered row stream. Exposed for direct testing (the JSgenerateWithOverlayInnersuite).sort/reverseare the index comparator. - generate_
with_ overlay_ inner_ unordered - Splice already-computed
overlaysinto an unordered row stream. Exposed for the JSgenerateWithOverlayInnerUnorderedsuite. - generate_
with_ overlay_ unordered - Unordered variant of
generate_with_overlay(generateWithOverlayUnordered,memory-source.ts:885): NO start, add injected eagerly, remove suppressed by PK. Narrowing is constraint → multiConstraint → predicate (no startAt). - generate_
with_ overlay_ unordered_ checked - generate_
with_ start - Skip rows until the start bound is reached, then pass the rest
(
generateWithStart,memory-source.ts:653). Uses the connection comparator (reverse-aware).start = None⇒ pass-through. - merge_
sorted_ streams - K-way min-heap merge of pre-sorted row streams under the reverse-aware
comparator.
Drop-clean (early close drops every sub-stream — §5.5). - overlays_
for_ constraint - Drop an add/remove that does not match the constraint (
overlaysForConstraint,memory-source.ts:821). - overlays_
for_ multi_ constraint - Keep an add/remove iff it matches some entry of the multiConstraint
(
overlaysForMultiConstraint,memory-source.ts:787). - overlays_
for_ start_ at - Drop an add/remove that sorts strictly before
start_at(overlaysForStartAt,memory-source.ts:806). Reverse-aware. - try_
gen_ push_ and_ write_ with_ split_ edit
Type Aliases§
- RowPredicate
- The in-memory predicate compiled from a connection’s pushed-down filter
(
createPredicate, owned by07).Rcso a fetch can clone it into the returned lazy stream without holding aRefCellborrow on connection state across the vend (the cardinal rule — foundations §6.2). The memory leaf reads columns byColIdindex; a bare&Rowkeeps this backend-agnostic.