Skip to content

Commit 687f8ca

Browse files
4.0 summary counters (#399)
* added test case for SummaryCounters * system updates
1 parent 80af47e commit 687f8ca

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed

neo4j/work/summary.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ class SummaryCounters:
135135
#:
136136
constraints_removed = 0
137137

138+
#:
139+
system_updates = 0
140+
138141
def __init__(self, statistics):
139142
for key, value in dict(statistics).items():
140143
key = key.replace("-", "_")
@@ -145,12 +148,18 @@ def __repr__(self):
145148

146149
@property
147150
def contains_updates(self):
151+
"""True if any of the counters except for system_updates, are greater than 0. Otherwise False."""
148152
return bool(self.nodes_created or self.nodes_deleted or
149153
self.relationships_created or self.relationships_deleted or
150154
self.properties_set or self.labels_added or self.labels_removed or
151155
self.indexes_added or self.indexes_removed or
152156
self.constraints_added or self.constraints_removed)
153157

158+
@property
159+
def contains_system_updates(self):
160+
"""True if the system database was updated, otherwise False."""
161+
return self.system_updates > 0
162+
154163

155164
#: A plan describes how the database will execute your statement.
156165
#:

tests/integration/test_summary.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727
ProfiledPlan,
2828
Notification,
2929
Position,
30+
GraphDatabase,
31+
)
32+
from neo4j.exceptions import (
33+
ServiceUnavailable,
34+
)
35+
from neo4j._exceptions import (
36+
BoltHandshakeError,
3037
)
3138

3239

@@ -121,3 +128,179 @@ def test_protocol_version_information(session):
121128
assert isinstance(summary.server.protocol_version[1], int)
122129

123130

131+
def test_summary_counters_case_1(session):
132+
# python -m pytest tests/integration/test_summary.py -s -v -k test_summary_counters_case_1
133+
134+
result = session.run("RETURN $number AS x", number=3)
135+
summary = result.consume()
136+
137+
assert summary.query == "RETURN $number AS x"
138+
assert summary.parameters == {"number": 3}
139+
140+
assert isinstance(summary.query_type, str)
141+
142+
counters = summary.counters
143+
144+
assert isinstance(counters, SummaryCounters)
145+
assert counters.nodes_created == 0
146+
assert counters.nodes_deleted == 0
147+
assert counters.relationships_created == 0
148+
assert counters.relationships_deleted == 0
149+
assert counters.properties_set == 0
150+
assert counters.labels_added == 0
151+
assert counters.labels_removed == 0
152+
assert counters.indexes_added == 0
153+
assert counters.indexes_removed == 0
154+
assert counters.constraints_added == 0
155+
assert counters.constraints_removed == 0
156+
assert counters.contains_updates is False
157+
158+
assert counters.system_updates == 0
159+
assert counters.contains_system_updates is False
160+
161+
162+
def test_summary_counters_case_2(neo4j_uri, auth, target):
163+
# python -m pytest tests/integration/test_summary.py -s -v -k test_summary_counters_case_2
164+
try:
165+
with GraphDatabase.driver(neo4j_uri, auth=auth) as driver:
166+
167+
with driver.session(database="system") as session:
168+
session.run("DROP DATABASE test IF EXISTS").consume()
169+
170+
# SHOW DATABASES
171+
172+
result = session.run("SHOW DATABASES")
173+
databases = set()
174+
for record in result:
175+
databases.add(record.get("name"))
176+
assert "system" in databases
177+
assert "neo4j" in databases
178+
179+
summary = result.consume()
180+
181+
assert summary.query == "SHOW DATABASES"
182+
assert summary.parameters == {}
183+
184+
assert isinstance(summary.query_type, str)
185+
186+
counters = summary.counters
187+
188+
assert isinstance(counters, SummaryCounters)
189+
assert counters.nodes_created == 0
190+
assert counters.nodes_deleted == 0
191+
assert counters.relationships_created == 0
192+
assert counters.relationships_deleted == 0
193+
assert counters.properties_set == 0
194+
assert counters.labels_added == 0
195+
assert counters.labels_removed == 0
196+
assert counters.indexes_added == 0
197+
assert counters.indexes_removed == 0
198+
assert counters.constraints_added == 0
199+
assert counters.constraints_removed == 0
200+
assert counters.contains_updates is False
201+
202+
assert counters.system_updates == 0
203+
assert counters.contains_system_updates is False
204+
205+
# CREATE DATABASE test
206+
207+
summary = session.run("CREATE DATABASE test").consume()
208+
209+
assert summary.query == "CREATE DATABASE test"
210+
assert summary.parameters == {}
211+
212+
assert isinstance(summary.query_type, str)
213+
214+
counters = summary.counters
215+
216+
assert isinstance(counters, SummaryCounters)
217+
assert counters.nodes_created == 0
218+
assert counters.nodes_deleted == 0
219+
assert counters.relationships_created == 0
220+
assert counters.relationships_deleted == 0
221+
assert counters.properties_set == 0
222+
assert counters.labels_added == 0
223+
assert counters.labels_removed == 0
224+
assert counters.indexes_added == 0
225+
assert counters.indexes_removed == 0
226+
assert counters.constraints_added == 0
227+
assert counters.constraints_removed == 0
228+
assert counters.contains_updates is False
229+
230+
assert counters.system_updates == 1
231+
assert counters.contains_system_updates is True
232+
233+
with driver.session(database="test") as session:
234+
summary = session.run("CREATE (n)").consume()
235+
assert summary.counters.contains_updates is True
236+
assert summary.counters.contains_system_updates is False
237+
assert summary.counters.nodes_created == 1
238+
239+
with driver.session(database="test") as session:
240+
summary = session.run("MATCH (n) DELETE (n)").consume()
241+
assert summary.counters.contains_updates is True
242+
assert summary.counters.contains_system_updates is False
243+
assert summary.counters.nodes_deleted == 1
244+
245+
with driver.session(database="test") as session:
246+
summary = session.run("CREATE ()-[:KNOWS]->()").consume()
247+
assert summary.counters.contains_updates is True
248+
assert summary.counters.contains_system_updates is False
249+
assert summary.counters.relationships_created == 1
250+
251+
with driver.session(database="test") as session:
252+
summary = session.run("MATCH ()-[r:KNOWS]->() DELETE r").consume()
253+
assert summary.counters.contains_updates is True
254+
assert summary.counters.contains_system_updates is False
255+
assert summary.counters.relationships_deleted == 1
256+
257+
with driver.session(database="test") as session:
258+
summary = session.run("CREATE (n:ALabel)").consume()
259+
assert summary.counters.contains_updates is True
260+
assert summary.counters.contains_system_updates is False
261+
assert summary.counters.labels_added == 1
262+
263+
with driver.session(database="test") as session:
264+
summary = session.run("MATCH (n:ALabel) REMOVE n:ALabel").consume()
265+
assert summary.counters.contains_updates is True
266+
assert summary.counters.contains_system_updates is False
267+
assert summary.counters.labels_removed == 1
268+
269+
with driver.session(database="test") as session:
270+
summary = session.run("CREATE (n {magic: 42})").consume()
271+
assert summary.counters.contains_updates is True
272+
assert summary.counters.contains_system_updates is False
273+
assert summary.counters.properties_set == 1
274+
275+
with driver.session(database="test") as session:
276+
summary = session.run("CREATE INDEX ON :ALabel(prop)").consume()
277+
assert summary.counters.contains_updates is True
278+
assert summary.counters.contains_system_updates is False
279+
assert summary.counters.indexes_added == 1
280+
281+
with driver.session(database="test") as session:
282+
summary = session.run("DROP INDEX ON :ALabel(prop)").consume()
283+
assert summary.counters.contains_updates is True
284+
assert summary.counters.contains_system_updates is False
285+
assert summary.counters.indexes_removed == 1
286+
287+
with driver.session(database="test") as session:
288+
summary = session.run("CREATE CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE").consume()
289+
assert summary.counters.contains_updates is True
290+
assert summary.counters.contains_system_updates is False
291+
assert summary.counters.constraints_added == 1
292+
293+
with driver.session(database="test") as session:
294+
summary = session.run("DROP CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE").consume()
295+
assert summary.counters.contains_updates is True
296+
assert summary.counters.contains_system_updates is False
297+
assert summary.counters.constraints_removed == 1
298+
299+
with driver.session(database="system") as session:
300+
session.run("DROP DATABASE test IF EXISTS").consume()
301+
except ServiceUnavailable as error:
302+
if error.args[0] == "Server does not support routing":
303+
# This is because a single instance Neo4j 3.5 does not have dbms.routing.cluster.getRoutingTable() call
304+
pytest.skip(error.args[0])
305+
elif isinstance(error.__cause__, BoltHandshakeError):
306+
pytest.skip(error.args[0])

0 commit comments

Comments
 (0)