Skip to main content

linkrs_query/planning/plan/logical/
logical_macros.rs

1//! Macros for defining logical plan nodes.
2//!
3//! These mirrors the physical node macros in `core::nodes::base::macros`
4//! but generate structs whose children are `LogicalNodeEnum` instead of
5//! `PlanNodeEnum`.  All fields are `pub` to allow cross-module construction
6//! during physical-to-logical conversion.
7
8#[macro_export]
9macro_rules! define_logical_plan_node {
10    (
11        $(#[$meta:meta])*
12        pub struct $name:ident {
13            $($field:ident: $type:ty),* $(,)?
14        }
15        enum: $enum_variant:ident
16        input: ZeroInputNode
17    ) => {
18        $(#[$meta])*
19        #[derive(Debug)]
20        pub struct $name {
21            pub id: i64,
22            $(pub $field: $type,)*
23            pub output_var: Option<String>,
24            pub col_names: Vec<String>,
25            pub column_types: Vec<linkrs_core::DataType>,
26        }
27
28        impl Clone for $name {
29            fn clone(&self) -> Self {
30                use $crate::planning::plan::core::node_id_generator::next_node_id;
31                Self {
32                    id: next_node_id(),
33                    $($field: self.$field.clone(),)*
34                    output_var: self.output_var.clone(),
35                    col_names: self.col_names.clone(),
36                    column_types: self.column_types.clone(),
37                }
38            }
39        }
40
41        impl $name {
42            pub fn id(&self) -> i64 { self.id }
43            pub fn type_name(&self) -> &'static str { stringify!($name) }
44            pub fn output_var(&self) -> Option<&str> { self.output_var.as_deref() }
45            pub fn col_names(&self) -> &[String] { &self.col_names }
46            pub fn set_output_var(&mut self, var: String) { self.output_var = Some(var); }
47            pub fn set_col_names(&mut self, names: Vec<String>) { self.col_names = names; }
48            pub fn column_types(&self) -> &[linkrs_core::DataType] { &self.column_types }
49            pub fn set_column_types(&mut self, types: Vec<linkrs_core::DataType>) { self.column_types = types; }
50
51            pub fn clone_logical_node(&self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
52                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
53                LogicalNodeEnum::$enum_variant(self.clone())
54            }
55        }
56
57        impl $crate::planning::plan::logical::logical_node_traits::LogicalNode for $name {
58            fn id(&self) -> i64 { self.id() }
59            fn name(&self) -> &'static str { self.type_name() }
60            fn output_var(&self) -> Option<&str> { self.output_var() }
61            fn col_names(&self) -> &[String] { self.col_names() }
62            fn set_output_var(&mut self, var: String) { self.set_output_var(var); }
63            fn set_col_names(&mut self, names: Vec<String>) { self.set_col_names(names); }
64            fn into_enum(self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
65                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
66                LogicalNodeEnum::$enum_variant(self)
67            }
68        }
69
70        impl $crate::planning::plan::logical::logical_node_traits::LogicalZeroInputNode for $name {}
71    };
72
73    (
74        $(#[$meta:meta])*
75        pub struct $name:ident {
76            $($field:ident: $type:ty),* $(,)?
77        }
78        enum: $enum_variant:ident
79        input: MultipleInputNode
80    ) => {
81        $(#[$meta])*
82        #[derive(Debug)]
83        pub struct $name {
84            pub id: i64,
85            pub deps: Vec<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum>,
86            $(pub $field: $type,)*
87            pub output_var: Option<String>,
88            pub col_names: Vec<String>,
89            pub column_types: Vec<linkrs_core::DataType>,
90        }
91
92        impl Clone for $name {
93            fn clone(&self) -> Self {
94                use $crate::planning::plan::core::node_id_generator::next_node_id;
95                Self {
96                    id: next_node_id(),
97                    deps: self.deps.clone(),
98                    $($field: self.$field.clone(),)*
99                    output_var: self.output_var.clone(),
100                    col_names: self.col_names.clone(),
101                    column_types: self.column_types.clone(),
102                }
103            }
104        }
105
106        impl $name {
107            pub fn id(&self) -> i64 { self.id }
108            pub fn type_name(&self) -> &'static str { stringify!($name) }
109            pub fn output_var(&self) -> Option<&str> { self.output_var.as_deref() }
110            pub fn col_names(&self) -> &[String] { &self.col_names }
111            pub fn set_output_var(&mut self, var: String) { self.output_var = Some(var); }
112            pub fn set_col_names(&mut self, names: Vec<String>) { self.col_names = names; }
113            pub fn column_types(&self) -> &[linkrs_core::DataType] { &self.column_types }
114            pub fn set_column_types(&mut self, types: Vec<linkrs_core::DataType>) { self.column_types = types; }
115
116            pub fn dependencies(&self) -> &[$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum] {
117                &self.deps
118            }
119
120            pub fn add_dependency(&mut self, dep: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
121                self.deps.push(dep);
122            }
123
124            pub fn remove_dependency(&mut self, id: i64) -> bool {
125                let initial_len = self.deps.len();
126                self.deps.retain(|dep| dep.id() != id);
127                self.deps.len() != initial_len
128            }
129
130            pub fn clone_logical_node(&self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
131                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
132                LogicalNodeEnum::$enum_variant(self.clone())
133            }
134        }
135
136        impl $crate::planning::plan::logical::logical_node_traits::LogicalNode for $name {
137            fn id(&self) -> i64 { self.id() }
138            fn name(&self) -> &'static str { self.type_name() }
139            fn output_var(&self) -> Option<&str> { self.output_var() }
140            fn col_names(&self) -> &[String] { self.col_names() }
141            fn set_output_var(&mut self, var: String) { self.set_output_var(var); }
142            fn set_col_names(&mut self, names: Vec<String>) { self.set_col_names(names); }
143            fn into_enum(self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
144                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
145                LogicalNodeEnum::$enum_variant(self)
146            }
147        }
148
149        impl $crate::planning::plan::logical::logical_node_traits::LogicalMultipleInputNode for $name {
150            fn inputs(&self) -> &[$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum] {
151                &self.deps
152            }
153
154            fn inputs_mut(&mut self) -> &mut Vec<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum> {
155                &mut self.deps
156            }
157
158            fn add_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
159                self.deps.push(input);
160            }
161
162            fn remove_input(&mut self, index: usize) -> Result<(), String> {
163                if index < self.deps.len() {
164                    self.deps.remove(index);
165                    Ok(())
166                } else {
167                    Err(format!("Index {} out of range", index))
168                }
169            }
170        }
171    };
172}
173
174#[macro_export]
175macro_rules! define_logical_plan_node_with_deps {
176    (
177        $(#[$meta:meta])*
178        pub struct $name:ident {
179            $($field:ident: $type:ty),* $(,)?
180        }
181        enum: $enum_variant:ident
182        input: SingleInputNode
183    ) => {
184        $(#[$meta])*
185        #[derive(Debug)]
186        pub struct $name {
187            pub id: i64,
188            pub input: Option<Box<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum>>,
189            $(pub $field: $type,)*
190            pub output_var: Option<String>,
191            pub col_names: Vec<String>,
192            pub column_types: Vec<linkrs_core::DataType>,
193        }
194
195        impl Clone for $name {
196            fn clone(&self) -> Self {
197                use $crate::planning::plan::core::node_id_generator::next_node_id;
198                Self {
199                    id: next_node_id(),
200                    input: self.input.clone(),
201                    $($field: self.$field.clone(),)*
202                    output_var: self.output_var.clone(),
203                    col_names: self.col_names.clone(),
204                    column_types: self.column_types.clone(),
205                }
206            }
207        }
208
209        impl $name {
210            pub fn id(&self) -> i64 { self.id }
211            pub fn type_name(&self) -> &'static str { stringify!($name) }
212            pub fn output_var(&self) -> Option<&str> { self.output_var.as_deref() }
213            pub fn col_names(&self) -> &[String] { &self.col_names }
214            pub fn set_output_var(&mut self, var: String) { self.output_var = Some(var); }
215            pub fn set_col_names(&mut self, names: Vec<String>) { self.col_names = names; }
216            pub fn column_types(&self) -> &[linkrs_core::DataType] { &self.column_types }
217            pub fn set_column_types(&mut self, types: Vec<linkrs_core::DataType>) { self.column_types = types; }
218
219            pub fn dependencies(&self) -> &[$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum] {
220                self.input
221                    .as_deref()
222                    .map(std::slice::from_ref)
223                    .unwrap_or(&[])
224            }
225
226            pub fn clone_logical_node(&self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
227                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
228                LogicalNodeEnum::$enum_variant(self.clone())
229            }
230        }
231
232        impl $crate::planning::plan::logical::logical_node_traits::LogicalNode for $name {
233            fn id(&self) -> i64 { self.id() }
234            fn name(&self) -> &'static str { self.type_name() }
235            fn output_var(&self) -> Option<&str> { self.output_var() }
236            fn col_names(&self) -> &[String] { self.col_names() }
237            fn set_output_var(&mut self, var: String) { self.set_output_var(var); }
238            fn set_col_names(&mut self, names: Vec<String>) { self.set_col_names(names); }
239            fn into_enum(self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
240                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
241                LogicalNodeEnum::$enum_variant(self)
242            }
243        }
244
245        impl $crate::planning::plan::logical::logical_node_traits::LogicalSingleInputNode for $name {
246            fn input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
247                self.input.as_ref().expect("Input node does not exist")
248            }
249
250            fn input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
251                self.input.as_mut().expect("Input node does not exist")
252            }
253
254            fn set_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
255                self.input = Some(Box::new(input));
256            }
257
258            fn take_input(&mut self) -> Option<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum> {
259                self.input.take().map(|b| *b)
260            }
261        }
262    };
263}
264
265#[macro_export]
266macro_rules! define_logical_join_node {
267    (
268        $(#[$meta:meta])*
269        pub struct $name:ident {
270            $($field:ident: $type:ty),* $(,)?
271        }
272        enum: $enum_variant:ident
273    ) => {
274        $(#[$meta])*
275        #[derive(Debug)]
276        pub struct $name {
277            pub id: i64,
278            pub left: Box<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum>,
279            pub right: Box<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum>,
280            pub hash_keys: Vec<linkrs_core::types::expr::contextual::ContextualExpression>,
281            pub probe_keys: Vec<linkrs_core::types::expr::contextual::ContextualExpression>,
282            $(pub $field: $type,)*
283            pub output_var: Option<String>,
284            pub col_names: Vec<String>,
285            pub column_types: Vec<linkrs_core::DataType>,
286        }
287
288        impl Clone for $name {
289            fn clone(&self) -> Self {
290                use $crate::planning::plan::core::node_id_generator::next_node_id;
291                Self {
292                    id: next_node_id(),
293                    left: self.left.clone(),
294                    right: self.right.clone(),
295                    hash_keys: self.hash_keys.clone(),
296                    probe_keys: self.probe_keys.clone(),
297                    $($field: self.$field.clone(),)*
298                    output_var: self.output_var.clone(),
299                    col_names: self.col_names.clone(),
300                    column_types: self.column_types.clone(),
301                }
302            }
303        }
304
305        impl $name {
306            pub fn id(&self) -> i64 { self.id }
307            pub fn type_name(&self) -> &'static str { stringify!($name) }
308            pub fn output_var(&self) -> Option<&str> { self.output_var.as_deref() }
309            pub fn col_names(&self) -> &[String] { &self.col_names }
310            pub fn set_output_var(&mut self, var: String) { self.output_var = Some(var); }
311            pub fn set_col_names(&mut self, names: Vec<String>) { self.col_names = names; }
312            pub fn column_types(&self) -> &[linkrs_core::DataType] { &self.column_types }
313            pub fn set_column_types(&mut self, types: Vec<linkrs_core::DataType>) { self.column_types = types; }
314
315            pub fn hash_keys(&self) -> &[linkrs_core::types::expr::contextual::ContextualExpression] {
316                &self.hash_keys
317            }
318
319            pub fn probe_keys(&self) -> &[linkrs_core::types::expr::contextual::ContextualExpression] {
320                &self.probe_keys
321            }
322
323            pub fn left_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
324                &self.left
325            }
326
327            pub fn right_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
328                &self.right
329            }
330
331            pub fn left_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
332                &mut self.left
333            }
334
335            pub fn right_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
336                &mut self.right
337            }
338
339            pub fn set_left_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
340                self.left = Box::new(input);
341            }
342
343            pub fn set_right_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
344                self.right = Box::new(input);
345            }
346
347            pub fn clone_logical_node(&self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
348                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
349                LogicalNodeEnum::$enum_variant(self.clone())
350            }
351        }
352
353        impl $crate::planning::plan::logical::logical_node_traits::LogicalNode for $name {
354            fn id(&self) -> i64 { self.id() }
355            fn name(&self) -> &'static str { self.type_name() }
356            fn output_var(&self) -> Option<&str> { self.output_var() }
357            fn col_names(&self) -> &[String] { self.col_names() }
358            fn set_output_var(&mut self, var: String) { self.set_output_var(var); }
359            fn set_col_names(&mut self, names: Vec<String>) { self.set_col_names(names); }
360            fn into_enum(self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
361                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
362                LogicalNodeEnum::$enum_variant(self)
363            }
364        }
365
366        impl $crate::planning::plan::logical::logical_node_traits::LogicalBinaryInputNode for $name {
367            fn left_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
368                &self.left
369            }
370
371            fn right_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
372                &self.right
373            }
374
375            fn left_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
376                &mut self.left
377            }
378
379            fn right_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
380                &mut self.right
381            }
382
383            fn set_left_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
384                self.left = Box::new(input);
385            }
386
387            fn set_right_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
388                self.right = Box::new(input);
389            }
390        }
391
392        impl $crate::planning::plan::logical::logical_node_traits::LogicalJoinNode for $name {
393            fn hash_keys(&self) -> &[linkrs_core::types::expr::contextual::ContextualExpression] {
394                &self.hash_keys
395            }
396
397            fn probe_keys(&self) -> &[linkrs_core::types::expr::contextual::ContextualExpression] {
398                &self.probe_keys
399            }
400        }
401    };
402}
403
404#[macro_export]
405macro_rules! define_logical_binary_input_node {
406    (
407        $(#[$meta:meta])*
408        pub struct $name:ident {
409            $($field:ident: $type:ty),* $(,)?
410        }
411        enum: $enum_variant:ident
412        input: BinaryInputNode
413    ) => {
414        $(#[$meta])*
415        #[derive(Debug)]
416        pub struct $name {
417            pub id: i64,
418            pub left: Box<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum>,
419            pub right: Box<$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum>,
420            $(pub $field: $type,)*
421            pub output_var: Option<String>,
422            pub col_names: Vec<String>,
423            pub column_types: Vec<linkrs_core::DataType>,
424        }
425
426        impl Clone for $name {
427            fn clone(&self) -> Self {
428                use $crate::planning::plan::core::node_id_generator::next_node_id;
429                Self {
430                    id: next_node_id(),
431                    left: self.left.clone(),
432                    right: self.right.clone(),
433                    $($field: self.$field.clone(),)*
434                    output_var: self.output_var.clone(),
435                    col_names: self.col_names.clone(),
436                    column_types: self.column_types.clone(),
437                }
438            }
439        }
440
441        impl $name {
442            pub fn id(&self) -> i64 { self.id }
443            pub fn type_name(&self) -> &'static str { stringify!($name) }
444            pub fn output_var(&self) -> Option<&str> { self.output_var.as_deref() }
445            pub fn col_names(&self) -> &[String] { &self.col_names }
446            pub fn set_output_var(&mut self, var: String) { self.output_var = Some(var); }
447            pub fn set_col_names(&mut self, names: Vec<String>) { self.col_names = names; }
448            pub fn column_types(&self) -> &[linkrs_core::DataType] { &self.column_types }
449            pub fn set_column_types(&mut self, types: Vec<linkrs_core::DataType>) { self.column_types = types; }
450
451            pub fn left_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
452                &self.left
453            }
454
455            pub fn right_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
456                &self.right
457            }
458
459            pub fn left_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
460                &mut self.left
461            }
462
463            pub fn right_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
464                &mut self.right
465            }
466
467            pub fn set_left_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
468                self.left = Box::new(input);
469            }
470
471            pub fn set_right_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
472                self.right = Box::new(input);
473            }
474
475            pub fn clone_logical_node(&self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
476                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
477                LogicalNodeEnum::$enum_variant(self.clone())
478            }
479        }
480
481        impl $crate::planning::plan::logical::logical_node_traits::LogicalNode for $name {
482            fn id(&self) -> i64 { self.id() }
483            fn name(&self) -> &'static str { self.type_name() }
484            fn output_var(&self) -> Option<&str> { self.output_var() }
485            fn col_names(&self) -> &[String] { self.col_names() }
486            fn set_output_var(&mut self, var: String) { self.set_output_var(var); }
487            fn set_col_names(&mut self, names: Vec<String>) { self.set_col_names(names); }
488            fn into_enum(self) -> $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
489                use $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
490                LogicalNodeEnum::$enum_variant(self)
491            }
492        }
493
494        impl $crate::planning::plan::logical::logical_node_traits::LogicalBinaryInputNode for $name {
495            fn left_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
496                &self.left
497            }
498
499            fn right_input(&self) -> &$crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
500                &self.right
501            }
502
503            fn left_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
504                &mut self.left
505            }
506
507            fn right_input_mut(&mut self) -> &mut $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum {
508                &mut self.right
509            }
510
511            fn set_left_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
512                self.left = Box::new(input);
513            }
514
515            fn set_right_input(&mut self, input: $crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum) {
516                self.right = Box::new(input);
517            }
518        }
519    };
520}