Skip to content

Commit

Permalink
range literal
Browse files Browse the repository at this point in the history
  • Loading branch information
AEsir777 committed Sep 13, 2023
1 parent defa82b commit ab0c9e0
Show file tree
Hide file tree
Showing 8 changed files with 3,229 additions and 2,908 deletions.
9 changes: 8 additions & 1 deletion src/antlr4/Cypher.g4
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,14 @@ oC_NodeLabel
: ':' SP? oC_LabelName ;

oC_RangeLiteral
: '*' SP? ( SHORTEST | ALL SP SHORTEST )? SP? oC_IntegerLiteral SP? '..' SP? oC_IntegerLiteral (SP? '(' SP? oC_Variable SP? ',' SP? '_' SP? '|' SP? oC_Where SP? ')')? ;
: '*' SP? ( SHORTEST | ALL SP SHORTEST )? SP? (oC_LowerBound? SP? '..' SP? oC_UpperBound? | oC_IntegerLiteral)? (SP? '(' SP? oC_Variable SP? ',' SP? '_' SP? '|' SP? oC_Where SP? ')')? ;

oC_LowerBound
: DecimalInteger ;

oC_UpperBound
: DecimalInteger ;


SHORTEST : ( 'S' | 's' ) ( 'H' | 'h' ) ( 'O' | 'o' ) ( 'R' | 'r' ) ( 'T' | 't' ) ( 'E' | 'e' ) ( 'S' | 's' ) ( 'T' | 't' ) ;

Expand Down
18 changes: 14 additions & 4 deletions src/binder/bind/bind_graph_pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,20 @@ std::shared_ptr<RelExpression> Binder::createRecursiveQueryRel(const parser::Rel
std::pair<uint64_t, uint64_t> Binder::bindVariableLengthRelBound(
const kuzu::parser::RelPattern& relPattern) {
auto recursiveInfo = relPattern.getRecursiveInfo();
auto lowerBound = std::min(TypeUtils::convertToUint32(recursiveInfo->lowerBound.c_str()),
clientContext->varLengthExtendMaxDepth);
auto upperBound = std::min(TypeUtils::convertToUint32(recursiveInfo->upperBound.c_str()),
clientContext->varLengthExtendMaxDepth);
auto lowerBound = TypeUtils::convertToUint32(recursiveInfo->lowerBound.c_str());
auto upperBound = clientContext->varLengthExtendMaxDepth;
if (!recursiveInfo->upperBound.empty()) {
upperBound = TypeUtils::convertToUint32(recursiveInfo->upperBound.c_str());
}

if (lowerBound > clientContext->varLengthExtendMaxDepth) {
throw BinderException("Lower bound of rel exceeds maximum: " +
std::to_string(clientContext->varLengthExtendMaxDepth) + ".");
}
if (upperBound > clientContext->varLengthExtendMaxDepth) {
throw BinderException("Upper bound of rel exceeds maximum: " +
std::to_string(clientContext->varLengthExtendMaxDepth) + ".");
}
if (lowerBound == 0 || upperBound == 0) {
throw BinderException("Lower and upper bound of a rel must be greater than 0.");
}
Expand Down
16 changes: 14 additions & 2 deletions src/parser/transform/transform_graph_pattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,20 @@ std::unique_ptr<RelPattern> Transformer::transformRelationshipPattern(
relType = QueryRelType::VARIABLE_LENGTH;
}
auto range = relDetail->oC_RangeLiteral();
auto lowerBound = range->oC_IntegerLiteral()[0]->getText();
auto upperBound = range->oC_IntegerLiteral()[1]->getText();
auto lowerBound = std::string("1");
auto upperBound = std::string("");

if (range->oC_IntegerLiteral()) {
lowerBound = range->oC_IntegerLiteral()->getText();
upperBound = lowerBound;
}
if (range->oC_LowerBound()) {
lowerBound = range->oC_LowerBound()->getText();
}
if (range->oC_UpperBound()) {
upperBound = range->oC_UpperBound()->getText();
}

auto recursiveRelName = std::string();
std::unique_ptr<ParsedExpression> whereExpression = nullptr;
if (range->oC_Where()) {
Expand Down
8 changes: 3 additions & 5 deletions test/test_files/tck/match/match3.test
Original file line number Diff line number Diff line change
Expand Up @@ -304,13 +304,11 @@ a
---- ok
-STATEMENT CREATE NODE TABLE C(ID SERIAL,PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE REL TABLE T1(FROM A TO B);
---- ok
-STATEMENT CREATE REL TABLE T2(FROM A TO C);
-STATEMENT CREATE REL TABLE GROUP T(FROM A TO B, FROM A TO C);
---- ok
-STATEMENT CREATE (a:A), (b:B), (c:C)
CREATE (a)-[:T1]->(b),
(a)-[:T2]->(c);
CREATE (a)-[:T]->(b),
(a)-[:T]->(c);
---- ok
-STATEMENT MATCH (a)-->(b)
MATCH (c)-->(d)
Expand Down
79 changes: 40 additions & 39 deletions test/test_files/tck/match/match4.test
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

# Simple variable length pattern
-CASE Scenario2
-SKIP
-STATEMENT CREATE NODE TABLE A(ID SERIAL, name STRING, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE REL TABLE CONTAIN(FROM A TO A);
Expand Down Expand Up @@ -66,20 +65,20 @@
-STATEMENT CREATE REL TABLE T(FROM A TO A);
---- ok
# indexing on varlist causes segmentaion fault
#-STATEMENT CREATE (a {var: 'start'}), (b {var: 'end'})
# WITH *
# UNWIND ['0', '1', '2'] AS i
# CREATE (n {var: i})
# WITH a, b, collect(n) AS nodeList
# UNWIND [0, 1] AS i
# WITH nodeList[i] AS n1, nodeList[i+1] AS n2
# CREATE (n1)-[:T]->(n2);
#---- ok
#-STATEMENT WITH collect(n) AS nodeList
# UNWIND [0, 1] AS i
# WITH nodeList[i] AS n1, nodeList[i+1] AS n2
# CREATE (n1)-[:T]->(n2);
#---- ok
-STATEMENT CREATE (a {var: 'start'}), (b {var: 'end'})
WITH *
UNWIND ['0', '1', '2'] AS i
CREATE (n {var: i})
WITH a, b, collect(n) AS nodeList
UNWIND [0, 1] AS i
WITH nodeList[i] AS n1, nodeList[i+1] AS n2
CREATE (n1)-[:T]->(n2);
---- ok
-STATEMENT WITH collect(n) AS nodeList
UNWIND [0, 1] AS i
WITH nodeList[i] AS n1, nodeList[i+1] AS n2
CREATE (n1)-[:T]->(n2);
---- ok
-STATEMENT CREATE (a {var: 'start'}), (b {var: 'end'})
WITH *
UNWIND range(1, 20) AS i
Expand All @@ -96,7 +95,6 @@

# Matching variable length pattern with property predicate
-CASE Scenario5
-SKIP
-STATEMENT CREATE NODE TABLE Artist(ID SERIAL, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE REL TABLE WORKED_WITH(FROM Artist TO Artist, year INT64);
Expand All @@ -116,7 +114,6 @@

# Matching variable length patterns from a bound node
-CASE Scenario6
-SKIP
-STATEMENT CREATE NODE TABLE A(ID SERIAL, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE REL TABLE X(FROM A To A);
Expand Down Expand Up @@ -163,13 +160,11 @@
---- ok
-STATEMENT CREATE NODE TABLE C(ID SERIAL, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE NODE TABLE A(ID SERIAL, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE REL TABLE Y2(FROM B TO C);
-STATEMENT CREATE REL TABLE GROUP Y(FROM A TO B, FROM B TO C);
---- ok
-STATEMENT CREATE (a:A), (b:B), (c:C)
CREATE (a)-[:Y1]->(b),
(b)-[:Y2]->(c)
CREATE (a)-[:Y]->(b),
(b)-[:Y]->(c)
---- ok
-STATEMENT MATCH ()-[r1]->()-[r2]->()
WITH [r1, r2] AS rs
Expand All @@ -184,23 +179,29 @@
-CASE Scenario9&10
-STATEMENT CREATE NODE TABLE A(ID SERIAL, name STRING, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE REL TABLE LIKES(FROM A TO A);
---- ok
-STATEMENT CREATE (n0 {name: 'n0'}),
(n00 {name: 'n00'}),
(n01 {name: 'n01'}),
(n000 {name: 'n000'}),
(n001 {name: 'n001'}),
(n010 {name: 'n010'}),
(n011 {name: 'n011'}),
(n0000 {name: 'n0000'}),
(n0001 {name: 'n0001'}),
(n0010 {name: 'n0010'}),
(n0011 {name: 'n0011'}),
(n0100 {name: 'n0100'}),
(n0101 {name: 'n0101'}),
(n0110 {name: 'n0110'}),
(n0111 {name: 'n0111'})
-STATEMENT CREATE NODE TABLE B(ID SERIAL, name STRING, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE NODE TABLE C(ID SERIAL, name STRING, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE NODE TABLE D(ID SERIAL, name STRING, PRIMARY KEY(ID));
---- ok
-STATEMENT CREATE REL TABLE GROUP LIKES(FROM A TO B, FROM B TO C, FROM C TO D);
---- ok
-STATEMENT CREATE (n0:A {name: 'n0'}),
(n00:B {name: 'n00'}),
(n01:B {name: 'n01'}),
(n000:C {name: 'n000'}),
(n001:C {name: 'n001'}),
(n010:C {name: 'n010'}),
(n011:C {name: 'n011'}),
(n0000:D {name: 'n0000'}),
(n0001:D {name: 'n0001'}),
(n0010:D {name: 'n0010'}),
(n0011:D {name: 'n0011'}),
(n0100:D {name: 'n0100'}),
(n0101:D {name: 'n0101'}),
(n0110:D {name: 'n0110'}),
(n0111:D {name: 'n0111'})
CREATE (n0)-[:LIKES]->(n00),
(n0)-[:LIKES]->(n01),
(n00)-[:LIKES]->(n000),
Expand Down
125 changes: 125 additions & 0 deletions test/test_files/tinysnb/var_length_extend/range_literal.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
-GROUP TinySnbReadTest
-DATASET CSV tinysnb

--

-CASE SingleUpperBound
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:knows*..2]->(b:person) RETURN COUNT(*);
---- 1
12
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:knows*..1]->(b:person) RETURN b.fName;
---- 3
Bob
Carol
Dan

-CASE SingleLowerBound
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*2..]->(b:person) RETURN a.fName, b.fName;
---- 1
Alice|Dan
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*3..]->(b:person) RETURN a.fName, b.fName;
---- 0
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*1..]->(b:person) RETURN a.fName, b.fName;
---- 2
Alice|Bob
Alice|Dan

-CASE SingleNodeBound
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*2]->(b:person) RETURN b.fName;
---- 1
Dan
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*1]->(b:person) RETURN b.fName;
---- 1
Bob
-STATEMENT MATCH(a:person {fName: "Elizabeth"})-[e:meets*1]-(b:person) RETURN b.fName;
---- 2
Carol
Carol
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*3]->(b:person) RETURN b.fName;
---- 0
-STATEMENT CALL var_length_extend_max_depth=10;
---- ok
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*]-(b:person) RETURN COUNT(*);
---- 1
484

-CASE BothBound
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*1..1]->(b:person) RETURN b.fName;
---- 1
Bob
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)-[:meets]->(b:person {ID: 11, fName: "Mike"});
---- ok
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*1..3]->(b:person) RETURN b.fName;
---- 3
Bob
Dan
Mike
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*2..3]->(b:person) RETURN b.fName;
---- 2
Dan
Mike
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*3..3]->(b:person) RETURN b.fName;
---- 1
Mike
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*3..4]->(b:person) RETURN b.fName;
---- 1
Mike

-CASE SingleAsterisk
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)-[:meets]->(b:person {ID: 11, fName: "Mike"});
---- ok
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*]->(b:person) RETURN b.fName;
---- 3
Bob
Dan
Mike
-STATEMENT MATCH(a:person {fName: "Bob"})<-[e:meets*]-(b:person) RETURN b.fName;
---- 2
Alice
Hubert Blaine Wolfeschlegelsteinhausenbergerdorff

-CASE NoBound
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)-[:meets]->(b:person {ID: 11, fName: "Mike"});
---- ok
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*..]->(b:person) RETURN b.fName;
---- 3
Bob
Dan
Mike
-STATEMENT MATCH(a:person {fName: "Bob"})<-[e:meets*..]-(b:person) RETURN b.fName;
---- 2
Alice
Hubert Blaine Wolfeschlegelsteinhausenbergerdorff

-CASE CreateRangeLiteralTest
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)-[:meets*]->(b:person {ID: 11, fName: "Mike"});
---- error
QueryPlanner::getProperties
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)<-[:meets*..]-(b:person {ID: 11, fName: "Mike"});
---- error
QueryPlanner::getProperties
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)-[:meets*2]-(b:person {ID: 11, fName: "Mike"});
---- error
QueryPlanner::getProperties
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)-[:meets*2..4]->(b:person {ID: 11, fName: "Mike"});
---- error
QueryPlanner::getProperties
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)<-[:meets*3..]-(b:person {ID: 11, fName: "Mike"});
---- error
QueryPlanner::getProperties
-STATEMENT MATCH (c:person) WHERE c.fName="Dan" CREATE(c)-[:meets*..3]->(b:person {ID: 11, fName: "Mike"});
---- error
QueryPlanner::getProperties

-CASE ExceedsVarLengthExceptionTest
-STATEMENT CALL var_length_extend_max_depth=10;
---- ok
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*11..23]->(b:person) RETURN b.fName;
---- error
Binder exception: Lower bound of rel exceeds maximum: 10.
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*..11]->(b:person) RETURN b.fName;
---- error
Binder exception: Upper bound of rel exceeds maximum: 10.
-STATEMENT MATCH(a:person {fName: "Alice"})-[e:meets*11]->(b:person) RETURN b.fName;
---- error
Binder exception: Lower bound of rel exceeds maximum: 10.
Loading

0 comments on commit ab0c9e0

Please sign in to comment.