Rindle docs and package mapSkip to main content

Graph

Struct Graph 

Source
pub struct Graph { /* private fields */ }

Implementations§

Source§

impl Graph

Source

pub fn new() -> Graph

Source

pub fn with_storage_factory(storage_factory: StorageFactory) -> Graph

Source

pub fn set_validate_changes(&self, on: bool)

Enable/disable strict change-consistency validation (WS02.2). Off by default. When on, try_source_push returns a RindleError::ConsistencyViolation (instead of a release-stripped debug_assert!) on a malformed change stream.

Source

pub fn validate_changes(&self) -> bool

Whether strict change validation is currently enabled.

Source

pub fn set_push_deadline(&self, deadline: Option<Instant>)

Arm (or clear) the wall-clock deadline for the CURRENT push (FOLLOWER-LAG-SHED §6.6). A host that bounds per-push derive time arms now + P around each push and clears it after; on expiry the fan-out checkpoints park a RindleError::PushDeadlineExceeded and stop iterating — the push surfaces Err from try_source_push with torn operator state, which the host discards (the same abort≙epoch-rehydrate contract a panic uses). Never arm this on wasm: the expiry check calls Instant::now(), which traps there.

Source

pub fn begin_recording(&mut self)

Begin capturing a PipelineManifest: subsequent Graph::add / Graph::alloc_storage record the ids they mint. Bracket one build_pipeline (+ its sink) with this and Graph::take_recording to get the exact id set to hand Graph::destroy_pipeline. # Panics (debug) if recording is already on.

Source

pub fn take_recording(&mut self) -> PipelineManifest

Stop recording and return the captured PipelineManifest (empty if recording was not active).

Source

pub fn alloc_storage(&mut self) -> StorageId

Allocate a fresh scratch-state slot for a stateful operator and return its StorageId (the builder, 08 §5, calls this and embeds the id in the Take/Cap/Exists struct). On the client/test path a fresh MemoryStorage is the namespace (10 §3.3 / §4.5): each slot is a disjoint keyspace because it is a distinct store. On the SQLite server path, a graph constructed with StorageFactory::sqlite vends an op_id-namespaced OpStorage instead (10 §4.4).

Source

pub fn storage_snapshot(&self) -> Vec<Vec<(Box<str>, StorageValue)>>

Snapshot all operator scratch storage, one entry per StorageId in allocation order, each a full ascending scan("") of (key, value) pairs. The test-only sink-independence probe (spec 11 §3.1.1): two graphs built from the same Ast allocate storage in the same order, so snapshot index i denotes the same operator’s store in both — letting run_push_test_ast_view assert Catch-sink storage equals View-sink storage (operator state is identical regardless of sink). StorageValue has no PartialEq, so the comparison is spelled out at the testkit boundary.

Source

pub fn storage_entries_of(&self, manifest: &PipelineManifest) -> usize

The number of (key, value) entries in the operator scratch storage one pipeline owns — the leak probe (take_partition_leak.rs’s assertion, and the family unbind’s “no zombie slot” check of design 310 impl plan D5), keyed by the PipelineManifest captured when the pipeline was built rather than by the whole arena, so a graph hosting several pipelines can be probed one at a time.

Source

pub fn storage_dump_of( &self, manifest: &PipelineManifest, ) -> Vec<(usize, String, String)>

Every (slot, key, value) of one pipeline’s operator scratch storage — the diagnostic twin of storage_entries_of, for the failure message when a leak probe finds entries it did not expect. slot indexes the manifest’s storage list (a stable, build-order name for the operator’s store).

Source

pub fn node_count(&self) -> usize

Total node slots in the arena, including tombstoned (freed) slots. A teardown does not shrink this; a subsequent build reuses freed slots, so this staying flat across a destroy+rebuild is the observable proof of slot reuse.

Source

pub fn storage_count(&self) -> usize

Total storage slots in the arena, including freed (cleared) ones (the node_count analogue for StorageId).

Source

pub fn destroy_pipeline(&mut self, manifest: &PipelineManifest)

Tear down one pipeline, identified by the PipelineManifest captured when it was built (recording mode). Two passes:

  1. Disconnect every SourceConn the pipeline owns via Source::destroy, which nulls that connection’s output edge. Because the push fan-out only drives connections whose output is Some (Graph::try_source_push), this orphans the whole subgraph from every future source push. The shared Source itself — pre-registered, outside the manifest — is untouched: its indexes and connection slots persist (§3.10).
  2. Reclaim each storage slot (clear its contents) and each node slot (replace the operator with Operator::Tombstone, dropping its heavy state: View tree, Collector buffers, compiled predicates, …). Both bump the slot’s generation and push it onto the free-list, so the slot is recycled by the next add/alloc_storage while every other pipeline’s ids stay valid.

Idempotency / safety: each slot’s current generation is asserted to match the manifest before freeing, so a double teardown (or a corrupted manifest) is a loud fail-fast rather than silent corruption. Runs under &mut self, so it can only be called between transactions, never mid-push.

Known limitation (deferred): the shared source’s per-connection slot is nulled (step 1) but not freed — ConnIds are not yet generational, so a source’s conns Vec grows by one small record per teardown. Under sustained build/destroy churn against a long-lived source this is a slow, bounded-per-query leak (no correctness impact: the fan-out skips nulled connections). Reclaiming it needs a generational ConnId + per-source free-list — a planned fast-follow.

Source

pub fn add_source(&mut self, schema: SourceSchema, initial: Vec<Row>) -> NodeId

Add an in-memory source. # Panics if a row’s width does not match the schema; prefer try_add_source in production (WS02.6).

Source

pub fn try_add_source( &mut self, schema: SourceSchema, initial: Vec<Row>, ) -> Result<NodeId, RindleError>

Fallible add_source: validates ingest row widths and returns a RindleError::SchemaViolation instead of panicking (WS02.4).

Source

pub fn add_memory_source(&mut self, source: MemorySource) -> NodeId

Source

pub fn add_dyn_source(&mut self, source: Box<dyn Source>) -> NodeId

Add an external Source erased behind a trait object — e.g. the SQLite TableSource from the rindle-sqlite crate. The in-memory backend uses the concrete add_source/add_memory_source.

Source

pub fn remove_source(&mut self, source: NodeId) -> Result<(), RindleError>

Remove an in-memory source added by add_source / try_add_source: tombstone its node and free the slot (bump generation + free-list) — the single-node analogue of destroy_pipeline. The inverse of add_source, for a synthetic table whose last reading query is gone (AGGREGATE-SYNC-DESIGN.md §4). Errors with a RindleError if source is not an in-memory source node, or if it still has a live connection — every pipeline reading it must be torn down first (destroy_pipeline), which the JS backend guarantees by refcounting readers.

Source

pub fn connect( &mut self, source: NodeId, sort: Option<Sort>, filters: Option<ConnectionFilters>, split_edit_keys: Vec<ColId>, ) -> NodeId

Create a new connection (output) on a source and return its SourceConn node id. Self-joins call this twice on the same source.

Source

pub fn add_join_slot( &mut self, parent: NodeId, child: NodeId, parent_key: Vec<ColId>, child_key: Vec<ColId>, rel_slot: RelId, ) -> NodeId

Wire a hierarchical join with an already-resolved RelId slot. The builder (08) resolves the relationship name against its query-local slot tree — computed from the query AST, not the shared source schema’s declared relationships (which a query can’t pre-declare for synthesized EXISTS-gate aliases like comments_0) — and passes the slot directly, so the join is not re-resolved against input_schema(parent).

Source

pub fn add_flipped_join_slot( &mut self, parent: NodeId, child: NodeId, parent_key: Vec<ColId>, child_key: Vec<ColId>, rel_slot: RelId, ) -> NodeId

The flipped, child-driven inner join with an already-resolved RelId slot — the flipped analogue of Graph::add_join_slot, for the builder’s query-local slot resolution. The flipped join outputs parent rows with the child relationship attached; wire its parent/child inputs with Graph::set_out_edge (JoinParent/JoinChild).

Source

pub fn add_flipped_join_slot_with_chunk_size( &mut self, parent: NodeId, child: NodeId, parent_key: Vec<ColId>, child_key: Vec<ColId>, rel_slot: RelId, chunk_size: usize, ) -> NodeId

Graph::add_flipped_join_slot with an explicit IN-batch chunk size — the test seam analogous to the JS setMultiConstraintChunkSizeForTest (flipped-join.ts:57). A small size forces the chunked fetch path (per-window fetch + node-level k-way merge) so it can be diffed against the unchunked path.

Source

pub fn add_view(&mut self, input: NodeId, schema: Schema) -> NodeId

Add a production View over input with the default ResultType::Complete (the server/test default). For explicit with_ids or a pending result type use Graph::add_view_with. The view shape is carried by schema (a relationship is in-view iff its RelDef has a child schema).

Source

pub fn add_view_with( &mut self, input: NodeId, schema: Schema, with_ids: bool, result_type: ResultType, ) -> NodeId

Add a production View with explicit with_ids and initial ResultType. The view shape is carried by schema.

Source

pub fn add_skip(&mut self, skip: Skip) -> NodeId

Add an out-of-file operator (the fan-out seam). The builder takes a fully-constructed Skip, so growing Skip’s fields never touches this method. Wire its downstream with Graph::set_output. (Take/Cap/Exists/FlippedJoin/Union* get an identical add_*.)

Source

pub fn add_take(&mut self, take: Take) -> NodeId

Add a Take (the LIMIT operator). Like Graph::add_skip, takes a fully-constructed value (the builder hands it a StorageId from Graph::alloc_storage); wire its downstream with Graph::set_output (terminal sink) or Graph::set_out_edge (feeding a relationship join’s parent port).

Source

pub fn add_cap(&mut self, cap: Cap) -> NodeId

Add a Cap (the unordered EXISTS-child limiter). Same shape as Graph::add_take: a fully-constructed value carrying its StorageId; wire its downstream with Graph::set_output / Graph::set_out_edge.

Source

pub fn add_reduce(&mut self, reduce: Reduce) -> NodeId

Add a Reduce (an invertible aggregate, REDUCE-DESIGN.md). Same shape as Graph::add_take: a fully-constructed value carrying its StorageId. Unlike Take, Reduce reshapes its row (output is a synthetic aggregate row), so it carries its own output schema. Wire its downstream with Graph::set_output.

Source

pub fn add_exists(&mut self, exists: Exists) -> NodeId

Add an Exists gate (a FilterChain link). Wire its upstream FilterStart’s chain head to it (Graph::set_chain_head) and its downstream FilterOutput with Graph::set_output.

Source

pub fn add_collector(&mut self, input: NodeId) -> NodeId

Source

pub fn add_change_sink(&mut self, input: NodeId) -> NodeId

Add a change-stream sink: a terminal sink that records the fully-materialized CaughtChange tree of every change pushed to it (nested relationships drained eagerly). Wire it with set_sink_edge; drain per-transaction events with take_sink_changes and get the initial hydration set with try_hydrate_change_sink. Implemented as a Collector with caught-capture enabled, so no new operator variant (and no change to the dispatch/fetch/schema match arms) is required.

Source

pub fn add_filter_start(&mut self, input: NodeId) -> NodeId

A FilterStart over input (the upstream normal Input). Wire its single chain edge with Graph::set_chain_head.

Source

pub fn add_filter_end(&mut self, start: NodeId) -> NodeId

A FilterEnd paired with start. Wire its downstream with Graph::set_output.

Source

pub fn add_fan_out(&mut self, input: NodeId) -> NodeId

A FanOut over input. Wire its branches + paired FanIn with Graph::set_fan.

Source

pub fn add_fan_in(&mut self, fan_out: NodeId) -> NodeId

A FanIn paired with fan_out. Wire its post-fan continuation with Graph::set_output.

Source

pub fn add_union_fan_out(&mut self, input: NodeId) -> NodeId

A UnionFanOut over input (the node-level OR fan-out). Wire its branch broadcast edges + paired UnionFanIn with Graph::set_union_fan.

Source

pub fn add_union_fan_in( &mut self, fan_out: NodeId, inputs: Vec<NodeId>, branch_constraints: Vec<Constraint>, schema: Schema, ) -> NodeId

A UnionFanIn paired with fan_out over the branch tails inputs, carrying the merged branch schema (it owns the output schema; the sort must be defined) and the per-branch pushable constraints (parallel to inputs) the fan-in merges into each branch fetch. Wire its post-fan continuation with Graph::set_output.

Source

pub fn add_filter(&mut self, input: NodeId, pred: CompiledPredicate) -> NodeId

A Filter link over input with predicate pred. Wire its single FilterOutput with Graph::set_output.

Source

pub fn add_filter_probe(&mut self, input: NodeId) -> NodeId

A FilterProbe link over input (proof instrumentation; see the struct).

Source

pub fn set_chain_head(&self, filter_start: NodeId, head: NodeId)

Wire a FilterStart’s single chain edge (#output, the chain head).

Source

pub fn set_fan(&self, fan_out: NodeId, branches: Vec<NodeId>, fan_in: NodeId)

Wire a FanOut’s branch outputs and its paired FanIn.

Source

pub fn set_union_fan( &self, fan_out: NodeId, branches: Vec<OutEdge>, fan_in: NodeId, )

Wire a UnionFanOut’s branch broadcast edges (each branch head + the port to push it on — JoinParent for a flipped branch, Single for a filter branch) and its paired UnionFanIn.

Source

pub fn set_conn_output(&self, conn: NodeId, edge: OutEdge)

Wire a source connection’s output edge (mirrors input.setOutput).

Source

pub fn set_output(&self, op: NodeId, downstream: NodeId)

Wire a single-output operator’s downstream. Covers the join plus every single-FilterOutput chassis link (FilterEnd, FanIn, Filter, FilterProbe). FilterStart uses Graph::set_chain_head and FanOut uses Graph::set_fan — those are not single-output.

Source

pub fn set_sink_edge(&self, upstream: NodeId, sink: NodeId)

Wire the final edge from a built pipeline’s last operator into a terminal sink (a view, change sink, or testkit Catch) or a forwarding testkit Snitch. Routes a SourceConn through Graph::set_conn_output (a bare source → sink pipeline) and any single-output operator — including a transparent tap — through Graph::set_output. Used by the testkit runners after the build closure returns the op feeding the sink.

Source

pub fn set_out_edge(&self, upstream: NodeId, edge: OutEdge)

Wire an upstream operator’s output edge with an explicit port — the port-aware generalization of Graph::set_output (which always wires Port::Single). The builder (08) uses this to chain joins: a SourceConn routes through the source’s Graph::set_conn_output; a Join sets its OutEdge cell directly. The port says how the downstream receives — JoinParent when upstream is the next join’s parent (sibling relationships), JoinChild when it is a nested child top.

Source

pub fn output_port_capable(&self, node: NodeId) -> bool

True iff node can carry a port-bearing OutEdge via Graph::set_out_edge. Covers the port-aware ops (SourceConn/Join/FlippedJoin/Skip/Take/Cap/ Reduce) and the filter-chain / union-fan tails FilterEnd/UnionFanIn, which now carry a port-bearing OutEdge (Gap B) — so a related/sibling relationship join can sit over a where sub-graph (an OR, a nested AND-OR, or a flipped EXISTS). Reduce is here as the top of a relationship-aggregate child subtree (§9). FanIn is excluded: it returns up the filter-chain stack, it is not a downstream-pushing tail.

Source

pub fn wire_single(&self, upstream: NodeId, downstream: NodeId)

Wire a Port::Single forward edge from upstream to downstream, tolerant of a non-port-aware tail. A SourceConn routes through Graph::set_conn_output; every other single-output operator — port-aware ops (via their Single fallback) AND the filter-chain / union-fan tails FilterEnd/FanIn/UnionFanIn — routes through Graph::set_output. Unlike Graph::set_out_edge, this accepts a FilterEnd/UnionFanIn tail, so a Take/Cap (a root or EXISTS-child limit) can sit above a where-subgraph / union-fan end without panicking.

Source

pub fn memory_source(&self, id: NodeId) -> Option<&MemorySource>

The in-memory source behind id, or None if the node is a SourceLeaf::Dyn backend (or not a source). The optimistic fork/rebase loop reaches through this to fork the live primary tree (OPTIMISTIC-WRITES-DESIGN.md §1) — memory sources only, by design: the loop is the wasm client’s, not a SQL backend’s.

Source

pub fn cursors_open(&self, source: NodeId) -> i64

Source

pub fn fetch<'g>( &'g self, id: NodeId, req: &FetchRequest, ) -> Box<dyn Iterator<Item = Node<'g>> + 'g>

Source

pub fn try_fetch_all<'g>( &'g self, id: NodeId, req: &FetchRequest, ) -> Result<Vec<Node<'g>>, RindleError>

Eagerly drain fetch and surface any runtime error a backend parked during the scan. The lazy Graph::fetch API remains infallible for iterator composition; production callers that need error propagation should use this owned-drain boundary.

Source

pub fn set_join_precheck_bounds( &self, per_join: Option<usize>, per_graph: usize, )

Set the join membership pre-check’s bounds (design 311 §2.5 / §8): the per-join distinct-key bound (None = off, the default) and the per-graph key budget. Host-settable on a built &Graph like set_validate_changes.

A change resets every join’s set to Unbuilt (and the tracked total to 0): a set built under a looser bound could be over the new one, and a set left Active while the feature is off would silently go stale (maintenance stops with it) and lie once it is turned back on. Rebuilding happens by observation on the next unconstrained enumeration — never by a fetch of its own — so flipping the knob on a live graph is safe at any time.

Source

pub fn join_precheck_bounds(&self) -> JoinPrecheckBounds

The current pre-check bounds.

Source

pub fn join_precheck_stats(&self) -> JoinPrecheckStats

The per-graph pre-check counters (probe hits/misses, disables by reason).

Source

pub fn join_precheck_tracked_keys(&self) -> usize

Distinct parent keys tracked across every join right now (the live charge against the per_graph budget).

Source

pub fn join_precheck_state(&self, join: NodeId) -> JoinPrecheckState

Inspect one join’s set. # Panics if join is not a live Join node.

Source

pub fn join_precheck_states_of( &self, nodes: &[NodeId], ) -> Vec<JoinPrecheckState>

The pre-check state of every live Join among nodes (a pipeline manifest’s node list), in the order given; non-join and stale ids are skipped. The per-query inspection hook a host with several pipelines on one graph uses (the replica worker’s join_precheck_report). Inspection-only: linear in the graph’s joins per manifest node.

Source

pub fn join_precheck_states(&self) -> Vec<(NodeId, JoinPrecheckState)>

Every live Join node with its pre-check state, in arena order — the inspection hook for a pipeline built by build_pipeline (whose join ids are not handed back).

Source

pub fn source_push(&self, src_id: NodeId, change: SourceChange)

Infallible push (tests / prototyping).

§Panics

On any RindleError (SQLite I/O, a strict consistency violation, …). Prefer try_source_push in production so the error is handled, not aborted (WS02.6 fault model).

Source

pub fn try_source_push( &self, src_id: NodeId, change: SourceChange, ) -> Result<(), RindleError>

Source

pub fn source_push_isolated( &self, src_id: NodeId, change: SourceChange, ) -> Result<(), RindleError>

Server fault boundary (WS02.5): run one mutation under catch_unwind so a residual — unconverted, genuinely-unexpected — panic during this push does not abort the whole process (which, serving many connections, would take them all down). A caught panic becomes a RindleError::Storage("internal panic: …").

Effective only under panic = "unwind" (the release-server profile, D2); under panic = "abort" (the default/wasm client) a panic aborts regardless and this just forwards the result. It is the last-resort net after the WS02.1–02.4 conversions of the expected data-reachable panics — not a substitute for them.

Recovery contract: fail the connection, do not retry in place. A panic mid-mutation can leave operator/view state logically torn (a RefCell is released on unwind — not poisoned, so the graph is still usable, just possibly inconsistent). The owning connection MUST discard and re-hydrate the view from source before serving further reads (WS09.6), never reuse it.

Source

pub fn hydrate(&self, view_id: NodeId)

Build the initial view by draining the input pipeline (#hydrate, array-view.ts:140). The fetch runs here (the Graph borrow stays with the caller); the View folds each node InPlace and flushes once. No RefCell borrow is held across the fetch (the root is taken out inside hydrate_from, after this iterator is constructed). Infallible hydrate (tests / prototyping).

§Panics

On any RindleError from the initial fetch. Prefer try_hydrate in production (WS02.6 fault model).

Source

pub fn try_hydrate(&self, view_id: NodeId) -> Result<(), RindleError>

Source

pub fn flush_view(&self, view_id: NodeId)

Fire the view’s listeners with the current snapshot and close the transaction (flush, array-view.ts:173).

Source

pub fn take_runtime_error(&self) -> Result<(), RindleError>

Source

pub fn view_add_listener(&self, view_id: NodeId, l: Listener) -> usize

Register a flush listener on the view; fires once immediately (addListener, array-view.ts:115). Returns its index.

Source

pub fn view_result_type(&self, view_id: NodeId) -> ResultType

The view’s current ResultType.

Source

pub fn set_view_result_type(&self, view_id: NodeId, rt: ResultType)

Resolve a pending query’s result type (the async queryComplete path, 09 §3.8); fires listeners out of band.

Source

pub fn set_collector_fetch_on_push(&self, id: NodeId, on: bool)

Enable reentrant fetch-during-push capture on a collector.

Source

pub fn collector_changes(&self, id: NodeId) -> Vec<CollectedChange>

The changes a collector has received, in order.

Source

pub fn collector_fetched(&self, id: NodeId) -> Vec<Vec<Row>>

The row-sets captured by reentrant fetch-during-push (one per change).

Source

pub fn take_sink_changes(&self, sink: NodeId) -> Vec<CaughtChange>

Drain (take) the change events a change-sink (see add_change_sink) has accumulated since the last call, in arrival order. The buffer is left empty, so this is the per-transaction delta after a push batch + flush.

Source

pub fn try_hydrate_change_sink( &self, sink: NodeId, ) -> Result<Vec<CaughtChange>, RindleError>

Materialize the pipeline feeding a change-sink as the initial set of CaughtChange::Add events — the hydration snapshot (one Add per top-level node, relationships drained). Does not touch the push buffer. Mirrors Catch.fetch (testkit.rs) without the testkit gate.

Fallible like try_hydrate, and for the same reason: the cold drain is a try_* boundary. A leaf error parked mid-fetch (an unsafe integer, a failed sqlite3_step) ended the stream early, and folding reduce groups during the drain can arm the §5.3 integer-sum overflow state (design 226) — an already-out-of-range set total must surface HERE as the typed error, not register as a success whose aggregate cell is NULL while every later write on the shared graph fails the overflow check. Callers tear the partial pipeline down on Err (the registration error path), which also clears the overflow state the drain armed.

Source

pub fn try_hydrate_change_sink_with( &self, sink: NodeId, req: &FetchRequest, ) -> Result<Vec<CaughtChange>, RindleError>

try_hydrate_change_sink under an explicit FetchRequest — the constrained form a parameterized query family’s per-partition hydrate uses (design 310 §4.4): the request’s constraint reaches the leaf unchanged through the spine (joins forward it to the parent, Skip keeps it, the root Take recognizes it as the partition and hydrates only that partition’s window).

Source

pub fn bind_family_partition( &self, fam: &FamilyPipeline, sink: NodeId, binding: &CanonKey, ) -> Result<Vec<CaughtChange>, RindleError>

Bind one partition of a family (design 310 §4.4 “bind”): add binding to the family’s binding set, then hydrate only that partition — a fetch of the pipeline top constrained on the parameter columns, returned as the partition’s initial Add set (the new subscriber’s snapshot). Existing partitions are untouched. Errors if binding is already bound, or if the hydrate fails (the binding is then rolled back, so the set never names a partition that was not hydrated).

Source

pub fn unbind_family_partition( &self, fam: &FamilyPipeline, sink: NodeId, binding: &CanonKey, ) -> Result<(), RindleError>

Unbind one partition of a family (design 310 §4.4 “unbind”, made concrete by impl plan D5 — a synthetic drain, not a slot delete). In order:

  1. fetch the partition’s current view rows through the pipeline top (bounded by the root limiter) while it is still bound;
  2. drop it from the binding set — the root connection now rejects the partition;
  3. inject Change::Remove for each row at the spine tail’s output edge, above the root limiter and the gates the rows already passed, so every related join runs its ordinary parent-left cleanup (child limiter partitions, pre-check membership) and nothing is refilled from a connection that would now reject it; the sink’s caught output for these is discarded;
  4. evict the spine EXISTS joins’ per-parent child partitions for those rows (the synthetic removes entered above them);
  5. evict the root Take’s partition slot (it kept a size-0 slot, impl plan D4).

Nothing is emitted to surviving partitions. Cost O(partition rows) — the same order a singleton’s teardown pays.

Source

pub fn hydrate_family( &self, fam: &FamilyPipeline, sink: NodeId, ) -> Result<Vec<CaughtChange>, RindleError>

Every bound partition’s rows, concatenated in binding order — the family form of a change-sink hydrate (read_snapshot).

Source

pub fn push_at<'g>(&'g self, id: NodeId, change: Change<'g>, port: Port)

Test/proof entry: inject a change at id (e.g. a FilterStart) exactly as a SourceConn’s output edge would deliver it. Drives the filter sub-graph in isolation; the full source push path is covered by the source tests.

Source

pub fn probe_counts(&self, id: NodeId) -> (usize, usize, usize)

(begin_filter, filter, end_filter) call counts recorded by a FilterProbe — lets a test assert the lifecycle fired, and balanced.

Source

pub fn view_data(&self, view_id: NodeId) -> ViewData

The view’s current top-level result snapshot (the data getter). A cheap Arc clone of the materialized tree. With the testkit feature, testkit::view_data_to_caught converts it to a comparable crate::CaughtNode tree.

Source

pub fn dump_view(&self, view_id: NodeId) -> Vec<(i64, Vec<i64>)>

Test/inspection helper: [(pk_id, [child_pk_id, ...]), ...] using column 0. Children are flattened across all relationship slots in slot order (the production View’s dump_col0).

Source

pub fn dump_view_deep(&self, view_id: NodeId) -> Vec<Col0Node>

Recursive col-0 dump (the deep counterpart of Graph::dump_view): surfaces grandchildren so a nested relationship (issue{comments{reactions}}) is fully observable. See crate::view::View::dump_col0_deep.

Source

pub fn dump_view_rows(&self, view_id: NodeId) -> Vec<(Vec<i64>, Vec<Vec<i64>>)>

Test helper: each top row’s FULL columns (as i64) + its children’s full columns. Unlike Graph::dump_view (column-0 ids only) this surfaces edited non-key columns, so an edit’s value change is observable. Assumes all columns are Int.

Trait Implementations§

Source§

impl Default for Graph

Source§

fn default() -> Graph

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl !Freeze for Graph

§

impl !RefUnwindSafe for Graph

§

impl !Send for Graph

§

impl !Sync for Graph

§

impl Unpin for Graph

§

impl UnsafeUnpin for Graph

§

impl !UnwindSafe for Graph

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.