linkrs_query/optimizer/heuristic/
result.rs1#[derive(Debug, thiserror::Error)]
8pub enum RewriteError {
9 #[error("Invalid plan node: {0}")]
10 InvalidNode(String),
11
12 #[error("Rewrite failed: {0}")]
13 RewriteFailed(String),
14
15 #[error("Unsupported node types: {0}")]
16 UnsupportedNodeType(String),
17
18 #[error("Optimizer error: {0}")]
19 OptimizerError(String),
20
21 #[error("Loop detection: node {0}")]
22 CycleDetected(usize),
23
24 #[error("Invalid program structure: {0}")]
25 InvalidPlanStructure(String),
26}
27
28impl RewriteError {
29 pub fn invalid_node(msg: impl Into<String>) -> Self {
30 Self::InvalidNode(msg.into())
31 }
32
33 pub fn rewrite_failed(msg: impl Into<String>) -> Self {
34 Self::RewriteFailed(msg.into())
35 }
36
37 pub fn unsupported_node_type(name: impl Into<String>) -> Self {
38 Self::UnsupportedNodeType(name.into())
39 }
40
41 pub fn optimizer_error(msg: impl Into<String>) -> Self {
42 Self::OptimizerError(msg.into())
43 }
44
45 pub fn cycle_detected(node_id: usize) -> Self {
46 Self::CycleDetected(node_id)
47 }
48
49 pub fn invalid_plan_structure(msg: impl Into<String>) -> Self {
50 Self::InvalidPlanStructure(msg.into())
51 }
52}
53
54pub type RewriteResult<T> = std::result::Result<T, RewriteError>;
56
57#[derive(Debug, Default, Clone)]
59pub struct TransformResult {
60 pub erase_curr: bool,
62 pub erase_all: bool,
64 pub new_nodes: Vec<crate::planning::plan::PlanNodeEnum>,
66 pub new_dependencies: Vec<usize>,
68 pub has_folded: bool,
70}
71
72impl TransformResult {
73 pub fn new() -> Self {
75 Self::default()
76 }
77
78 pub fn with_erase_curr(mut self, erase_curr: bool) -> Self {
80 self.erase_curr = erase_curr;
81 self
82 }
83
84 pub fn with_erase_all(mut self, erase_all: bool) -> Self {
86 self.erase_all = erase_all;
87 self
88 }
89
90 pub fn add_new_node(&mut self, node: crate::planning::plan::PlanNodeEnum) {
92 self.new_nodes.push(node);
93 }
94
95 pub fn add_new_dependency(&mut self, dep_id: usize) {
97 self.new_dependencies.push(dep_id);
98 }
99
100 pub fn with_erased(mut self) -> Self {
102 self.erase_curr = true;
103 self
104 }
105
106 pub fn mark_folded(&mut self) {
108 self.has_folded = true;
109 }
110
111 pub fn has_new_nodes(&self) -> bool {
113 !self.new_nodes.is_empty()
114 }
115
116 pub fn first_new_node(&self) -> Option<&crate::planning::plan::PlanNodeEnum> {
118 self.new_nodes.first()
119 }
120}
121
122#[derive(Debug, Default, Clone)]
126pub struct MatchedResult {
127 pub nodes: Vec<crate::planning::plan::PlanNodeEnum>,
129 pub dependencies: Vec<crate::planning::plan::PlanNodeEnum>,
131 pub root_node: Option<crate::planning::plan::PlanNodeEnum>,
133}
134
135impl MatchedResult {
136 pub fn new() -> Self {
138 Self::default()
139 }
140
141 pub fn add_node(&mut self, node: crate::planning::plan::PlanNodeEnum) {
143 self.nodes.push(node);
144 }
145
146 pub fn add_dependency(&mut self, node: crate::planning::plan::PlanNodeEnum) {
148 self.dependencies.push(node);
149 }
150
151 pub fn set_root_node(&mut self, node: crate::planning::plan::PlanNodeEnum) {
153 self.root_node = Some(node);
154 }
155
156 pub fn has_matches(&self) -> bool {
158 !self.nodes.is_empty()
159 }
160
161 pub fn first_node(&self) -> Option<&crate::planning::plan::PlanNodeEnum> {
163 self.nodes.first()
164 }
165
166 pub fn first_dependency(&self) -> Option<&crate::planning::plan::PlanNodeEnum> {
168 self.dependencies.first()
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175 use crate::planning::plan::core::nodes::access::graph_scan_node::ScanVerticesNode;
176
177 #[test]
178 fn test_transform_result() {
179 let mut result = TransformResult::new();
180 assert!(!result.has_new_nodes());
181 assert!(!result.has_folded);
182
183 let node =
184 crate::planning::plan::PlanNodeEnum::ScanVertices(ScanVerticesNode::new(1, "default"));
185 result.add_new_node(node);
186
187 assert!(result.has_new_nodes());
188 assert!(result.first_new_node().is_some());
189
190 result.mark_folded();
191 assert!(result.has_folded);
192 }
193
194 #[test]
195 fn test_matched_result() {
196 let mut result = MatchedResult::new();
197 assert!(!result.has_matches());
198
199 let node =
200 crate::planning::plan::PlanNodeEnum::ScanVertices(ScanVerticesNode::new(1, "default"));
201 result.add_node(node);
202
203 assert!(result.has_matches());
204 assert!(result.first_node().is_some());
205 }
206
207 #[test]
208 fn test_rewrite_error() {
209 let err = RewriteError::invalid_node("test node");
210 assert!(err.to_string().contains("test node"));
211
212 let err = RewriteError::cycle_detected(42);
213 assert!(err.to_string().contains("42"));
214 }
215}