reddb_server/storage/query/parser/
graph_commands.rs1use super::super::ast::{GraphCommand, GraphCommandOrderBy, QueryExpr};
4use super::super::lexer::Token;
5use super::error::ParseError;
6use super::Parser;
7
8impl<'a> Parser<'a> {
9 pub fn parse_graph_command(&mut self) -> Result<QueryExpr, ParseError> {
11 self.expect(Token::Graph)?;
12 match self.peek().clone() {
13 Token::Neighborhood => self.parse_graph_neighborhood(),
14 Token::ShortestPath => self.parse_graph_shortest_path(),
15 Token::Traverse => self.parse_graph_traverse(),
16 Token::Centrality => self.parse_graph_centrality(),
17 Token::Community => self.parse_graph_community(),
18 Token::Components => self.parse_graph_components(),
19 Token::Cycles => self.parse_graph_cycles(),
20 Token::Clustering => self.parse_graph_clustering(),
21 Token::TopologicalSort => self.parse_graph_topological_sort(),
22 Token::Properties => self.parse_graph_properties(),
23 _ => Err(ParseError::expected(
24 vec![
25 "NEIGHBORHOOD",
26 "SHORTEST_PATH",
27 "TRAVERSE",
28 "CENTRALITY",
29 "COMMUNITY",
30 "COMPONENTS",
31 "CYCLES",
32 "CLUSTERING",
33 "TOPOLOGICAL_SORT",
34 "PROPERTIES",
35 ],
36 self.peek(),
37 self.position(),
38 )),
39 }
40 }
41
42 fn parse_graph_neighborhood(&mut self) -> Result<QueryExpr, ParseError> {
44 self.advance()?; let source = self.parse_string()?;
46 let mut depth = 3;
47 let mut direction = "outgoing".to_string();
48 let mut edge_labels = None;
49
50 loop {
51 if self.consume(&Token::Depth)? {
52 depth = self.parse_integer()? as u32;
53 } else if self.consume(&Token::Direction)? {
54 direction = self.expect_ident_or_keyword()?;
55 } else if self.consume_ident_ci("EDGES")? {
56 edge_labels = Some(self.parse_graph_edge_label_list()?);
57 } else {
58 break;
59 }
60 }
61
62 Ok(QueryExpr::GraphCommand(GraphCommand::Neighborhood {
63 source,
64 depth,
65 direction,
66 edge_labels,
67 }))
68 }
69
70 fn parse_graph_shortest_path(&mut self) -> Result<QueryExpr, ParseError> {
72 self.advance()?; let _ = self.consume(&Token::From)?; let source = self.parse_string()?;
75 self.expect(Token::To)?;
76 let target = self.parse_string()?;
77 let mut algorithm: Option<String> = None;
78 let mut direction: Option<String> = None;
79 let mut limit: Option<u32> = None;
80 let mut order_by: Option<GraphCommandOrderBy> = None;
81 loop {
82 if algorithm.is_none() && self.consume(&Token::Algorithm)? {
83 algorithm = Some(self.expect_ident_or_keyword()?);
84 } else if direction.is_none() && self.consume(&Token::Direction)? {
85 direction = Some(self.expect_ident_or_keyword()?);
86 } else if order_by.is_none() && self.consume(&Token::Order)? {
87 order_by = Some(self.parse_graph_order_by_tail()?);
88 } else if limit.is_none() && self.consume(&Token::Limit)? {
89 let n = self.parse_integer()?;
90 limit = Some(n as u32);
91 } else {
92 break;
93 }
94 }
95 Ok(QueryExpr::GraphCommand(GraphCommand::ShortestPath {
96 source,
97 target,
98 algorithm: algorithm.unwrap_or_else(|| "bfs".to_string()),
99 direction: direction.unwrap_or_else(|| "outgoing".to_string()),
100 limit,
101 order_by,
102 }))
103 }
104
105 fn parse_graph_traverse(&mut self) -> Result<QueryExpr, ParseError> {
107 self.advance()?; let _ = self.consume(&Token::From)?; let source = self.parse_string()?;
110 let mut strategy = "bfs".to_string();
111 let mut depth: u32 = 5;
112 let mut direction = "outgoing".to_string();
113 let mut edge_labels = None;
114 loop {
115 if self.consume(&Token::Strategy)? {
116 strategy = self.expect_ident_or_keyword()?;
117 } else if self.consume(&Token::Depth)? || self.consume_ident_ci("MAX_DEPTH")? {
118 depth = self.parse_integer()? as u32;
119 } else if self.consume(&Token::Direction)? {
120 direction = self.expect_ident_or_keyword()?;
121 } else if self.consume_ident_ci("EDGES")? {
122 edge_labels = Some(self.parse_graph_edge_label_list()?);
123 } else {
124 break;
125 }
126 }
127 Ok(QueryExpr::GraphCommand(GraphCommand::Traverse {
128 source,
129 strategy,
130 depth,
131 direction,
132 edge_labels,
133 }))
134 }
135
136 fn parse_graph_edge_label_list(&mut self) -> Result<Vec<String>, ParseError> {
137 self.expect(Token::In)?;
138 self.expect(Token::LParen)?;
139 let mut labels = Vec::new();
140 loop {
141 labels.push(self.parse_string()?);
142 if !self.consume(&Token::Comma)? {
143 break;
144 }
145 }
146 self.expect(Token::RParen)?;
147 Ok(labels)
148 }
149
150 fn parse_graph_centrality(&mut self) -> Result<QueryExpr, ParseError> {
152 self.advance()?; let mut algorithm: Option<String> = None;
154 let mut limit: Option<u32> = None;
155 let mut order_by: Option<GraphCommandOrderBy> = None;
156 loop {
157 if algorithm.is_none() && self.consume(&Token::Algorithm)? {
158 algorithm = Some(self.expect_ident_or_keyword()?);
159 } else if order_by.is_none() && self.consume(&Token::Order)? {
160 order_by = Some(self.parse_graph_order_by_tail()?);
161 } else if limit.is_none() && self.consume(&Token::Limit)? {
162 let n = self.parse_integer()?;
165 limit = Some(n as u32);
166 } else {
167 break;
168 }
169 }
170 Ok(QueryExpr::GraphCommand(GraphCommand::Centrality {
171 algorithm: algorithm.unwrap_or_else(|| "degree".to_string()),
172 limit,
173 order_by,
174 }))
175 }
176
177 fn parse_graph_community(&mut self) -> Result<QueryExpr, ParseError> {
179 self.advance()?; let mut algorithm: Option<String> = None;
181 let mut max_iterations: Option<u32> = None;
182 let mut limit: Option<u32> = None;
183 let mut order_by: Option<GraphCommandOrderBy> = None;
184 let mut return_assignments = false;
185 loop {
186 if algorithm.is_none() && self.consume(&Token::Algorithm)? {
187 algorithm = Some(self.expect_ident_or_keyword()?);
188 } else if max_iterations.is_none() && self.consume(&Token::MaxIterations)? {
189 max_iterations = Some(self.parse_integer()? as u32);
190 } else if order_by.is_none() && self.consume(&Token::Order)? {
191 order_by = Some(self.parse_graph_order_by_tail()?);
192 } else if limit.is_none() && self.consume(&Token::Limit)? {
193 let n = self.parse_integer()?;
194 limit = Some(n as u32);
195 } else if !return_assignments && self.consume(&Token::Return)? {
196 let target = self.expect_ident_or_keyword()?;
198 if !target.eq_ignore_ascii_case("assignments") {
199 return Err(ParseError::expected(
200 vec!["ASSIGNMENTS"],
201 self.peek(),
202 self.position(),
203 ));
204 }
205 return_assignments = true;
206 } else {
207 break;
208 }
209 }
210 Ok(QueryExpr::GraphCommand(GraphCommand::Community {
211 algorithm: algorithm.unwrap_or_else(|| "label_propagation".to_string()),
212 max_iterations: max_iterations.unwrap_or(100),
213 limit,
214 order_by,
215 return_assignments,
216 }))
217 }
218
219 fn parse_graph_components(&mut self) -> Result<QueryExpr, ParseError> {
221 self.advance()?; let mut mode: Option<String> = None;
223 let mut limit: Option<u32> = None;
224 let mut order_by: Option<GraphCommandOrderBy> = None;
225 loop {
226 if mode.is_none() && self.consume(&Token::Mode)? {
227 mode = Some(self.expect_ident_or_keyword()?);
228 } else if order_by.is_none() && self.consume(&Token::Order)? {
229 order_by = Some(self.parse_graph_order_by_tail()?);
230 } else if limit.is_none() && self.consume(&Token::Limit)? {
231 let n = self.parse_integer()?;
232 limit = Some(n as u32);
233 } else {
234 break;
235 }
236 }
237 Ok(QueryExpr::GraphCommand(GraphCommand::Components {
238 mode: mode.unwrap_or_else(|| "connected".to_string()),
239 limit,
240 order_by,
241 }))
242 }
243
244 fn parse_graph_order_by_tail(&mut self) -> Result<GraphCommandOrderBy, ParseError> {
245 self.expect(Token::By)?;
246 let metric = self.expect_ident_or_keyword()?;
247 let ascending = if self.consume(&Token::Desc)? {
248 false
249 } else {
250 self.consume(&Token::Asc)?;
251 true
252 };
253 Ok(GraphCommandOrderBy { metric, ascending })
254 }
255
256 fn parse_graph_cycles(&mut self) -> Result<QueryExpr, ParseError> {
258 self.advance()?; let max_length = if self.consume(&Token::MaxLength)? {
260 self.parse_integer()? as u32
261 } else {
262 10
263 };
264 Ok(QueryExpr::GraphCommand(GraphCommand::Cycles { max_length }))
265 }
266
267 fn parse_graph_clustering(&mut self) -> Result<QueryExpr, ParseError> {
269 self.advance()?; Ok(QueryExpr::GraphCommand(GraphCommand::Clustering))
271 }
272
273 fn parse_graph_topological_sort(&mut self) -> Result<QueryExpr, ParseError> {
275 self.advance()?; Ok(QueryExpr::GraphCommand(GraphCommand::TopologicalSort))
277 }
278
279 fn parse_graph_properties(&mut self) -> Result<QueryExpr, ParseError> {
281 self.advance()?; let source = if matches!(self.peek(), Token::String(_)) {
283 Some(self.parse_string()?)
284 } else {
285 None
286 };
287 Ok(QueryExpr::GraphCommand(GraphCommand::Properties { source }))
288 }
289}