1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct GqlQuery {
11 pub clauses: Vec<QueryClause>,
12 pub returning: Option<ReturnClause>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub enum QueryClause {
18 Match(MatchClause),
19 Where(WhereClause),
20 GroupBy(GroupByClause),
21 Having(HavingClause),
22 OrderBy(OrderByClause),
23 Limit(LimitClause),
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct MatchClause {
29 pub optional: bool,
30 pub pattern: GraphPattern,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct GraphPattern {
36 pub path_patterns: Vec<PathPattern>,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct PathPattern {
42 pub variable: Option<String>,
43 pub path_term: PathTerm,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub enum PathTerm {
49 PathElement(PathElement),
50 PathConcatenation(Box<PathTerm>, Box<PathTerm>),
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct PathElement {
56 pub vertex_pattern: VertexPattern,
57 pub edge_patterns: Vec<EdgePattern>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct VertexPattern {
63 pub variable: Option<String>,
64 pub labels: Vec<String>,
65 pub properties: HashMap<String, ValueExpression>,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct EdgePattern {
71 pub variable: Option<String>,
72 pub direction: EdgeDirection,
73 pub labels: Vec<String>,
74 pub properties: HashMap<String, ValueExpression>,
75 pub quantifier: Option<PathQuantifier>,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
80pub enum EdgeDirection {
81 Left, Right, Both, }
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct PathQuantifier {
89 pub min: Option<u32>,
90 pub max: Option<u32>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct WhereClause {
96 pub expression: BooleanExpression,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub enum BooleanExpression {
102 And(Box<BooleanExpression>, Box<BooleanExpression>),
103 Or(Box<BooleanExpression>, Box<BooleanExpression>),
104 Not(Box<BooleanExpression>),
105 Comparison(ComparisonExpression),
106 Exists(Box<GraphPattern>),
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct ComparisonExpression {
112 pub left: Box<ValueExpression>,
113 pub operator: ComparisonOperator,
114 pub right: Box<ValueExpression>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub enum ComparisonOperator {
120 Equal,
121 NotEqual,
122 LessThan,
123 LessThanOrEqual,
124 GreaterThan,
125 GreaterThanOrEqual,
126 Like,
127 Regex,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub enum ValueExpression {
133 Literal(AstValue),
134 Variable(String),
135 PropertyAccess(Box<ValueExpression>, String),
136 FunctionCall(FunctionCall),
137 Arithmetic(ArithmeticExpression),
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct ArithmeticExpression {
143 pub left: Box<ValueExpression>,
144 pub operator: ArithmeticOperator,
145 pub right: Box<ValueExpression>,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
150pub enum ArithmeticOperator {
151 Add,
152 Subtract,
153 Multiply,
154 Divide,
155 Modulo,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct FunctionCall {
161 pub function_name: String,
162 pub arguments: Vec<ValueExpression>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub enum AstValue {
168 Null,
169 Boolean(bool),
170 Integer(i64),
171 Float(f64),
172 String(String),
173 List(Vec<AstValue>),
174 Map(HashMap<String, AstValue>),
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct ReturnClause {
180 pub distinct: bool,
181 pub items: Vec<ReturnItem>,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct ReturnItem {
187 pub expression: ValueExpression,
188 pub alias: Option<String>,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct GroupByClause {
194 pub grouping_keys: Vec<ValueExpression>,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct HavingClause {
200 pub expression: BooleanExpression,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct OrderByClause {
206 pub sort_keys: Vec<SortKey>,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct SortKey {
212 pub expression: ValueExpression,
213 pub direction: SortDirection,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
218pub enum SortDirection {
219 Ascending,
220 Descending,
221}
222
223#[derive(Debug, Clone, Serialize, Deserialize)]
225pub struct LimitClause {
226 pub count: u64,
227 pub offset: Option<u64>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub enum GqlStatement {
233 CreateGraph(CreateGraphStatement),
234 DropGraph(DropGraphStatement),
235 CreateVertex(CreateVertexStatement),
236 CreateEdge(CreateEdgeStatement),
237 Insert(InsertStatement),
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct CreateGraphStatement {
243 pub graph_name: String,
244 pub if_not_exists: bool,
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct DropGraphStatement {
250 pub graph_name: String,
251 pub if_exists: bool,
252}
253
254#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct CreateVertexStatement {
257 pub labels: Vec<String>,
258 pub properties: HashMap<String, ValueExpression>,
259}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
263pub struct CreateEdgeStatement {
264 pub label: String,
265 pub from_vertex: VertexPattern,
266 pub to_vertex: VertexPattern,
267 pub properties: HashMap<String, ValueExpression>,
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct InsertStatement {
273 pub vertex_inserts: Vec<VertexInsert>,
274 pub edge_inserts: Vec<EdgeInsert>,
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct VertexInsert {
280 pub variable: Option<String>,
281 pub labels: Vec<String>,
282 pub properties: HashMap<String, ValueExpression>,
283}
284
285#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct EdgeInsert {
288 pub variable: Option<String>,
289 pub label: String,
290 pub from_vertex: String,
291 pub to_vertex: String,
292 pub properties: HashMap<String, ValueExpression>,
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298
299 #[test]
300 fn test_simple_match_query() {
301 let vertex_pattern = VertexPattern {
304 variable: Some("v".to_string()),
305 labels: vec!["Person".to_string()],
306 properties: HashMap::new(),
307 };
308
309 let path_element = PathElement {
310 vertex_pattern,
311 edge_patterns: Vec::new(),
312 };
313
314 let path_pattern = PathPattern {
315 variable: None,
316 path_term: PathTerm::PathElement(path_element),
317 };
318
319 let match_clause = MatchClause {
320 optional: false,
321 pattern: GraphPattern {
322 path_patterns: vec![path_pattern],
323 },
324 };
325
326 let query = GqlQuery {
327 clauses: vec![QueryClause::Match(match_clause)],
328 returning: Some(ReturnClause {
329 distinct: false,
330 items: vec![ReturnItem {
331 expression: ValueExpression::Variable("v".to_string()),
332 alias: None,
333 }],
334 }),
335 };
336
337 assert_eq!(query.clauses.len(), 1);
339 if let QueryClause::Match(ref match_clause) = &query.clauses[0] {
340 assert!(!match_clause.optional);
341 assert_eq!(match_clause.pattern.path_patterns.len(), 1);
342 }
343 }
344}