pub struct Take {
pub input: NodeId,
pub storage: StorageId,
pub limit: u32,
pub partition_key: Option<Vec<ColId>>,
pub output: Cell<Option<OutEdge>>,
pub sort: Sort,
pub retain_empty_partitions: bool,
/* private fields */
}Expand description
Take: ordered, bounded top-N per partition, backed by a StorageId slot.
Fields§
§input: NodeIdUpstream input (the connection, a Skip, or — once EXISTS lands — a join).
storage: StorageIdHandle into the Graph storage arena holding this op’s per-partition
TakeState (under encode_state_key("take", …)) + the MAX_BOUND row.
limit: u32The LIMIT count. 0 ⇒ the operator yields nothing and stores no state.
partition_key: Option<Vec<ColId>>The partition columns (the correlation child field of a limited
relationship), or None for a top-level limit (a single global partition).
output: Cell<Option<OutEdge>>The single downstream edge as a port-carrying OutEdge (like
Skip/Join): Port::Single to a
terminal sink, Port::JoinParent when this Take feeds a relationship join’s
parent port (a limited relationship). Wired via
Graph::set_output (Single) or
Graph::set_out_edge (explicit port).
sort: SortThe input sort, resolved at build time (the connection’s completed,
PK-including order). Take requires sorted input (take.ts:74); the
comparator only ever reads these columns.
retain_empty_partitions: boolKeep a partition’s slot when it drains to empty (design 310, impl plan D4). A
partitioned child Take deletes the slot, because its parent join’s constrained
fetch re-hydrates it when the parent re-enters; a family root Take has no
parent, so after such a delete the next Add for a still-bound value would find
get_state == None and be dropped — a silent missing row for that binding. Set
only by the family builder; the slot is then deleted by Take::evict_partition
at unbind. The top-level unpartitioned branch already keeps size-0 state for the
same reason; this flag extends that rule to root partitions.
Implementations§
Source§impl Take
impl Take
pub fn new( input: NodeId, storage: StorageId, limit: u32, partition_key: Option<Vec<ColId>>, sort: Sort, ) -> Take
Sourcepub fn with_retain_empty_partitions(self, on: bool) -> Take
pub fn with_retain_empty_partitions(self, on: bool) -> Take
Builder: keep drained-to-empty partition slots (see
Take::retain_empty_partitions). The family root limiter sets this.
Sourcepub fn fetch<'g>(
&'g self,
g: &'g Graph,
req: &FetchRequest,
) -> Box<dyn Iterator<Item = Node<'g>> + 'g>
pub fn fetch<'g>( &'g self, g: &'g Graph, req: &FetchRequest, ) -> Box<dyn Iterator<Item = Node<'g>> + 'g>
Lazy pull (take.ts:93). Two regimes:
- No partition key, or the request constraint matches the partition key:
bound by that single partition’s
TakeState(hydrating it on first sight). - Partitioned but the constraint is absent / on a different key (nested
subqueries): bound by
MAX_BOUND, re-checking each row against its own partition’s bound.
Sourcepub fn evict_partition(&self, g: &Graph, constraint: &Constraint)
pub fn evict_partition(&self, g: &Graph, constraint: &Constraint)
Delete the per-partition slot identified by constraint (the parent→child
correlation key), if this Take is partitioned and the constraint covers its
partition key. Called by the relationship join when a parent leaves a bounded
parent view (a parent Remove on Port::JoinParent): the child partition that
parent hydrated is no longer referenced by any result row, but — unlike the
drain-to-empty case in push_remove — its child rows are still live in the
window, so nothing else ever deletes the slot. Without this, a partitioned child
Take accumulates one zombie slot per distinct parent that ever floated through
the bounded view (e.g. every page that hit the wiki demo’s “latest” board as the
last_ts ordering churns), leaking operator state proportional to the retention
window rather than the (bounded) view.
Safe — and symmetric with the drain-time delete — because a partitioned Take is
re-hydrated from source by the parent join’s constrained fetch when its parent
re-enters (Take::fetch’s no-state → initial_fetch), and a push to an
un-hydrated partition is already dropped (get_state == None). The caller only
invokes this when the parent correlation key is unique (the parent’s primary key),
so the evicted slot belongs to exactly the one parent that left. No-op for an
unpartitioned (top-level) Take or a constraint that does not cover the partition
key.
Sourcepub fn push<'g>(&'g self, g: &'g Graph, change: Change<'g>)
pub fn push<'g>(&'g self, g: &'g Graph, change: Change<'g>)
Eager push (take.ts:247). Edit routes to Take::push_edit; otherwise
look up the partition’s state (drop the change if it was never hydrated) and
dispatch Add / Remove / Child. Forwards on the edge’s own port so a limited
relationship can feed a parent join.