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 loop {
185 if algorithm.is_none() && self.consume(&Token::Algorithm)? {
186 algorithm = Some(self.expect_ident_or_keyword()?);
187 } else if max_iterations.is_none() && self.consume(&Token::MaxIterations)? {
188 max_iterations = Some(self.parse_integer()? as u32);
189 } else if order_by.is_none() && self.consume(&Token::Order)? {
190 order_by = Some(self.parse_graph_order_by_tail()?);
191 } else if limit.is_none() && self.consume(&Token::Limit)? {
192 let n = self.parse_integer()?;
193 limit = Some(n as u32);
194 } else {
195 break;
196 }
197 }
198 Ok(QueryExpr::GraphCommand(GraphCommand::Community {
199 algorithm: algorithm.unwrap_or_else(|| "label_propagation".to_string()),
200 max_iterations: max_iterations.unwrap_or(100),
201 limit,
202 order_by,
203 }))
204 }
205
206 fn parse_graph_components(&mut self) -> Result<QueryExpr, ParseError> {
208 self.advance()?; let mut mode: Option<String> = None;
210 let mut limit: Option<u32> = None;
211 let mut order_by: Option<GraphCommandOrderBy> = None;
212 loop {
213 if mode.is_none() && self.consume(&Token::Mode)? {
214 mode = Some(self.expect_ident_or_keyword()?);
215 } else if order_by.is_none() && self.consume(&Token::Order)? {
216 order_by = Some(self.parse_graph_order_by_tail()?);
217 } else if limit.is_none() && self.consume(&Token::Limit)? {
218 let n = self.parse_integer()?;
219 limit = Some(n as u32);
220 } else {
221 break;
222 }
223 }
224 Ok(QueryExpr::GraphCommand(GraphCommand::Components {
225 mode: mode.unwrap_or_else(|| "connected".to_string()),
226 limit,
227 order_by,
228 }))
229 }
230
231 fn parse_graph_order_by_tail(&mut self) -> Result<GraphCommandOrderBy, ParseError> {
232 self.expect(Token::By)?;
233 let metric = self.expect_ident_or_keyword()?;
234 let ascending = if self.consume(&Token::Desc)? {
235 false
236 } else {
237 self.consume(&Token::Asc)?;
238 true
239 };
240 Ok(GraphCommandOrderBy { metric, ascending })
241 }
242
243 fn parse_graph_cycles(&mut self) -> Result<QueryExpr, ParseError> {
245 self.advance()?; let max_length = if self.consume(&Token::MaxLength)? {
247 self.parse_integer()? as u32
248 } else {
249 10
250 };
251 Ok(QueryExpr::GraphCommand(GraphCommand::Cycles { max_length }))
252 }
253
254 fn parse_graph_clustering(&mut self) -> Result<QueryExpr, ParseError> {
256 self.advance()?; Ok(QueryExpr::GraphCommand(GraphCommand::Clustering))
258 }
259
260 fn parse_graph_topological_sort(&mut self) -> Result<QueryExpr, ParseError> {
262 self.advance()?; Ok(QueryExpr::GraphCommand(GraphCommand::TopologicalSort))
264 }
265
266 fn parse_graph_properties(&mut self) -> Result<QueryExpr, ParseError> {
268 self.advance()?; let source = if matches!(self.peek(), Token::String(_)) {
270 Some(self.parse_string()?)
271 } else {
272 None
273 };
274 Ok(QueryExpr::GraphCommand(GraphCommand::Properties { source }))
275 }
276}