Skip to content

Commit 6dd1cd3

Browse files
authored
Update Graph query support for SQL 2023 conformance (#552)
* GRAPH_TABLE Syntax * GRAPH_TABLE AST * GRAPH_TABLE pretty print & lexer/parser updates for non-reserved keywords * GRAPH_TABLE updates to logical plan lowering * Update to latest conformance tests
1 parent 38cc1e5 commit 6dd1cd3

File tree

108 files changed

+4723
-1448
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+4723
-1448
lines changed

extension/partiql-extension-visualize/src/ast_to_dot.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ impl ToDot<ast::FromLet> for AstToDot {
508508
let lbl = match &ast.kind {
509509
ast::FromLetKind::Scan => "Scan",
510510
ast::FromLetKind::Unpivot => "Unpivot",
511+
ast::FromLetKind::GraphTable => "GRAPH_TABLE",
511512
};
512513
let id = out.node_auto_labelled(lbl).id();
513514

partiql-ast/src/ast/graph.rs

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

0 commit comments

Comments
 (0)