-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
edges are not bound-able #498
base: master
Are you sure you want to change the base?
Changes from all commits
4e3fa07
c613605
c7d7a3e
a5b3db3
c7c198a
bb22b30
aaf7ba9
0be9ca8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -7,6 +7,7 @@ | |||||||||
|
||||||||||
class testBoundVariables(FlowTestsBase): | ||||||||||
def __init__(self): | ||||||||||
|
||||||||||
self.env, self.db = Env() | ||||||||||
self.graph = self.db.select_graph(GRAPH_ID) | ||||||||||
self.populate_graph() | ||||||||||
|
@@ -20,6 +21,7 @@ def populate_graph(self): | |||||||||
for idx, v in enumerate(node_props): | ||||||||||
node = Node(alias=f"n_{idx}", labels="L", properties={"val": v}) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure that + from graph_entities import Node, Edge Also applies to: 27-28 Committable suggestion
Suggested change
ToolsRuff
|
||||||||||
nodes.append(node) | ||||||||||
|
||||||||||
nodes_str = [str(n) for n in nodes] | ||||||||||
|
||||||||||
e0 = Edge(nodes[0], "E", nodes[1]) | ||||||||||
|
@@ -33,6 +35,7 @@ def test01_with_projected_entity(self): | |||||||||
|
||||||||||
# Verify that this query does not generate a Cartesian product. | ||||||||||
execution_plan = str(self.graph.explain(query)) | ||||||||||
|
||||||||||
self.env.assertNotIn('Cartesian Product', execution_plan) | ||||||||||
|
||||||||||
# Verify results. | ||||||||||
|
@@ -44,6 +47,7 @@ def test02_match_create_bound_variable(self): | |||||||||
# (v1)-[:E]->(v2)-[:E]->(v3)-[:e]->(v4) | ||||||||||
query = """MATCH (a:L {val: 'v3'}) CREATE (a)-[:E]->(b:L {val: 'v4'}) RETURN b.val""" | ||||||||||
actual_result = self.graph.query(query) | ||||||||||
|
||||||||||
expected_result = [['v4']] | ||||||||||
self.env.assertEquals(actual_result.result_set, expected_result) | ||||||||||
self.env.assertEquals(actual_result.relationships_created, 1) | ||||||||||
|
@@ -53,10 +57,12 @@ def test03_procedure_match_bound_variable(self): | |||||||||
# Create a full-text index. | ||||||||||
create_node_fulltext_index(self.graph, "L", "val", sync=True) | ||||||||||
|
||||||||||
|
||||||||||
# Project the result of scanning this index into a MATCH pattern. | ||||||||||
query = """CALL db.idx.fulltext.queryNodes('L', 'v1') YIELD node MATCH (node)-[]->(b) RETURN b.val""" | ||||||||||
# Verify that execution begins at the procedure call and proceeds into the traversals. | ||||||||||
execution_plan = str(self.graph.explain(query)) | ||||||||||
|
||||||||||
# For the moment, we'll just verify that ProcedureCall appears later in the plan than | ||||||||||
# its parent, Conditional Traverse. | ||||||||||
traverse_idx = execution_plan.index("Conditional Traverse") | ||||||||||
|
@@ -70,10 +76,12 @@ def test03_procedure_match_bound_variable(self): | |||||||||
|
||||||||||
def test04_projected_scanned_entity(self): | ||||||||||
query = """MATCH (a:L {val: 'v1'}) WITH a MATCH (a), (b {val: 'v2'}) RETURN a.val, b.val""" | ||||||||||
|
||||||||||
actual_result = self.graph.query(query) | ||||||||||
|
||||||||||
# Verify that this query generates exactly 2 scan ops. | ||||||||||
execution_plan = str(self.graph.explain(query)) | ||||||||||
|
||||||||||
self.env.assertEquals(2, execution_plan.count('Scan')) | ||||||||||
|
||||||||||
# Verify results. | ||||||||||
|
@@ -99,7 +107,29 @@ def test06_override_bound_with_label(self): | |||||||||
res = self.graph.query("CREATE (:N)") | ||||||||||
self.env.assertEquals(res.nodes_created, 1) | ||||||||||
|
||||||||||
res = self.graph.query("MATCH(n:N) WITH n MATCH (n:X) RETURN n") | ||||||||||
res = self.graph.query("MATCH (n:N) WITH n MATCH (n:X) RETURN n") | ||||||||||
|
||||||||||
# make sure no nodes were returned | ||||||||||
self.env.assertEquals(len(res.result_set), 0) | ||||||||||
|
||||||||||
def test07_bound_edges(self): | ||||||||||
# edges can only be declared once | ||||||||||
# re-declaring a variable as an edge is forbidden | ||||||||||
|
||||||||||
queries = ["MATCH ()-[e]->()-[e]->() RETURN *", | ||||||||||
"MATCH ()-[e]->() MATCH ()<-[e]-() RETURN *", | ||||||||||
"WITH NULL AS e MATCH ()-[e]->() RETURN *", | ||||||||||
"MATCH ()-[e]->() WITH e MATCH ()-[e]->() RETURN *", | ||||||||||
"MATCH ()-[e]->() MERGE ()-[e:R]->() RETURN *", | ||||||||||
"WITH NULL AS e MERGE ()-[e:R]->() RETURN *", | ||||||||||
"MERGE ()-[e:R]->() MERGE ()-[e:R]->()", | ||||||||||
"MATCH ()-[e]->() WHERE ()-[e]->() RETURN *"] | ||||||||||
|
||||||||||
for q in queries: | ||||||||||
try: | ||||||||||
res = self.graph.query(q) | ||||||||||
# should not reach this point | ||||||||||
self.env.assertFalse(True) | ||||||||||
except Exception as e: | ||||||||||
self.env.assertIn("The bound edge 'e' can't be redeclared in a MERGE clause", str(e)) | ||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -134,21 +134,22 @@ def test09_create_use_alias_in_many_clauses(self): | |||||
self.env.assertEquals(result.relationships_created, 2) | ||||||
|
||||||
queries = ["CREATE (n1)-[r:Rel1]->(n2) CREATE (n2)-[r:Rel1]->(n1)", | ||||||
"CREATE (n1)-[r:Rel1]->(n2) CREATE (n2)-[r2:Rel1]->(n3), (n3)-[r:Rel1]->(n2)", | ||||||
"MATCH (r) CREATE (r)"] | ||||||
"CREATE (n1)-[r:Rel1]->(n2), (n2)-[r:Rel1]->(n1)", | ||||||
"CREATE (n1)-[r:Rel1]->(n2) CREATE (n2)-[r2:Rel1]->(n3), (n3)-[r:Rel1]->(n2)"] | ||||||
|
||||||
for query in queries: | ||||||
try: | ||||||
self.graph.query(query) | ||||||
self.env.assertTrue(False) | ||||||
except redis.exceptions.ResponseError as e: | ||||||
self.env.assertContains("The bound variable 'r' can't be redeclared in a CREATE clause", str(e)) | ||||||
self.env.assertContains("The bound edge 'r' can't be redeclared in a CREATE clause", str(e)) | ||||||
|
||||||
query = "CREATE (n1)-[r:Rel1]->(n2), (n2)-[r:Rel1]->(n1)" | ||||||
query = "MATCH (r) CREATE (r)" | ||||||
try: | ||||||
self.graph.query(query) | ||||||
self.env.assertTrue(False) | ||||||
except redis.exceptions.ResponseError as e: | ||||||
self.env.assertContains("Variable `r` already declared", str(e)) | ||||||
self.env.assertContains("The bound variable 'r' can't be redeclared in a CREATE clause", str(e)) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refine the error message check to ensure it precisely matches the new standard error message for variable redeclaration. - self.env.assertContains("The bound variable 'r' can't be redeclared in a CREATE clause", str(e))
+ self.env.assertContains("The bound variable 'r' cannot be redeclared in a CREATE clause", str(e)) Note: This suggestion assumes that the error message standardization also applies to other variable redeclaration scenarios. If not, please disregard this comment. Committable suggestion
Suggested change
|
||||||
|
||||||
# test creating queries with matching relationship type :R|R | ||||||
# the results can't report duplicates | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper handling of negative range values in
_ValidateMultiHopTraversal
.The function
_ValidateMultiHopTraversal
currently checks if the start of the range is greater than the end, but it does not explicitly check for negative values. In Cypher, ranges should be non-negative. Adding a check for negative values would prevent potential issues with range specifications.Committable suggestion