Skip to main content

partiql_ast/ast/
graph.rs

1use crate::ast::{AstNode, Expr, SymbolPrimitive};
2use partiql_ast_macros::Visit;
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5use std::num::NonZeroU32;
6
7#[derive(Visit, Clone, Debug, PartialEq)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub struct GraphTable {
10    pub graph_match: AstNode<GraphMatch>,
11}
12
13/// `<expr> MATCH <graph_pattern>`
14#[derive(Visit, Clone, Debug, PartialEq)]
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16pub struct GraphMatch {
17    pub expr: Box<Expr>,
18    pub pattern: AstNode<GraphPattern>,
19    #[visit(skip)]
20    pub shape: GraphTableShape,
21}
22
23#[derive(Visit, Clone, Debug, PartialEq)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct GraphPattern {
26    #[visit(skip)]
27    pub match_mode: Option<GraphMatchMode>,
28    pub patterns: Vec<AstNode<GraphPathPattern>>,
29    #[visit(skip)]
30    pub keep: Option<GraphPathPrefix>,
31    pub where_clause: Option<Box<Expr>>,
32}
33
34#[derive(Clone, Debug, PartialEq, Eq)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[non_exhaustive]
37pub enum GraphMatchMode {
38    /// Edges are not allowed to bind to more than one edge variable in a path
39    DifferentEdges,
40    /// No restrictions on binding of edges or vertices
41    RepeatableElements,
42}
43
44#[derive(Clone, Debug, PartialEq)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46pub struct GraphTableShape {
47    pub rows: Option<AstNode<GraphTableRows>>,
48    pub cols: Option<AstNode<GraphTableColumns>>,
49    pub export: Option<AstNode<GraphTableExport>>,
50}
51
52#[derive(Clone, Default, Debug, PartialEq, Eq)]
53#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
54#[non_exhaustive]
55pub enum GraphTableRows {
56    #[default]
57    OneRowPerMatch,
58    OneRowPerVertex {
59        v: SymbolPrimitive,
60        in_paths: Option<Vec<SymbolPrimitive>>,
61    },
62    OneRowPerStep {
63        v1: SymbolPrimitive,
64        e: SymbolPrimitive,
65        v2: SymbolPrimitive,
66        in_paths: Option<Vec<SymbolPrimitive>>,
67    },
68}
69
70#[derive(Clone, Debug, PartialEq)]
71#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
72pub struct GraphTableColumns {
73    pub columns: Vec<GraphTableColumnDef>,
74}
75
76#[derive(Clone, Debug, PartialEq)]
77#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
78#[non_exhaustive]
79pub enum GraphTableColumnDef {
80    Expr(Box<Expr>, Option<SymbolPrimitive>),
81    AllProperties(SymbolPrimitive),
82}
83
84#[derive(Clone, Debug, PartialEq, Eq)]
85#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
86#[non_exhaustive]
87pub enum GraphTableExport {
88    AllSingletons {
89        except: Option<Vec<SymbolPrimitive>>,
90    },
91    Singletons {
92        exports: Vec<SymbolPrimitive>,
93    },
94    NoSingletons,
95}
96
97/// The direction of an edge
98///
99/// | Orientation               | Edge pattern | Abbreviation |
100/// |---------------------------|--------------|--------------|
101/// | Pointing left             | <−[ spec ]−  | <−           |
102/// | Undirected                | ~[ spec ]~   | ~            |
103/// | Pointing right            | −[ spec ]−>  | −>           |
104/// | Left or undirected        | <~[ spec ]~  | <~           |
105/// | Undirected or right       | ~[ spec ]~>  | ~>           |
106/// | Left or right             | <−[ spec ]−> | <−>          |
107/// | Left, undirected or right | −[ spec ]−   | −            |
108#[derive(Clone, Debug, PartialEq, Eq)]
109#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
110#[non_exhaustive]
111pub enum GraphMatchDirection {
112    Left,
113    Undirected,
114    Right,
115    LeftOrUndirected,
116    UndirectedOrRight,
117    LeftOrRight,
118    LeftOrUndirectedOrRight,
119}
120
121/// A quantifier for graph edges or patterns. (e.g., the `{2,5}` in `MATCH (x)->{2,5}(y)`)
122#[derive(Clone, Debug, PartialEq, Eq)]
123#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
124pub struct GraphMatchQuantifier {
125    pub lower: u32,
126    pub upper: Option<NonZeroU32>,
127}
128
129/// Filters paths. Options other than `Walk` ensure a finite number of matches.
130#[derive(Clone, Debug, PartialEq, Eq)]
131#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
132#[non_exhaustive]
133pub enum GraphPathMode {
134    /// No filtering of edges/nodes.
135    Walk,
136    /// No repeated edges.
137    Trail,
138    /// No repeated nodes.
139    Acyclic,
140    /// No repeated nodes, except that the first and last nodes may be the same.
141    Simple,
142}
143
144/// A single node in a graph pattern.
145#[derive(Visit, Clone, Debug, PartialEq)]
146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
147pub struct GraphMatchNode {
148    /// the optional element variable of the node match, e.g.: `x` in `MATCH (x)`
149    #[visit(skip)]
150    pub variable: Option<SymbolPrimitive>,
151    /// the optional label(s) to match for the node, e.g.: `Entity` in `MATCH (x:Entity)`
152    #[visit(skip)]
153    pub label: Option<AstNode<GraphMatchLabel>>,
154    /// an optional node where clause, e.g.: `WHERE c.name='Alarm'` in `MATCH (c WHERE c.name='Alarm')`
155    pub where_clause: Option<Box<Expr>>,
156}
157
158/// A single edge in a graph pattern.
159#[derive(Visit, Clone, Debug, PartialEq)]
160#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
161pub struct GraphMatchEdge {
162    /// edge direction
163    #[visit(skip)]
164    pub direction: GraphMatchDirection,
165    /// the optional element variable of the edge match, e.g.: `t` in `MATCH −[t]−>`
166    #[visit(skip)]
167    pub variable: Option<SymbolPrimitive>,
168    /// the optional label(s) to match for the edge. e.g.: `Target` in `MATCH −[t:Target]−>`
169    #[visit(skip)]
170    pub label: Option<AstNode<GraphMatchLabel>>,
171    /// an optional edge where clause, e.g.: `WHERE t.capacity>100` in `MATCH −[t:hasSupply WHERE t.capacity>100]−>`
172    pub where_clause: Option<Box<Expr>>,
173}
174
175#[derive(Clone, Debug, PartialEq)]
176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
177#[non_exhaustive]
178pub enum GraphMatchLabel {
179    Name(SymbolPrimitive),
180    Wildcard,
181    Negated(Box<AstNode<GraphMatchLabel>>),
182    Conjunction(Vec<AstNode<GraphMatchLabel>>),
183    Disjunction(Vec<AstNode<GraphMatchLabel>>),
184}
185
186#[derive(Visit, Clone, Debug, PartialEq)]
187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
188pub struct GraphPathPattern {
189    /// the optional element variable of the pattern, e.g.: `p` in `MATCH p = (a) −[t]−> (b)`
190    #[visit(skip)]
191    pub variable: Option<SymbolPrimitive>,
192    #[visit(skip)]
193    pub prefix: Option<GraphPathPrefix>,
194    /// the ordered pattern parts
195    pub path: AstNode<GraphMatchPathPattern>,
196}
197
198#[derive(Visit, Clone, Debug, PartialEq)]
199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
200pub struct GraphPathSubPattern {
201    /// the optional element variable of the pattern, e.g.: `p` in `MATCH p = (a) −[t]−> (b)`
202    #[visit(skip)]
203    pub variable: Option<SymbolPrimitive>,
204    #[visit(skip)]
205    pub mode: Option<GraphPathMode>,
206    /// the ordered pattern parts
207    pub path: AstNode<GraphMatchPathPattern>,
208    /// an optional pattern where e.g.: `WHERE a.name=b.name` in `MATCH [(a)->(b) WHERE a.name=b.name]`
209    pub where_clause: Option<Box<Expr>>,
210}
211
212#[derive(Visit, Clone, Debug, PartialEq)]
213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
214#[non_exhaustive]
215pub enum GraphMatchPathPattern {
216    Path(Vec<AstNode<GraphMatchPathPattern>>),
217    Union(Vec<AstNode<GraphMatchPathPattern>>),
218    Multiset(Vec<AstNode<GraphMatchPathPattern>>),
219
220    Questioned(Box<AstNode<GraphMatchPathPattern>>),
221    Quantified(GraphMatchPathPatternQuantified),
222
223    Sub(Box<AstNode<GraphPathSubPattern>>),
224
225    /// A single node in a graph pattern.
226    Node(AstNode<GraphMatchNode>),
227
228    /// A single edge in a graph pattern.
229    Edge(AstNode<GraphMatchEdge>),
230
231    #[visit(skip)]
232    Simplified(AstNode<GraphMatchSimplified>),
233}
234
235#[derive(Visit, Clone, Debug, PartialEq)]
236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
237pub struct GraphMatchPathPatternQuantified {
238    pub path: Box<AstNode<GraphMatchPathPattern>>,
239    #[visit(skip)]
240    pub quant: AstNode<GraphMatchQuantifier>,
241}
242
243#[derive(Clone, Debug, PartialEq)]
244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
245pub struct GraphMatchElement {
246    pub variable: Option<SymbolPrimitive>,
247    pub label: Option<AstNode<GraphMatchLabel>>,
248    pub where_clause: Option<Box<Expr>>,
249}
250
251#[derive(Clone, Debug, PartialEq)]
252#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
253pub struct GraphMatchSimplified {
254    pub dir: GraphMatchDirection,
255    pub pattern: AstNode<GraphMatchSimplifiedPattern>,
256}
257
258#[derive(Clone, Debug, PartialEq)]
259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
260#[non_exhaustive]
261pub enum GraphMatchSimplifiedPattern {
262    Union(Vec<AstNode<GraphMatchSimplifiedPattern>>),
263    Multiset(Vec<AstNode<GraphMatchSimplifiedPattern>>),
264
265    Path(Vec<AstNode<GraphMatchSimplifiedPattern>>),
266    Sub(Box<AstNode<GraphMatchSimplifiedPattern>>),
267
268    Conjunction(Vec<AstNode<GraphMatchSimplifiedPattern>>),
269
270    Questioned(Box<AstNode<GraphMatchSimplifiedPattern>>),
271    Quantified(GraphMatchSimplifiedPatternQuantified),
272
273    /// Direction override
274    Direction(GraphMatchSimplifiedPatternDirected),
275
276    Negated(Box<AstNode<GraphMatchSimplifiedPattern>>),
277    Label(SymbolPrimitive),
278}
279
280#[derive(Clone, Debug, PartialEq)]
281#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
282pub struct GraphMatchSimplifiedPatternQuantified {
283    pub path: Box<AstNode<GraphMatchSimplifiedPattern>>,
284    pub quant: AstNode<GraphMatchQuantifier>,
285}
286
287#[derive(Clone, Debug, PartialEq)]
288#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
289pub struct GraphMatchSimplifiedPatternDirected {
290    pub dir: GraphMatchDirection,
291    pub path: Box<AstNode<GraphMatchSimplifiedPattern>>,
292}
293
294#[derive(Clone, Debug, PartialEq, Eq)]
295#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
296#[non_exhaustive]
297pub enum GraphPathPrefix {
298    Mode(GraphPathMode),
299    Search(GraphPathSearchPrefix, Option<GraphPathMode>),
300}
301
302/// | Keyword
303/// |------------------
304/// | ALL
305/// | Any
306/// | ANY k
307/// | ALL SHORTEST
308/// | ANY SHORTEST
309/// | SHORTEST k
310/// | SHORTEST k GROUP
311#[derive(Clone, Debug, PartialEq, Eq)]
312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
313#[non_exhaustive]
314pub enum GraphPathSearchPrefix {
315    All,
316    Any,
317    AnyK(NonZeroU32),
318    AllShortest,
319    AnyShortest,
320    ShortestK(NonZeroU32),
321    ShortestKGroup(Option<NonZeroU32>),
322}