linkrs_query/executor/streaming/operators/spec/unary.rs
1//! Immutable configuration for unary (one-input) operators.
2
3use linkrs_core::types::expr::Expression;
4use linkrs_core::DataType;
5
6/// Immutable config for unary (one-input) operators.
7#[derive(Debug, Clone)]
8pub enum UnarySpec {
9 Filter {
10 predicate: Expression,
11 /// Expression-level subqueries compiled for this filter;
12 /// the materializer turns them into a per-operator `SubqueryExecutor`.
13 subquery_runners: Vec<crate::executor::streaming::subquery::SubqueryRunnerSpec>,
14 },
15 Project {
16 output_expressions: Vec<Expression>,
17 output_col_names: Vec<String>,
18 /// Resolved per-column types from the planner (`ProjectNode.column_types`).
19 /// May be empty for hand-built plans; layouts fall back to untyped slots.
20 output_col_types: Vec<DataType>,
21 /// Expression-level subqueries compiled for this project.
22 subquery_runners: Vec<crate::executor::streaming::subquery::SubqueryRunnerSpec>,
23 },
24 Limit {
25 offset: u32,
26 limit: u32,
27 },
28 Assign {
29 assignments: Vec<(String, Expression)>,
30 /// Expression-level subqueries compiled for this assign.
31 subquery_runners: Vec<crate::executor::streaming::subquery::SubqueryRunnerSpec>,
32 },
33 Unwind {
34 unwind_column: String,
35 list_expression: Option<Expression>,
36 },
37 /// Storage-backed vertex property append.
38 ///
39 /// Evaluates `entity_expr` per input row to resolve the vertex id, reads
40 /// the vertex (full or projected) from storage, and appends the property
41 /// columns to the row. With a non-empty `prop_names` the appended
42 /// columns are the flat `{entity_var}.{prop}` names; with an empty list
43 /// the whole `Value::Vertex` is appended under `entity_var`.
44 AppendVertices {
45 /// Space the vertex is read from.
46 space_name: String,
47 /// Single tag for forced single-label fetch.
48 tag: String,
49 /// Binding variable of the appended vertex (flat-column prefix).
50 entity_var: String,
51 /// Expression resolved per row to the vertex id.
52 entity_expr: Expression,
53 /// Property names to read; empty reads the full vertex.
54 prop_names: Vec<String>,
55 },
56 Sample {
57 count: u64,
58 },
59 Flatten {
60 group_pos: u32,
61 /// Alias names of the flattened group snapshotted at rewrite time.
62 ///
63 /// Traceability metadata only; the executor never validates these
64 /// names because the schema alias namespace and the runtime
65 /// column namespace are not identical.
66 group_columns: Vec<String>,
67 /// Group count of the child schema at rewrite time, when known.
68 ///
69 /// The executor rejects a stale `group_pos` (`group_pos` must be
70 /// below this count) loudly at `open()`. `None` means unknown
71 /// (hand-built or legacy plan) and skips the check honestly.
72 expected_groups: Option<u32>,
73 },
74}
75
76impl UnarySpec {
77 /// Expression-level subquery runner specs of this operator (empty for
78 /// kinds that do not host subqueries). The materializer instantiates a
79 /// per-operator `SubqueryExecutor` from these.
80 pub fn subquery_runners(&self) -> &[crate::executor::streaming::subquery::SubqueryRunnerSpec] {
81 match self {
82 Self::Filter {
83 subquery_runners, ..
84 }
85 | Self::Project {
86 subquery_runners, ..
87 }
88 | Self::Assign {
89 subquery_runners, ..
90 } => subquery_runners,
91 _ => &[],
92 }
93 }
94}