uni_query/query/executor/
path_builder.rs1use crate::types::{Edge, Node, Path, Value};
10
11#[derive(Debug, Clone)]
16pub struct PathBuilder {
17 nodes: Vec<Node>,
18 edges: Vec<Edge>,
19}
20
21impl PathBuilder {
22 pub fn new(start_node: Node) -> Self {
31 Self {
32 nodes: vec![start_node],
33 edges: Vec::new(),
34 }
35 }
36
37 pub fn from_path(path: Path) -> Self {
49 Self {
50 nodes: path.nodes,
51 edges: path.edges,
52 }
53 }
54
55 pub fn add_hop(&mut self, edge: Edge, target: Node) {
67 self.edges.push(edge);
68 self.nodes.push(target);
69 }
70
71 pub fn current_node(&self) -> &Node {
80 self.nodes.last().expect("Path must have at least one node")
81 }
82
83 pub fn length(&self) -> usize {
88 self.edges.len()
89 }
90
91 pub fn build(self) -> Path {
95 Path {
96 nodes: self.nodes,
97 edges: self.edges,
98 }
99 }
100
101 pub fn build_value(self) -> Value {
106 Value::Path(self.build())
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use std::collections::HashMap;
114 use uni_common::core::id::{Eid, Vid};
115
116 fn make_node(vid: u64, label: &str, name: &str) -> Node {
117 let mut properties = HashMap::new();
118 properties.insert("name".to_string(), Value::String(name.to_string()));
119 Node {
120 vid: Vid::new(vid),
121 labels: vec![label.to_string()],
122 properties,
123 }
124 }
125
126 fn make_edge(eid: u64, edge_type: &str, src: u64, dst: u64) -> Edge {
127 Edge {
128 eid: Eid::new(eid),
129 edge_type: edge_type.to_string(),
130 src: Vid::new(src),
131 dst: Vid::new(dst),
132 properties: HashMap::new(),
133 }
134 }
135
136 #[test]
137 fn test_path_builder_single_hop() {
138 let node_a = make_node(1, "Person", "Alice");
140 let node_b = make_node(2, "Person", "Bob");
141 let edge_r = make_edge(100, "KNOWS", 1, 2);
142
143 let mut builder = PathBuilder::new(node_a.clone());
144 builder.add_hop(edge_r.clone(), node_b.clone());
145
146 let path = builder.build();
147
148 assert_eq!(path.nodes.len(), 2);
149 assert_eq!(path.edges.len(), 1);
150 assert_eq!(path.nodes[0].vid, Vid::new(1));
151 assert_eq!(path.nodes[1].vid, Vid::new(2));
152 assert_eq!(path.edges[0].eid, Eid::new(100));
153 }
154
155 #[test]
156 fn test_path_builder_multi_hop() {
157 let node_a = make_node(1, "Person", "Alice");
159 let node_b = make_node(2, "Person", "Bob");
160 let node_c = make_node(3, "Person", "Charlie");
161 let edge_r1 = make_edge(100, "KNOWS", 1, 2);
162 let edge_r2 = make_edge(101, "KNOWS", 2, 3);
163
164 let mut builder = PathBuilder::new(node_a.clone());
165 builder.add_hop(edge_r1.clone(), node_b.clone());
166 builder.add_hop(edge_r2.clone(), node_c.clone());
167
168 let path = builder.build();
169
170 assert_eq!(path.nodes.len(), 3);
171 assert_eq!(path.edges.len(), 2);
172 assert_eq!(path.nodes[0].vid, Vid::new(1));
173 assert_eq!(path.nodes[1].vid, Vid::new(2));
174 assert_eq!(path.nodes[2].vid, Vid::new(3));
175 assert_eq!(path.edges[0].eid, Eid::new(100));
176 assert_eq!(path.edges[1].eid, Eid::new(101));
177 }
178
179 #[test]
180 fn test_path_extension() {
181 let node_a = make_node(1, "Person", "Alice");
183 let node_b = make_node(2, "Person", "Bob");
184 let node_c = make_node(3, "Person", "Charlie");
185 let edge_r1 = make_edge(100, "KNOWS", 1, 2);
186 let edge_r2 = make_edge(101, "KNOWS", 2, 3);
187
188 let initial_path = Path {
190 nodes: vec![node_a.clone(), node_b.clone()],
191 edges: vec![edge_r1.clone()],
192 };
193
194 let mut builder = PathBuilder::from_path(initial_path);
196 builder.add_hop(edge_r2.clone(), node_c.clone());
197
198 let path = builder.build();
199
200 assert_eq!(path.nodes.len(), 3);
201 assert_eq!(path.edges.len(), 2);
202 }
203
204 #[test]
205 fn test_current_node() {
206 let node_a = make_node(1, "Person", "Alice");
207 let node_b = make_node(2, "Person", "Bob");
208 let edge_r = make_edge(100, "KNOWS", 1, 2);
209
210 let mut builder = PathBuilder::new(node_a.clone());
211
212 assert_eq!(builder.current_node().vid, Vid::new(1));
214
215 builder.add_hop(edge_r, node_b.clone());
216
217 assert_eq!(builder.current_node().vid, Vid::new(2));
219 }
220
221 #[test]
222 fn test_path_length() {
223 let node_a = make_node(1, "Person", "Alice");
224 let node_b = make_node(2, "Person", "Bob");
225 let node_c = make_node(3, "Person", "Charlie");
226 let edge_r1 = make_edge(100, "KNOWS", 1, 2);
227 let edge_r2 = make_edge(101, "KNOWS", 2, 3);
228
229 let mut builder = PathBuilder::new(node_a.clone());
230 assert_eq!(builder.length(), 0);
231
232 builder.add_hop(edge_r1, node_b.clone());
233 assert_eq!(builder.length(), 1);
234
235 builder.add_hop(edge_r2, node_c.clone());
236 assert_eq!(builder.length(), 2);
237 }
238
239 #[test]
240 fn test_build_value() {
241 let node_a = make_node(1, "Person", "Alice");
242 let node_b = make_node(2, "Person", "Bob");
243 let edge_r = make_edge(100, "KNOWS", 1, 2);
244
245 let mut builder = PathBuilder::new(node_a);
246 builder.add_hop(edge_r, node_b);
247
248 let value = builder.build_value();
249
250 match value {
251 Value::Path(path) => {
252 assert_eq!(path.nodes.len(), 2);
253 assert_eq!(path.edges.len(), 1);
254 }
255 _ => panic!("Expected Value::Path"),
256 }
257 }
258}