The with Clause
with { ... } attaches an options block to the construct directly before it: a create statement, a column definition, or a pipeline operator. It is not an operator itself - it never stands alone as a pipeline step. The keys inside the braces belong to whatever the clause is attached to, and each construct accepts a fixed set of them.
Where with appears
- --Create statements. After the column block of a table, ring buffer, series, or view: storage options like
capacityorkey, row settings, and partitioning. - --Column definitions. After a column's type:
auto_incrementanddictionary. - --Pipeline operators. At the end of join, distinct, and window: state lifetime and behavior options for the engine that keeps views up to date.
Storage options at creation
Each storage shape has its own keys. A ring buffer declares its capacity; a series declares its key column and optionally precision and tag. Views place the clause between the column block and as - a ring-buffer-backed view takes capacity, a series-backed view takes precision. Unknown keys are rejected, so a typo fails at parse time instead of being silently ignored:
Here the clause is the whole reason the shape works: two rows of capacity, so the third insert evicts the first. See ring buffers for partitioning with partition.
Row settings
Tables, ring buffers, series, and views all accept a row block that controls the lifetime of their rows: ttl with a duration such as '30m' or '30d' and an optional mode (drop or delete), plus persistent: false for rows that live in memory only. A non-persistent shape must also declare a TTL - rows that never reach disk have to expire.
The full expiry semantics - what anchors the clock, what each mode means for views and subscriptions - are covered on the TTL page.
Column options
A with block after a column's type configures that column. auto_increment makes the engine fill the column from a sequence when an insert omits it; dictionary: ns::dict stores the column dictionary-encoded through a dictionary:
Operator options
On pipeline operators, with configures the state the flow engine keeps when the pipeline runs inside a view. join accepts three keys: snapshot: true turns the joined-in side into a passive lookup - right-side changes update the join's state but emit no revisions to rows already joined; latest: true keeps only the newest right-side row per key instead of every match; and ttl: { left: { duration: '1h' } } (and/or right) evicts join state that has not been touched within the duration.
distinct takes a ttl the same way: an entry the operator has not seen within the duration is evicted, so the value counts as new when it next appears.
These options exist for incremental view maintenance. An ad-hoc query like the ones above accepts them, but since it computes its result in one shot, there is no long-lived state for them to manage. window is configured the same way (with { interval: '5s' }) and only runs inside deferred views; newer engine builds also accept with { ttl: ... } on apply, though the sandbox build on this site does not.
Keys are validated
The with block is not a free-form bag of settings. Every construct checks the keys it is given - a table accepts row and partition and nothing else:
