Skip to content

Commit a25262c

Browse files
committed
Experimental support for MATCH as expr.
- Still doesn't allow edge as first part of a non-nested pattern - Requires parens around entire MATCH expression
1 parent f4931e5 commit a25262c

File tree

3 files changed

+272
-242
lines changed

3 files changed

+272
-242
lines changed

partiql-ast/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ pub enum Expr {
208208
Like(AstNode<Like>),
209209
Between(AstNode<Between>),
210210
In(AstNode<In>),
211+
/// <expr> MATCH <graph_pattern>
212+
GraphMatch(AstNode<GraphMatch>),
211213
Case(AstNode<Case>),
212214
/// Constructors
213215
Struct(AstNode<Struct>),
@@ -535,8 +537,6 @@ pub enum FromClause {
535537
FromLet(AstNode<FromLet>),
536538
/// <from_source> JOIN \[INNER | LEFT | RIGHT | FULL\] <from_source> ON <expr>
537539
Join(AstNode<Join>),
538-
/// <expr> MATCH <graph_pattern>
539-
GraphMatch(AstNode<GraphMatch>),
540540
}
541541

542542
#[derive(Clone, Debug, PartialEq)]

partiql-parser/src/parse/mod.rs

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -684,111 +684,120 @@ mod tests {
684684

685685
#[test]
686686
fn no_labels() {
687-
parse!(r#"SELECT 1 FROM my_graph MATCH ()"#);
688-
parse!(r#"SELECT 1 FROM my_graph MATCH () WHERE contains_value('1')"#);
689-
parse!(r#"SELECT x.info AS info FROM my_graph MATCH (x) WHERE x.name LIKE 'foo'"#);
690-
//parse!(r#"SELECT 1 FROM g MATCH -[]-> "#);
687+
parse!(r#"SELECT 1 FROM (my_graph MATCH ())"#);
688+
parse!(r#"SELECT 1 FROM (my_graph MATCH ()) WHERE contains_value('1')"#);
689+
parse!(r#"SELECT x.info AS info FROM (my_graph MATCH (x)) WHERE x.name LIKE 'foo'"#);
690+
// TODO fails due to edge first
691+
// parse!(r#"SELECT 1 FROM (g MATCH -[]->) "#);
692+
}
693+
694+
#[test]
695+
fn lone_match_expr() {
696+
parse!(r#"(MyGraph MATCH (x))"#);
697+
parse!(r#"(MyGraph MATCH (x), (y) )"#);
698+
// TODO fails due to edge first
699+
//parse!(r#"(MyGraph MATCH (x), -[u]-> )"#);
691700
}
692701

693702
#[test]
694703
fn labelled_nodes() {
695-
parse!(r#"SELECT x AS target FROM my_graph MATCH (x:Label) WHERE x.has_data = true"#);
704+
parse!(r#"SELECT x AS target FROM (my_graph MATCH (x:Label)) WHERE x.has_data = true"#);
696705
}
697706

698707
#[test]
699708
fn edges() {
700-
parse!(r#"SELECT a,b FROM g MATCH (a:A) -[e:E]-> (b:B)"#);
701-
parse!(r#"SELECT a,b FROM g MATCH (a:A) -> (b:B)"#);
702-
parse!(r#"SELECT a,b FROM g MATCH (a:A) ~[e:E]~ (b:B)"#);
703-
parse!(r#"SELECT a,b FROM g MATCH (a:A) ~ (b:B)"#);
704-
parse!(r#"SELECT a,b FROM g MATCH (a:A) <-[e:E]- (b:B)"#);
705-
parse!(r#"SELECT a,b FROM g MATCH (a:A) <- (b:B)"#);
706-
parse!(r#"SELECT a,b FROM g MATCH (a:A) ~[e:E]~> (b:B)"#);
707-
parse!(r#"SELECT a,b FROM g MATCH (a:A) ~> (b:B)"#);
708-
parse!(r#"SELECT a,b FROM g MATCH (a:A) <~[e:E]~ (b:B)"#);
709-
parse!(r#"SELECT a,b FROM g MATCH (a:A) <~ (b:B)"#);
710-
parse!(r#"SELECT a,b FROM g MATCH (a:A) <-[e:E]-> (b:B)"#);
711-
parse!(r#"SELECT a,b FROM g MATCH (a:A) <-> (b:B)"#);
712-
parse!(r#"SELECT a,b FROM g MATCH (a:A) -[e:E]- (b:B)"#);
713-
parse!(r#"SELECT a,b FROM g MATCH (a:A) - (b:B)"#);
709+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) -[e:E]-> (b:B))"#);
710+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) -> (b:B))"#);
711+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) ~[e:E]~ (b:B))"#);
712+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) ~ (b:B))"#);
713+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) <-[e:E]- (b:B))"#);
714+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) <- (b:B))"#);
715+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) ~[e:E]~> (b:B))"#);
716+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) ~> (b:B))"#);
717+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) <~[e:E]~ (b:B))"#);
718+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) <~ (b:B))"#);
719+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) <-[e:E]-> (b:B))"#);
720+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) <-> (b:B))"#);
721+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) -[e:E]- (b:B))"#);
722+
parse!(r#"SELECT a,b FROM (g MATCH (a:A) - (b:B))"#);
714723
}
715724

716725
#[test]
717726
fn quantifiers() {
718-
parse!(r#"SELECT a,b FROM g MATCH (a:A)-[:edge]->*(b:B)"#);
719-
parse!(r#"SELECT a,b FROM g MATCH (a:A)<-[:edge]-+(b:B)"#);
720-
parse!(r#"SELECT a,b FROM g MATCH (a:A)~[:edge]~{5,}(b:B)"#);
721-
parse!(r#"SELECT a,b FROM g MATCH (a:A)-[e:edge]-{2,6}(b:B)"#);
722-
parse!(r#"SELECT a,b FROM g MATCH (a:A)->*(b:B)"#);
723-
parse!(r#"SELECT a,b FROM g MATCH (a:A)<-+(b:B)"#);
724-
parse!(r#"SELECT a,b FROM g MATCH (a:A)~{5,}(b:B)"#);
725-
parse!(r#"SELECT a,b FROM g MATCH (a:A)-{2,6}(b:B)"#);
727+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)-[:edge]->*(b:B))"#);
728+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)<-[:edge]-+(b:B))"#);
729+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)~[:edge]~{5,}(b:B))"#);
730+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)-[e:edge]-{2,6}(b:B))"#);
731+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)->*(b:B))"#);
732+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)<-+(b:B))"#);
733+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)~{5,}(b:B))"#);
734+
parse!(r#"SELECT a,b FROM (g MATCH (a:A)-{2,6}(b:B))"#);
726735
}
727736

728737
#[test]
729738
fn patterns() {
730739
parse!(
731-
r#"SELECT the_a.name AS src, the_b.name AS dest FROM my_graph MATCH (the_a:a) -[the_y:y]-> (the_b:b) WHERE the_y.score > 10"#
740+
r#"SELECT the_a.name AS src, the_b.name AS dest FROM (my_graph MATCH (the_a:a) -[the_y:y]-> (the_b:b)) WHERE the_y.score > 10"#
732741
);
733-
parse!(r#""SELECT a,b FROM g MATCH (a)-[:has]->()-[:contains]->(b)""#);
742+
parse!(r#""SELECT a,b FROM (g MATCH (a)-[:has]->()-[:contains]->(b))""#);
734743
parse!(r#"SELECT a,b FROM (g MATCH (a) -[:has]-> (x), (x)-[:contains]->(b))"#);
735744
}
736745

737746
#[test]
738747
fn path_var() {
739-
parse!(r#"SELECT a,b FROM g MATCH p = (a:A) -[e:E]-> (b:B)"#);
748+
parse!(r#"SELECT a,b FROM (g MATCH p = (a:A) -[e:E]-> (b:B))"#);
740749
}
741750

742751
#[test]
743752
fn paranthesized() {
744-
parse!(r#"SELECT a,b FROM g MATCH [(a:A)-[e:Edge]->(b:A) WHERE a.owner=b.owner]{2,5}"#);
745-
parse!(r#"SELECT a,b FROM g MATCH pathVar = (a:A)[()-[e:Edge]->()]{1,3}(b:B)"#);
753+
parse!(r#"SELECT a,b FROM (g MATCH [(a:A)-[e:Edge]->(b:A) WHERE a.owner=b.owner]{2,5})"#);
754+
parse!(r#"SELECT a,b FROM (g MATCH pathVar = (a:A)[()-[e:Edge]->()]{1,3}(b:B))"#);
746755

747756
// brackets
748-
parse!(r#"SELECT a,b FROM g MATCH pathVar = (a:A)[-[e:Edge]->]*(b:B)"#);
757+
parse!(r#"SELECT a,b FROM (g MATCH pathVar = (a:A)[-[e:Edge]->]*(b:B))"#);
749758
// parens
750-
parse!(r#"SELECT a,b FROM g MATCH pathVar = (a:A)(-[e:Edge]->)*(b:B)"#);
759+
parse!(r#"SELECT a,b FROM (g MATCH pathVar = (a:A)(-[e:Edge]->)*(b:B))"#);
751760
}
752761

753762
#[test]
754763
fn filters() {
755764
parse!(
756-
r#"SELECT u as banCandidate FROM g MATCH (p:Post Where p.isFlagged = true) <-[:createdPost]- (u:User WHERE u.isBanned = false AND u.karma < 20) -[:createdComment]->(c:Comment WHERE c.isFlagged = true) WHERE p.title LIKE '%considered harmful%'"#
765+
r#"SELECT u as banCandidate FROM (g MATCH (p:Post Where p.isFlagged = true) <-[:createdPost]- (u:User WHERE u.isBanned = false AND u.karma < 20) -[:createdComment]->(c:Comment WHERE c.isFlagged = true)) WHERE p.title LIKE '%considered harmful%'"#
757766
);
758767
}
759768

760769
#[test]
761770
fn restrictors() {
762771
parse!(
763-
r#"SELECT p FROM g MATCH TRAIL p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
772+
r#"SELECT p FROM (g MATCH TRAIL p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
764773
);
765774
parse!(
766-
r#"SELECT p FROM g MATCH SIMPLE p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
775+
r#"SELECT p FROM (g MATCH SIMPLE p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
767776
);
768777
parse!(
769-
r#"SELECT p FROM g MATCH ACYCLIC p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
778+
r#"SELECT p FROM (g MATCH ACYCLIC p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
770779
);
771780
}
772781

773782
#[test]
774783
fn selectors() {
775784
parse!(
776-
r#"SELECT p FROM g MATCH ANY SHORTEST p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
785+
r#"SELECT p FROM (g MATCH ANY SHORTEST p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
777786
);
778787
parse!(
779-
r#"SELECT p FROM g MATCH ALL SHORTEST p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
788+
r#"SELECT p FROM (g MATCH ALL SHORTEST p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
780789
);
781790
parse!(
782-
r#"SELECT p FROM g MATCH ANY p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
791+
r#"SELECT p FROM (g MATCH ANY p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
783792
);
784793
parse!(
785-
r#"SELECT p FROM g MATCH ANY 5 p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
794+
r#"SELECT p FROM (g MATCH ANY 5 p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
786795
);
787796
parse!(
788-
r#"SELECT p FROM g MATCH SHORTEST 5 p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
797+
r#"SELECT p FROM (g MATCH SHORTEST 5 p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
789798
);
790799
parse!(
791-
r#"SELECT p FROM g MATCH SHORTEST 5 GROUP p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha')"#
800+
r#"SELECT p FROM (g MATCH SHORTEST 5 GROUP p = (a WHERE a.owner='Dave') -[t:Transfer]-> * (b WHERE b.owner='Aretha'))"#
792801
);
793802
}
794803

@@ -799,10 +808,16 @@ mod tests {
799808
);
800809
}
801810

811+
#[test]
812+
fn union() {
813+
parse!(r#"(MyGraph MATCH (x)) UNION SELECT * FROM tbl1"#);
814+
parse!(r#"SELECT * FROM tbl1 UNION (MyGraph MATCH (x))"#);
815+
}
816+
802817
#[test]
803818
fn etc() {
804-
parse!("SELECT * FROM g MATCH ALL SHORTEST [ (x)-[e]->*(y) ]");
805-
parse!("SELECT * FROM g MATCH ALL SHORTEST [ TRAIL (x)-[e]->*(y) ]");
819+
parse!("SELECT * FROM (g MATCH ALL SHORTEST [ (x)-[e]->*(y) ])");
820+
parse!("SELECT * FROM (g MATCH ALL SHORTEST [ TRAIL (x)-[e]->*(y) ])");
806821
}
807822
}
808823

0 commit comments

Comments
 (0)