pub enum SqlPlan {
Show 44 variants
ConstantResult {
columns: Vec<String>,
values: Vec<SqlValue>,
},
Scan {
collection: String,
alias: Option<String>,
engine: EngineType,
filters: Vec<Filter>,
projection: Vec<Projection>,
sort_keys: Vec<SortKey>,
limit: Option<usize>,
offset: usize,
distinct: bool,
window_functions: Vec<WindowSpec>,
temporal: TemporalScope,
},
PointGet {
collection: String,
alias: Option<String>,
engine: EngineType,
key_column: String,
key_value: SqlValue,
},
DocumentIndexLookup {Show 14 fields
collection: String,
alias: Option<String>,
engine: EngineType,
field: String,
value: SqlValue,
filters: Vec<Filter>,
projection: Vec<Projection>,
sort_keys: Vec<SortKey>,
limit: Option<usize>,
offset: usize,
distinct: bool,
window_functions: Vec<WindowSpec>,
case_insensitive: bool,
temporal: TemporalScope,
},
RangeScan {
collection: String,
field: String,
lower: Option<SqlValue>,
upper: Option<SqlValue>,
limit: usize,
},
Insert {
collection: String,
engine: EngineType,
rows: Vec<Vec<(String, SqlValue)>>,
column_defaults: Vec<(String, String)>,
if_absent: bool,
},
KvInsert {
collection: String,
entries: Vec<(SqlValue, Vec<(String, SqlValue)>)>,
ttl_secs: u64,
intent: KvInsertIntent,
on_conflict_updates: Vec<(String, SqlExpr)>,
},
Upsert {
collection: String,
engine: EngineType,
rows: Vec<Vec<(String, SqlValue)>>,
column_defaults: Vec<(String, String)>,
on_conflict_updates: Vec<(String, SqlExpr)>,
},
InsertSelect {
target: String,
source: Box<SqlPlan>,
limit: usize,
},
Update {
collection: String,
engine: EngineType,
assignments: Vec<(String, SqlExpr)>,
filters: Vec<Filter>,
target_keys: Vec<SqlValue>,
returning: bool,
},
UpdateFrom {
collection: String,
engine: EngineType,
source: Box<SqlPlan>,
target_join_col: String,
source_join_col: String,
assignments: Vec<(String, SqlExpr)>,
target_filters: Vec<Filter>,
returning: bool,
},
Delete {
collection: String,
engine: EngineType,
filters: Vec<Filter>,
target_keys: Vec<SqlValue>,
},
Truncate {
collection: String,
restart_identity: bool,
},
Join {
left: Box<SqlPlan>,
right: Box<SqlPlan>,
on: Vec<(String, String)>,
join_type: JoinType,
condition: Option<SqlExpr>,
limit: usize,
projection: Vec<Projection>,
filters: Vec<Filter>,
},
Aggregate {
input: Box<SqlPlan>,
group_by: Vec<SqlExpr>,
aggregates: Vec<AggregateExpr>,
having: Vec<Filter>,
limit: usize,
grouping_sets: Option<Vec<Vec<usize>>>,
sort_keys: Vec<SortKey>,
},
TimeseriesScan {
collection: String,
time_range: (i64, i64),
bucket_interval_ms: i64,
group_by: Vec<String>,
aggregates: Vec<AggregateExpr>,
filters: Vec<Filter>,
projection: Vec<Projection>,
gap_fill: String,
limit: usize,
tiered: bool,
temporal: TemporalScope,
},
TimeseriesIngest {
collection: String,
rows: Vec<Vec<(String, SqlValue)>>,
},
VectorSearch {
collection: String,
field: String,
query_vector: Vec<f32>,
top_k: usize,
ef_search: usize,
metric: DistanceMetric,
filters: Vec<Filter>,
array_prefilter: Option<ArrayPrefilter>,
ann_options: VectorAnnOptions,
skip_payload_fetch: bool,
payload_filters: Vec<SqlPayloadAtom>,
},
MultiVectorSearch {
collection: String,
query_vector: Vec<f32>,
top_k: usize,
ef_search: usize,
},
TextSearch {
collection: String,
query: FtsQuery,
top_k: usize,
filters: Vec<Filter>,
score_alias: Option<String>,
},
HybridSearch {
collection: String,
query_vector: Vec<f32>,
query_text: String,
top_k: usize,
ef_search: usize,
vector_weight: f32,
fuzzy: bool,
score_alias: Option<String>,
},
HybridSearchTriple {
collection: String,
query_vector: Vec<f32>,
query_text: String,
graph_seed_id: String,
graph_depth: usize,
graph_edge_label: Option<String>,
top_k: usize,
ef_search: usize,
fuzzy: bool,
rrf_k: (f64, f64, f64),
score_alias: Option<String>,
},
SpatialScan {
collection: String,
field: String,
predicate: SpatialPredicate,
query_geometry: Geometry,
distance_meters: f64,
attribute_filters: Vec<Filter>,
limit: usize,
projection: Vec<Projection>,
},
Union {
inputs: Vec<SqlPlan>,
distinct: bool,
},
Intersect {
left: Box<SqlPlan>,
right: Box<SqlPlan>,
all: bool,
},
Except {
left: Box<SqlPlan>,
right: Box<SqlPlan>,
all: bool,
},
RecursiveScan {
collection: String,
base_filters: Vec<Filter>,
recursive_filters: Vec<Filter>,
join_link: Option<(String, String)>,
max_iterations: usize,
distinct: bool,
limit: usize,
},
RecursiveValue {
cte_name: String,
columns: Vec<String>,
init_exprs: Vec<String>,
step_exprs: Vec<String>,
condition: Option<String>,
max_depth: usize,
distinct: bool,
},
Cte {
definitions: Vec<(String, SqlPlan)>,
outer: Box<SqlPlan>,
},
CreateArray {
name: String,
dims: Vec<ArrayDimAst>,
attrs: Vec<ArrayAttrAst>,
tile_extents: Vec<i64>,
cell_order: ArrayCellOrderAst,
tile_order: ArrayTileOrderAst,
prefix_bits: u8,
audit_retain_ms: Option<u64>,
minimum_audit_retain_ms: Option<u64>,
},
DropArray {
name: String,
if_exists: bool,
},
AlterArray {
name: String,
audit_retain_ms: Option<Option<i64>>,
minimum_audit_retain_ms: Option<u64>,
},
InsertArray {
name: String,
rows: Vec<ArrayInsertRow>,
},
DeleteArray {
name: String,
coords: Vec<Vec<ArrayCoordLiteral>>,
},
ArraySlice {
name: String,
slice: ArraySliceAst,
attr_projection: Vec<String>,
limit: u32,
temporal: TemporalScope,
},
ArrayProject {
name: String,
attr_projection: Vec<String>,
},
ArrayAgg {
name: String,
attr: String,
reducer: ArrayReducerAst,
group_by_dim: Option<String>,
temporal: TemporalScope,
},
ArrayElementwise {
left: String,
right: String,
op: ArrayBinaryOpAst,
attr: String,
},
ArrayFlush {
name: String,
},
ArrayCompact {
name: String,
},
Merge {
target: String,
engine: EngineType,
source: Box<SqlPlan>,
target_join_col: String,
source_join_col: String,
source_alias: String,
clauses: Vec<MergePlanClause>,
returning: bool,
},
LateralTopK {
outer: Box<SqlPlan>,
outer_alias: Option<String>,
inner_collection: String,
inner_filters: Vec<Filter>,
inner_order_by: Vec<SortKey>,
inner_limit: usize,
correlation_keys: Vec<(String, String)>,
lateral_alias: String,
projection: Vec<Projection>,
left_join: bool,
},
LateralLoop {
outer: Box<SqlPlan>,
outer_alias: Option<String>,
inner: Box<SqlPlan>,
correlation_predicates: Vec<(String, String)>,
lateral_alias: String,
projection: Vec<Projection>,
outer_row_cap: usize,
left_join: bool,
},
VectorPrimaryInsert {
collection: String,
field: String,
quantization: VectorQuantization,
payload_indexes: Vec<(String, PayloadIndexKind)>,
rows: Vec<VectorPrimaryRow>,
},
}Expand description
The top-level plan produced by the SQL planner.
Variants§
ConstantResult
Query with no FROM clause: SELECT 1, SELECT ‘hello’ AS name, etc. Produces a single row with evaluated constant expressions.
Scan
Fields
engine: EngineTypeprojection: Vec<Projection>window_functions: Vec<WindowSpec>temporal: TemporalScopeBitemporal qualifier extracted from FOR SYSTEM_TIME /
FOR VALID_TIME. Default when the scan is current-state.
PointGet
Fields
engine: EngineTypeDocumentIndexLookup
Document fetch via a secondary index: equality predicate on an indexed field. The executor performs an index lookup to resolve matching document IDs, reads each document, and applies any remaining filters, projection, sort, and limit.
Emitted by document_schemaless::plan_scan /
document_strict::plan_scan when the WHERE clause contains a
single equality predicate on a Ready indexed field. Any
additional predicates fall through as post-filters.
Fields
engine: EngineTypeprojection: Vec<Projection>window_functions: Vec<WindowSpec>case_insensitive: boolWhether the chosen index is COLLATE NOCASE — the executor lowercases the lookup value before probing.
temporal: TemporalScopeBitemporal qualifier — mirrors Scan::temporal. Document
engines must honor it at the Ceiling stage.
RangeScan
Fields
Insert
Fields
engine: EngineTypeKvInsert
KV INSERT: key and value are fundamentally separate.
Each entry is (key, value_columns).
Fields
intent: KvInsertIntentINSERT-vs-UPSERT distinction. KvOp::Put is a Redis-SET-style
upsert by design; to honor SQL INSERT semantics the planner must
tell the converter whether a duplicate key should raise (plain
INSERT, Insert), be silently skipped (ON CONFLICT DO NOTHING,
InsertIfAbsent), or overwrite (UPSERT / ON CONFLICT DO UPDATE, Put).
Upsert
UPSERT: insert or merge if document exists.
Fields
engine: EngineTypeInsertSelect
Update
Fields
engine: EngineTypeUpdateFrom
UPDATE target SET col = src.col2 FROM src WHERE target.id = src.id
Two-phase execution: scan source with source_filters, then for
each matched source row that satisfies the join predicates against a
target row, apply assignments (which may reference source columns
via qualified names src.col).
join_predicates are equality pairs (target_col, source_col) extracted
from the WHERE clause linking the two tables. target_filters are
remaining WHERE predicates that reference only target.
Fields
engine: EngineTypeDelete
Truncate
Join
Fields
projection: Vec<Projection>Post-join projection: column names to keep (empty = all columns).
Aggregate
Fields
aggregates: Vec<AggregateExpr>grouping_sets: Option<Vec<Vec<usize>>>When the GROUP BY contains ROLLUP/CUBE/GROUPING SETS, this field holds
the expansion. Each inner Vec<usize> is one grouping set — the indices
into group_by (the canonical key list) that are present (non-NULL)
for rows in that set. None = plain single-set GROUP BY.
TimeseriesScan
Fields
aggregates: Vec<AggregateExpr>projection: Vec<Projection>temporal: TemporalScopeBitemporal system-time / valid-time scope. Only non-default
on collections created WITH BITEMPORAL; TimeseriesRules::plan_scan
rejects temporal scopes otherwise.
TimeseriesIngest
VectorSearch
Fields
metric: DistanceMetricDistance metric requested by the query operator (<->, <=>, <#>).
Overrides the collection-default metric at search time.
array_prefilter: Option<ArrayPrefilter>Optional cross-engine prefilter: when set, the ND-array slice
runs first and its output cells’ surrogates form a bitmap that
gates the HNSW candidate set. Set by the planner when an
ORDER BY vector_distance(...) LIMIT k query is JOINed against
ARRAY_SLICE(...). The convert layer lowers this to
VectorOp::Search { inline_prefilter_plan: Some(ArrayOp::SurrogateBitmapScan) }.
ann_options: VectorAnnOptionsANN knobs parsed from the optional third JSON-string argument
to vector_distance(field, query, '{...}').
skip_payload_fetch: boolWhen true, the projection contains only the surrogate/PK column
and/or vector_distance(...) — no payload fields. The Data Plane
can skip the document-body fetch entirely for vector-primary
collections. Always false for non-vector-primary collections
(document body is the primary result).
payload_filters: Vec<SqlPayloadAtom>Predicates against payload-indexed columns on a vector-primary
collection. Each atom is Eq(field, value), In(field, values),
or Range(field, ...). The convert layer translates SqlValue →
nodedb_types::Value and emits them as
VectorOp::Search::payload_filters. The Data Plane intersects
the resulting bitmap with the HNSW candidate set via the
per-collection PayloadIndexSet::pre_filter.
MultiVectorSearch
TextSearch
Fields
query: FtsQueryStructured FTS query. Use FtsQuery::Plain { text, fuzzy } for
simple keyword search. FtsQuery::And/Or/Prefix are supported;
FtsQuery::Phrase and FtsQuery::Not are represented but rejected
by the executor with Unsupported.
score_alias: Option<String>When set, the SELECT list contains bm25_score(field, term) and the
caller wants a full-collection scan with the score injected under this
alias. The converter emits TextOp::BM25ScoreScan instead of
TextOp::Search so that all documents — including non-matching ones —
appear in the response with null for the score when they do not
contain the term.
HybridSearch
Fields
HybridSearchTriple
Three-source hybrid search: vector + BM25 text + graph BFS, fused via weighted RRF.
Produced when the planner detects rrf_score(vector_distance(...), bm25_score(...), graph_score(...)) with three source arguments.
Fields
SpatialScan
Union
Intersect
Except
RecursiveScan
Fields
RecursiveValue
Value-generating recursive CTE (WITH RECURSIVE name(cols) AS (anchor UNION [ALL] step)).
Unlike RecursiveScan, this variant carries no collection reference — the anchor
row is produced entirely from literal expressions and each iteration applies the
step expressions to the previous row. The executor evaluates this iteratively
in the Data Plane without touching storage.
All expressions are stored as raw SQL text so they can be serialised across the
SPSC bridge without requiring SqlExpr to implement Serialize. The executor
parses them at execution time via the same lightweight expression evaluator used
by the procedural executor.
Fields
step_exprs: Vec<String>Recursive step SELECT expressions as raw SQL text (one per column).
May reference column names from columns.
Cte
Non-recursive CTE: execute each definition, then the outer query.
Fields
CreateArray
CREATE ARRAY <name> DIMS (...) ATTRS (...) TILE_EXTENTS (...).
AST is engine-agnostic — the Origin converter builds the typed
nodedb_array::ArraySchema and persists the catalog row.
Fields
dims: Vec<ArrayDimAst>attrs: Vec<ArrayAttrAst>cell_order: ArrayCellOrderAsttile_order: ArrayTileOrderAstDropArray
DROP ARRAY [IF EXISTS] <name> — pure Control-Plane catalog
mutation. Per-core array store cleanup happens lazily.
AlterArray
ALTER ARRAY <name> SET (audit_retain_ms = N, ...).
Double-Option semantics for each diff field:
None= key was absent from SET clause → field unchanged.Some(None)= key present with valueNULL→ field set to NULL.Some(Some(v))= key present with integer value → field set to v.
Fields
InsertArray
INSERT INTO ARRAY <name> COORDS (...) VALUES (...) [, ...].
DeleteArray
DELETE FROM ARRAY <name> WHERE COORDS IN ((...), (...)).
ArraySlice
SELECT * FROM ARRAY_SLICE(name, {dim:[lo,hi],..}, [attrs], limit).
Fields
slice: ArraySliceAsttemporal: TemporalScopeBitemporal qualifier. When both axes are None / Any, the Data
Plane returns the live (current) state — the default fast path.
Populated from AS OF SYSTEM TIME / AS OF VALID TIME clauses.
ArrayProject
SELECT * FROM ARRAY_PROJECT(name, [attrs]).
ArrayAgg
SELECT * FROM ARRAY_AGG(name, attr, reducer [, group_by_dim]).
Fields
reducer: ArrayReducerAsttemporal: TemporalScopeBitemporal qualifier. When both axes are None / Any, the Data
Plane aggregates against the live (current) state — the default
fast path. Populated from AS OF SYSTEM TIME / AS OF VALID TIME.
ArrayElementwise
SELECT * FROM ARRAY_ELEMENTWISE(left, right, op, attr).
ArrayFlush
SELECT ARRAY_FLUSH(name) — returns one row {result: BOOL}.
ArrayCompact
SELECT ARRAY_COMPACT(name) — returns one row {result: BOOL}.
Merge
MERGE INTO target USING source ON ... WHEN ... THEN ...
Supported only for document_schemaless and document_strict engines.
The Data Plane handler evaluates WHEN arms in declaration order and
applies the first matching action to each joined or unmatched row.
LateralTopK
LATERAL subquery that is equi-correlated and has ORDER BY + LIMIT k.
Emitted when the inner subquery has an equi-key correlation to the outer
table plus an ORDER BY ... LIMIT k clause. The Data Plane scans the
inner collection once per outer row applying the equi-filter, sorts by
inner_order_by, and retains at most inner_limit rows.
correlation_keys is (outer_col, inner_col) — the equi-join pairs
that correlate inner to outer.
Fields
projection: Vec<Projection>Post-lateral projection.
LateralLoop
General LATERAL subquery — per-outer-row correlated nested loop.
Emitted for LATERAL subqueries that cannot be rewritten as equi-join
hash joins or LateralTopK. The Control Plane drives execution: it
materialises outer rows, then for each row substitutes the correlation
values as additional filters on the inner plan and re-dispatches it.
Bounded by outer_row_cap; queries that exceed the cap receive a typed
SqlError::Unsupported before any data is returned.
Fields
correlation_predicates: Vec<(String, String)>Correlated predicates extracted from the inner WHERE that reference
outer columns. Each entry is (inner_field, outer_field).
projection: Vec<Projection>Post-lateral projection.
VectorPrimaryInsert
INSERT into a vector-primary collection.
Emitted by the planner instead of the generic Insert variant when the
target collection has primary = PrimaryEngine::Vector. The Data Plane
routes each row through VectorOp::DirectUpsert, bypassing full-document
MessagePack encoding.
Fields
field: StringVector column name (matches VectorPrimaryConfig::vector_field).
Plumbed to VectorOp::DirectUpsert so the Data Plane keys its
HNSW index by (tid, collection, field) — the same key the SELECT
path uses.
quantization: VectorQuantizationCollection-level quantization. Applied via set_quantization on
the first DirectUpsert so subsequent seals trigger codec-dispatch
rebuilds against the configured codec.
payload_indexes: Vec<(String, PayloadIndexKind)>Payload field names that get equality bitmap indexes. Registered
via payload.add_index on the first DirectUpsert.
rows: Vec<VectorPrimaryRow>Trait Implementations§
Auto Trait Implementations§
impl Freeze for SqlPlan
impl RefUnwindSafe for SqlPlan
impl Send for SqlPlan
impl Sync for SqlPlan
impl Unpin for SqlPlan
impl UnsafeUnpin for SqlPlan
impl UnwindSafe for SqlPlan
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.