linkrs_query/planning/plan/logical/
conversion.rs1use crate::planning::plan::core::nodes::base::plan_node_enum::PlanNodeEnum;
12use crate::planning::plan::logical::logical_node_enum::LogicalNodeEnum;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum ConversionError {
17 NotYetImplemented(String),
19}
20
21impl std::fmt::Display for ConversionError {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 Self::NotYetImplemented(name) => {
25 write!(f, "conversion not yet implemented for: {}", name)
26 }
27 }
28 }
29}
30
31impl std::error::Error for ConversionError {}
32
33pub fn convert_plan(node: &PlanNodeEnum) -> Result<LogicalNodeEnum, ConversionError> {
53 match node {
54 PlanNodeEnum::Start(n) => access::convert_start(n),
56 PlanNodeEnum::ScanVertices(n) => access::convert_scan_vertices(n),
57 PlanNodeEnum::ScanEdges(n) => access::convert_scan_edges(n),
58 PlanNodeEnum::GetVertices(n) => access::convert_get_vertices(n),
59 PlanNodeEnum::GetNeighbors(n) => access::convert_get_neighbors(n),
60 PlanNodeEnum::IndexScan(n) => access::convert_index_scan(n),
61 PlanNodeEnum::Project(n) => operation::convert_project(n),
63 PlanNodeEnum::Filter(n) => operation::convert_filter(n),
64 PlanNodeEnum::Sort(n) => operation::convert_sort(n),
65 PlanNodeEnum::Limit(n) => operation::convert_limit(n),
66 PlanNodeEnum::TopN(n) => operation::convert_top_n(n),
67 PlanNodeEnum::Sample(n) => operation::convert_sample(n),
68 PlanNodeEnum::Dedup(n) => operation::convert_dedup(n),
69 PlanNodeEnum::Aggregate(n) => operation::convert_aggregate(n),
70 PlanNodeEnum::Window(n) => operation::convert_window(n),
71 PlanNodeEnum::InnerJoin(n) => join::convert_inner_join(n),
73 PlanNodeEnum::LeftJoin(n) => join::convert_left_join(n),
74 PlanNodeEnum::RightJoin(n) => join::convert_right_join(n),
75 PlanNodeEnum::CrossJoin(n) => join::convert_cross_join(n),
76 PlanNodeEnum::FullOuterJoin(n) => join::convert_full_outer_join(n),
77 PlanNodeEnum::SemiJoin(n) => join::convert_semi_join(n),
78 PlanNodeEnum::Flatten(n) => join::convert_flatten(n),
79 PlanNodeEnum::Expand(n) => traversal::convert_expand(n),
81 PlanNodeEnum::ExpandAll(n) => traversal::convert_expand_all(n),
82 PlanNodeEnum::Traverse(n) => traversal::convert_traverse(n),
83 PlanNodeEnum::AppendVertices(n) => traversal::convert_append_vertices(n),
84 PlanNodeEnum::BiExpand(n) => traversal::convert_bi_expand(n),
85 PlanNodeEnum::BiTraverse(n) => traversal::convert_bi_traverse(n),
86 PlanNodeEnum::Select(n) => control_flow::convert_select(n),
88 PlanNodeEnum::Loop(n) => control_flow::convert_loop(n),
89 PlanNodeEnum::Argument(n) => control_flow::convert_argument(n),
90 PlanNodeEnum::PassThrough(n) => control_flow::convert_pass_through(n),
91 PlanNodeEnum::Assign(n) => pipeline::convert_assign(n),
93 PlanNodeEnum::DataCollect(n) => pipeline::convert_data_collect(n),
94 PlanNodeEnum::Materialize(n) => pipeline::convert_materialize(n),
95 PlanNodeEnum::Union(n) => setop::convert_union(n),
97 PlanNodeEnum::Minus(n) => setop::convert_minus(n),
98 PlanNodeEnum::Intersect(n) => setop::convert_intersect(n),
99 PlanNodeEnum::Unwind(n) => setop::convert_unwind(n),
100 PlanNodeEnum::Apply(n) => apply::convert_apply(n),
102 PlanNodeEnum::PatternApply(n) => apply::convert_pattern_apply(n),
103 PlanNodeEnum::RollUpApply(n) => apply::convert_roll_up_apply(n),
104 PlanNodeEnum::CorrelatedApply(n) => apply::convert_correlated_apply(n),
105 PlanNodeEnum::WcoIntersect(n) => apply::convert_wco_intersect(n),
106 PlanNodeEnum::GetEdges(n) => write::convert_get_edges(n),
108 PlanNodeEnum::InsertVertices(n) => write::convert_insert_vertices(n),
109 PlanNodeEnum::InsertEdges(n) => write::convert_insert_edges(n),
110 PlanNodeEnum::Update(n) => write::convert_update(n),
111 PlanNodeEnum::DeleteVertices(n) => write::convert_delete_vertices(n),
112 PlanNodeEnum::DeleteEdges(n) => write::convert_delete_edges(n),
113 PlanNodeEnum::DeleteIndex(n) => write::convert_delete_index(n),
114 PlanNodeEnum::PipeDeleteVertices(n) => write::convert_pipe_delete_vertices(n),
115 PlanNodeEnum::PipeDeleteEdges(n) => write::convert_pipe_delete_edges(n),
116 PlanNodeEnum::CopyFrom(n) => write::convert_copy_from(n),
117 PlanNodeEnum::CopyTo(n) => write::convert_copy_to(n),
118 _ => Err(ConversionError::NotYetImplemented(
126 node.type_name().to_string(),
127 )),
128 }
129}
130
131mod access;
132mod apply;
133mod control_flow;
134mod join;
135mod operation;
136mod pipeline;
137mod setop;
138mod traversal;
139mod write;
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn test_convert_start() {
147 let start = crate::planning::plan::core::nodes::control_flow::start_node::StartNode::new();
148 let plan_enum = PlanNodeEnum::Start(start);
149 let result = convert_plan(&plan_enum);
150 assert!(result.is_ok());
151 let logical = result.unwrap();
152 assert_eq!(logical.type_name(), "Start");
153 }
154
155 #[test]
156 fn test_convert_filter_with_start() {
157 let start = crate::planning::plan::core::nodes::control_flow::start_node::StartNode::new();
158 let start_enum = PlanNodeEnum::Start(start);
159
160 let ctx = std::sync::Arc::new(
161 linkrs_core::types::expr::expression_context::ExpressionAnalysisContext::new(),
162 );
163 let expr = linkrs_core::Expression::Variable("test".to_string());
164 let expr_meta = linkrs_core::types::expr::ExpressionMeta::new(expr);
165 let id = ctx.register_expression(expr_meta);
166 let condition = linkrs_core::types::expr::contextual::ContextualExpression::new(id, ctx);
167
168 let filter = crate::planning::plan::core::nodes::operation::filter_node::FilterNode::new(
169 start_enum, condition,
170 )
171 .expect("Filter node creation failed");
172
173 let filter_enum = PlanNodeEnum::Filter(filter);
174 let result = convert_plan(&filter_enum);
175 assert!(result.is_ok());
176 let logical = result.unwrap();
177 assert_eq!(logical.type_name(), "Filter");
178 }
179
180 #[test]
181 fn test_convert_unsupported() {
182 let arg =
185 crate::planning::plan::core::nodes::control_flow::control_flow_node::ArgumentNode::new(
186 -1, "x",
187 );
188 let plan_enum = PlanNodeEnum::Argument(arg);
189 let result = convert_plan(&plan_enum);
190 assert!(result.is_ok());
191 assert_eq!(result.unwrap().type_name(), "Argument");
192 }
193}