Skip to main content

reifydb_rql/
nodes.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_catalog::catalog::{
5	ringbuffer::RingBufferColumnToCreate, subscription::SubscriptionColumnToCreate, table::TableColumnToCreate,
6	view::ViewColumnToCreate,
7};
8use reifydb_core::{
9	common::{JoinType, WindowSize, WindowSlide, WindowType},
10	interface::{
11		catalog::namespace::NamespaceDef,
12		resolved::{
13			ResolvedColumn, ResolvedDictionary, ResolvedFlow, ResolvedNamespace, ResolvedPrimitive,
14			ResolvedRingBuffer, ResolvedSequence, ResolvedTable, ResolvedTableVirtual, ResolvedView,
15		},
16	},
17	sort::{SortDirection, SortKey},
18};
19use reifydb_type::{
20	fragment::Fragment,
21	value::{constraint::TypeConstraint, r#type::Type},
22};
23
24use crate::{
25	expression::{AliasExpression, Expression, VariableExpression},
26	query::QueryPlan,
27};
28
29/// Owned primary key definition for physical plan nodes (materialized from bump-allocated logical plan)
30#[derive(Debug, Clone)]
31pub struct PrimaryKeyDef {
32	pub columns: Vec<PrimaryKeyColumn>,
33}
34
35/// Owned primary key column for physical plan nodes
36#[derive(Debug, Clone)]
37pub struct PrimaryKeyColumn {
38	pub column: Fragment,
39	pub order: Option<SortDirection>,
40}
41
42#[derive(Debug, Clone)]
43pub enum PhysicalPlan {
44	CreateDeferredView(CreateDeferredViewNode),
45	CreateTransactionalView(CreateTransactionalViewNode),
46	CreateNamespace(CreateNamespaceNode),
47	CreateTable(CreateTableNode),
48	CreateRingBuffer(CreateRingBufferNode),
49	CreateFlow(CreateFlowNode),
50	CreateDictionary(CreateDictionaryNode),
51	CreateSumType(CreateSumTypeNode),
52	CreateSubscription(CreateSubscriptionNode),
53	// Alter
54	AlterSequence(AlterSequenceNode),
55	AlterTable(AlterTableNode),
56	AlterView(AlterViewNode),
57	AlterFlow(AlterFlowNode),
58	// Mutate
59	Delete(DeleteTableNode),
60	DeleteRingBuffer(DeleteRingBufferNode),
61	InsertTable(InsertTableNode),
62	InsertRingBuffer(InsertRingBufferNode),
63	InsertDictionary(InsertDictionaryNode),
64	Update(UpdateTableNode),
65	UpdateRingBuffer(UpdateRingBufferNode),
66	// Variable assignment
67	Declare(DeclareNode),
68	Assign(AssignNode),
69	Append(AppendPhysicalNode),
70	// Variable resolution
71	Variable(VariableNode),
72	Environment(EnvironmentNode),
73	// Control flow
74	Conditional(ConditionalNode),
75	Loop(LoopPhysicalNode),
76	While(WhilePhysicalNode),
77	For(ForPhysicalNode),
78	Break,
79	Continue,
80	// User-defined functions
81	DefineFunction(DefineFunctionNode),
82	Return(ReturnNode),
83	CallFunction(CallFunctionNode),
84
85	// Query
86	Aggregate(AggregateNode),
87	Distinct(DistinctNode),
88	Filter(FilterNode),
89	IndexScan(IndexScanNode),
90	// Row-number optimized access
91	RowPointLookup(RowPointLookupNode),
92	RowListLookup(RowListLookupNode),
93	RowRangeScan(RowRangeScanNode),
94	JoinInner(JoinInnerNode),
95	JoinLeft(JoinLeftNode),
96	JoinNatural(JoinNaturalNode),
97	Take(TakeNode),
98	Sort(SortNode),
99	Map(MapNode),
100	Extend(ExtendNode),
101	Patch(PatchNode),
102	Apply(ApplyNode),
103	InlineData(InlineDataNode),
104	TableScan(TableScanNode),
105	TableVirtualScan(TableVirtualScanNode),
106	ViewScan(ViewScanNode),
107	RingBufferScan(RingBufferScanNode),
108	FlowScan(FlowScanNode),
109	DictionaryScan(DictionaryScanNode),
110	Generator(GeneratorNode),
111	Window(WindowNode),
112	// Auto-scalarization for 1x1 frames
113	Scalarize(ScalarizeNode),
114}
115
116#[derive(Debug, Clone)]
117pub struct CreateDeferredViewNode {
118	pub namespace: NamespaceDef, // FIXME REsolvedNamespace
119	pub view: Fragment,
120	pub if_not_exists: bool,
121	pub columns: Vec<ViewColumnToCreate>,
122	pub as_clause: Box<QueryPlan>,
123	pub primary_key: Option<PrimaryKeyDef>,
124}
125
126#[derive(Debug, Clone)]
127pub struct CreateFlowNode {
128	pub namespace: NamespaceDef,
129	pub flow: Fragment,
130	pub if_not_exists: bool,
131	pub as_clause: Box<QueryPlan>,
132}
133
134#[derive(Debug, Clone)]
135pub struct CreateTransactionalViewNode {
136	pub namespace: NamespaceDef, // FIXME REsolvedNamespace
137	pub view: Fragment,
138	pub if_not_exists: bool,
139	pub columns: Vec<ViewColumnToCreate>,
140	pub as_clause: Box<QueryPlan>,
141	pub primary_key: Option<PrimaryKeyDef>,
142}
143
144#[derive(Debug, Clone)]
145pub struct CreateNamespaceNode {
146	pub segments: Vec<Fragment>,
147	pub if_not_exists: bool,
148}
149
150#[derive(Debug, Clone)]
151pub struct CreateTableNode {
152	pub namespace: ResolvedNamespace,
153	pub table: Fragment,
154	pub if_not_exists: bool,
155	pub columns: Vec<TableColumnToCreate>,
156	pub primary_key: Option<PrimaryKeyDef>,
157}
158
159#[derive(Debug, Clone)]
160pub struct CreateRingBufferNode {
161	pub namespace: ResolvedNamespace,
162	pub ringbuffer: Fragment,
163	pub if_not_exists: bool,
164	pub columns: Vec<RingBufferColumnToCreate>,
165	pub capacity: u64,
166	pub primary_key: Option<PrimaryKeyDef>,
167}
168
169#[derive(Debug, Clone)]
170pub struct CreateDictionaryNode {
171	pub namespace: NamespaceDef,
172	pub dictionary: Fragment,
173	pub if_not_exists: bool,
174	pub value_type: Type,
175	pub id_type: Type,
176}
177
178#[derive(Debug, Clone)]
179pub struct CreateSumTypeNode {
180	pub namespace: NamespaceDef,
181	pub name: Fragment,
182	pub if_not_exists: bool,
183	pub variants: Vec<CreateSumTypeVariant>,
184}
185
186#[derive(Debug, Clone)]
187pub struct CreateSumTypeVariant {
188	pub name: String,
189	pub columns: Vec<CreateSumTypeColumn>,
190}
191
192#[derive(Debug, Clone)]
193pub struct CreateSumTypeColumn {
194	pub name: String,
195	pub column_type: TypeConstraint,
196}
197
198#[derive(Debug, Clone)]
199pub struct CreateSubscriptionNode {
200	pub columns: Vec<SubscriptionColumnToCreate>,
201	pub as_clause: Option<Box<QueryPlan>>,
202}
203
204#[derive(Debug, Clone)]
205pub struct AlterSequenceNode {
206	pub sequence: ResolvedSequence,
207	pub column: ResolvedColumn,
208	pub value: Expression,
209}
210
211// Alter Table types
212
213#[derive(Debug, Clone, PartialEq)]
214pub struct AlterTableNode {
215	pub table: AlterTableIdentifier,
216	pub operations: Vec<AlterTableOperation>,
217}
218
219#[derive(Debug, Clone, PartialEq)]
220pub struct AlterTableIdentifier {
221	pub namespace: Option<Fragment>,
222	pub name: Fragment,
223}
224
225#[derive(Debug, Clone, PartialEq)]
226pub enum AlterTableOperation {
227	CreatePrimaryKey {
228		name: Option<Fragment>,
229		columns: Vec<AlterTableIndexColumn>,
230	},
231	DropPrimaryKey,
232}
233
234#[derive(Debug, Clone, PartialEq)]
235pub struct AlterTableIndexColumn {
236	pub column: AlterTableColumnIdentifier,
237	pub order: Option<SortDirection>,
238}
239
240#[derive(Debug, Clone, PartialEq)]
241pub struct AlterTableColumnIdentifier {
242	pub namespace: Option<Fragment>,
243	pub name: Fragment,
244}
245
246// Alter View types
247
248#[derive(Debug, Clone, PartialEq)]
249pub struct AlterViewNode {
250	pub view: AlterViewIdentifier,
251	pub operations: Vec<AlterViewOperation>,
252}
253
254#[derive(Debug, Clone, PartialEq)]
255pub struct AlterViewIdentifier {
256	pub namespace: Option<Fragment>,
257	pub name: Fragment,
258}
259
260#[derive(Debug, Clone, PartialEq)]
261pub enum AlterViewOperation {
262	CreatePrimaryKey {
263		name: Option<Fragment>,
264		columns: Vec<AlterViewIndexColumn>,
265	},
266	DropPrimaryKey,
267}
268
269#[derive(Debug, Clone, PartialEq)]
270pub struct AlterViewIndexColumn {
271	pub column: AlterViewColumnIdentifier,
272	pub order: Option<SortDirection>,
273}
274
275#[derive(Debug, Clone, PartialEq)]
276pub struct AlterViewColumnIdentifier {
277	pub namespace: Option<Fragment>,
278	pub name: Fragment,
279}
280
281// Alter Flow types
282
283#[derive(Debug, Clone)]
284pub struct AlterFlowNode {
285	pub flow: AlterFlowIdentifier,
286	pub action: AlterFlowAction,
287}
288
289#[derive(Debug, Clone)]
290pub struct AlterFlowIdentifier {
291	pub namespace: Option<Fragment>,
292	pub name: Fragment,
293}
294
295#[derive(Debug, Clone)]
296pub enum AlterFlowAction {
297	Rename {
298		new_name: Fragment,
299	},
300	SetQuery {
301		query: Box<QueryPlan>,
302	},
303	Pause,
304	Resume,
305}
306
307#[derive(Debug, Clone)]
308pub enum LetValue {
309	Expression(Expression),
310	Statement(QueryPlan),
311	EmptyFrame,
312}
313
314impl std::fmt::Display for LetValue {
315	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
316		match self {
317			LetValue::Expression(expr) => write!(f, "{}", expr),
318			LetValue::Statement(query) => write!(f, "Statement({:?})", query),
319			LetValue::EmptyFrame => write!(f, "EmptyFrame"),
320		}
321	}
322}
323
324#[derive(Debug, Clone)]
325pub struct DeclareNode {
326	pub name: Fragment,
327	pub value: LetValue,
328}
329
330#[derive(Debug, Clone)]
331pub enum AssignValue {
332	Expression(Expression),
333	Statement(QueryPlan),
334}
335
336impl std::fmt::Display for AssignValue {
337	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
338		match self {
339			AssignValue::Expression(expr) => write!(f, "{}", expr),
340			AssignValue::Statement(query) => write!(f, "Statement({:?})", query),
341		}
342	}
343}
344
345#[derive(Debug, Clone)]
346pub struct AssignNode {
347	pub name: Fragment,
348	pub value: AssignValue,
349}
350
351#[derive(Debug, Clone)]
352pub struct VariableNode {
353	pub variable_expr: VariableExpression,
354}
355
356#[derive(Debug, Clone)]
357pub struct EnvironmentNode {}
358
359/// A function parameter in the physical plan
360#[derive(Debug, Clone)]
361pub struct FunctionParameter {
362	/// Parameter name (includes $)
363	pub name: Fragment,
364	/// Optional type constraint
365	pub type_constraint: Option<TypeConstraint>,
366}
367
368#[derive(Debug, Clone)]
369pub struct ScalarizeNode {
370	pub input: Box<QueryPlan>,
371	pub fragment: Fragment,
372}
373
374#[derive(Debug, Clone)]
375pub struct AggregateNode {
376	pub input: Box<QueryPlan>,
377	pub by: Vec<Expression>,
378	pub map: Vec<Expression>,
379}
380
381#[derive(Debug, Clone)]
382pub struct DistinctNode {
383	pub input: Box<QueryPlan>,
384	pub columns: Vec<ResolvedColumn>,
385}
386
387#[derive(Debug, Clone)]
388pub struct AssertNode {
389	pub input: Option<Box<QueryPlan>>,
390	pub conditions: Vec<Expression>,
391	pub message: Option<String>,
392}
393
394#[derive(Debug, Clone)]
395pub struct FilterNode {
396	pub input: Box<QueryPlan>,
397	pub conditions: Vec<Expression>,
398}
399
400#[derive(Debug, Clone)]
401pub struct DeleteTableNode {
402	pub input: Option<Box<QueryPlan>>,
403	pub target: Option<ResolvedTable>,
404}
405
406#[derive(Debug, Clone)]
407pub struct InsertTableNode {
408	pub input: Box<QueryPlan>,
409	pub target: ResolvedTable,
410}
411
412#[derive(Debug, Clone)]
413pub struct InsertRingBufferNode {
414	pub input: Box<QueryPlan>,
415	pub target: ResolvedRingBuffer,
416}
417
418#[derive(Debug, Clone)]
419pub struct InsertDictionaryNode {
420	pub input: Box<QueryPlan>,
421	pub target: ResolvedDictionary,
422}
423
424#[derive(Debug, Clone)]
425pub struct UpdateTableNode {
426	pub input: Box<QueryPlan>,
427	pub target: Option<ResolvedTable>,
428}
429
430#[derive(Debug, Clone)]
431pub struct DeleteRingBufferNode {
432	pub input: Option<Box<QueryPlan>>,
433	pub target: ResolvedRingBuffer,
434}
435
436#[derive(Debug, Clone)]
437pub struct UpdateRingBufferNode {
438	pub input: Box<QueryPlan>,
439	pub target: ResolvedRingBuffer,
440}
441
442#[derive(Debug, Clone)]
443pub struct JoinInnerNode {
444	pub left: Box<QueryPlan>,
445	pub right: Box<QueryPlan>,
446	pub on: Vec<Expression>,
447	pub alias: Option<Fragment>,
448}
449
450#[derive(Debug, Clone)]
451pub struct JoinLeftNode {
452	pub left: Box<QueryPlan>,
453	pub right: Box<QueryPlan>,
454	pub on: Vec<Expression>,
455	pub alias: Option<Fragment>,
456}
457
458#[derive(Debug, Clone)]
459pub struct JoinNaturalNode {
460	pub left: Box<QueryPlan>,
461	pub right: Box<QueryPlan>,
462	pub join_type: JoinType,
463	pub alias: Option<Fragment>,
464}
465
466#[derive(Debug, Clone)]
467pub struct AppendQueryNode {
468	pub left: Box<QueryPlan>,
469	pub right: Box<QueryPlan>,
470}
471
472#[derive(Debug, Clone)]
473pub struct SortNode {
474	pub input: Box<QueryPlan>,
475	pub by: Vec<SortKey>,
476}
477
478#[derive(Debug, Clone)]
479pub struct MapNode {
480	pub input: Option<Box<QueryPlan>>,
481	pub map: Vec<Expression>,
482}
483
484#[derive(Debug, Clone)]
485pub struct ExtendNode {
486	pub input: Option<Box<QueryPlan>>,
487	pub extend: Vec<Expression>,
488}
489
490#[derive(Debug, Clone)]
491pub struct PatchNode {
492	pub input: Option<Box<QueryPlan>>,
493	pub assignments: Vec<Expression>,
494}
495
496#[derive(Debug, Clone)]
497pub struct ApplyNode {
498	pub input: Option<Box<QueryPlan>>,
499	pub operator: Fragment, // FIXME becomes OperatorIdentifier
500	pub expressions: Vec<Expression>,
501}
502
503#[derive(Debug, Clone)]
504pub struct InlineDataNode {
505	pub rows: Vec<Vec<AliasExpression>>,
506}
507
508#[derive(Debug, Clone)]
509pub struct IndexScanNode {
510	pub source: ResolvedTable,
511	pub index_name: String,
512}
513
514#[derive(Debug, Clone)]
515pub struct TableScanNode {
516	pub source: ResolvedTable,
517}
518
519#[derive(Debug, Clone)]
520pub struct ViewScanNode {
521	pub source: ResolvedView,
522}
523
524#[derive(Debug, Clone)]
525pub struct RingBufferScanNode {
526	pub source: ResolvedRingBuffer,
527}
528
529#[derive(Debug, Clone)]
530pub struct FlowScanNode {
531	pub source: ResolvedFlow,
532}
533
534#[derive(Debug, Clone)]
535pub struct DictionaryScanNode {
536	pub source: ResolvedDictionary,
537}
538
539#[derive(Debug, Clone)]
540pub struct GeneratorNode {
541	pub name: Fragment,
542	pub expressions: Vec<Expression>,
543}
544
545#[derive(Debug, Clone)]
546pub struct TableVirtualScanNode {
547	pub source: ResolvedTableVirtual,
548	pub pushdown_context: Option<TableVirtualPushdownContext>,
549}
550
551#[derive(Debug, Clone)]
552pub struct TableVirtualPushdownContext {
553	pub filters: Vec<Expression>,
554	pub projections: Vec<Expression>,
555	pub order_by: Vec<SortKey>,
556	pub limit: Option<usize>,
557}
558
559#[derive(Debug, Clone)]
560pub struct TakeNode {
561	pub input: Box<QueryPlan>,
562	pub take: usize,
563}
564
565#[derive(Debug, Clone)]
566pub struct WindowNode {
567	pub input: Option<Box<QueryPlan>>,
568	pub window_type: WindowType,
569	pub size: WindowSize,
570	pub slide: Option<WindowSlide>,
571	pub group_by: Vec<Expression>,
572	pub aggregations: Vec<Expression>,
573	pub min_events: usize,
574	pub max_window_count: Option<usize>,
575	pub max_window_age: Option<std::time::Duration>,
576}
577
578/// O(1) point lookup by row number: `filter rownum == N`
579#[derive(Debug, Clone)]
580pub struct RowPointLookupNode {
581	/// The source to look up in (table, ring buffer, etc.)
582	pub source: ResolvedPrimitive,
583	/// The row number to fetch
584	pub row_number: u64,
585}
586
587/// O(k) list lookup by row numbers: `filter rownum in [a, b, c]`
588#[derive(Debug, Clone)]
589pub struct RowListLookupNode {
590	/// The source to look up in
591	pub source: ResolvedPrimitive,
592	/// The row numbers to fetch
593	pub row_numbers: Vec<u64>,
594}
595
596/// Range scan by row numbers: `filter rownum between X and Y`
597#[derive(Debug, Clone)]
598pub struct RowRangeScanNode {
599	/// The source to scan
600	pub source: ResolvedPrimitive,
601	/// Start of the range (inclusive)
602	pub start: u64,
603	/// End of the range (inclusive)
604	pub end: u64,
605}
606
607/// APPEND statement physical plan node
608#[derive(Debug, Clone)]
609pub enum AppendPhysicalNode {
610	IntoVariable {
611		target: Fragment,
612		source: AppendPhysicalSource,
613	},
614	Query {
615		left: Box<QueryPlan>,
616		right: Box<QueryPlan>,
617	},
618}
619
620/// Source for an APPEND physical plan
621#[derive(Debug, Clone)]
622pub enum AppendPhysicalSource {
623	Statement(Vec<PhysicalPlan>),
624	Inline(InlineDataNode),
625}
626
627// --- Control flow and function nodes (owned, for PhysicalPlan enum) ---
628
629#[derive(Debug, Clone)]
630pub struct ConditionalNode {
631	pub condition: Expression,
632	pub then_branch: Box<PhysicalPlan>,
633	pub else_ifs: Vec<ElseIfBranch>,
634	pub else_branch: Option<Box<PhysicalPlan>>,
635}
636
637#[derive(Debug, Clone)]
638pub struct ElseIfBranch {
639	pub condition: Expression,
640	pub then_branch: Box<PhysicalPlan>,
641}
642
643#[derive(Debug, Clone)]
644pub struct LoopPhysicalNode {
645	pub body: Vec<PhysicalPlan>,
646}
647
648#[derive(Debug, Clone)]
649pub struct WhilePhysicalNode {
650	pub condition: Expression,
651	pub body: Vec<PhysicalPlan>,
652}
653
654#[derive(Debug, Clone)]
655pub struct ForPhysicalNode {
656	pub variable_name: Fragment,
657	pub iterable: Box<PhysicalPlan>,
658	pub body: Vec<PhysicalPlan>,
659}
660
661#[derive(Debug, Clone)]
662pub struct DefineFunctionNode {
663	pub name: Fragment,
664	pub parameters: Vec<FunctionParameter>,
665	pub return_type: Option<TypeConstraint>,
666	pub body: Vec<PhysicalPlan>,
667}
668
669#[derive(Debug, Clone)]
670pub struct ReturnNode {
671	pub value: Option<Expression>,
672}
673
674#[derive(Debug, Clone)]
675pub struct CallFunctionNode {
676	pub name: Fragment,
677	pub arguments: Vec<Expression>,
678}