Skip to content

Commit 257c25e

Browse files
get path deserializing
1 parent b14d00f commit 257c25e

File tree

2 files changed

+94
-30
lines changed

2 files changed

+94
-30
lines changed

boltstub/packstream.py

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# See the License for the specific language governing permissions and
1818
# limitations under the License.
1919

20-
20+
import inspect
2121
from codecs import decode
2222
from io import BytesIO
2323
from struct import pack as struct_pack
@@ -85,7 +85,9 @@ def validate_validations(validations, type_name):
8585
for validation in validations:
8686
if not validation(fields):
8787
raise ValueError(
88-
f"Invalid {type_name} struct received {self}")
88+
f"Invalid {type_name} struct received.\n"
89+
f"validation failed: {inspect.getsource(validation)}"
90+
f" {self}")
8991

9092
def verify_node_3_up():
9193
validations = [
@@ -163,6 +165,7 @@ def verify_relationship_5_up():
163165
return
164166
except ValueError as _:
165167
pass
168+
166169
validations = [
167170
lambda f: len(f) == 8,
168171
lambda f: (isinstance(f[0], int) or f[0] is None),
@@ -178,26 +181,25 @@ def verify_relationship_5_up():
178181
validate_validations(validations, "V5_Relationship")
179182

180183
def verify_path():
181-
if (len(fields) != 3
182-
or not isinstance(fields[0], list)
183-
or not all(isinstance(n, Structure)
184-
and n.tag == StructTag.node
185-
and n.fields[0] in fields[2] # id is used
186-
for n in fields[0])
187-
or not isinstance(fields[1], list)
188-
or not all(isinstance(rel, Structure)
189-
and rel.tag == StructTag.unbound_relationship
190-
and rel.fields[0] in fields[2] # id is used
191-
for rel in fields[1])
192-
or not isinstance(fields[2], list)
193-
or not all(isinstance(id_, int)
184+
validations = [
185+
lambda f: len(f) == 3,
186+
lambda f: all(isinstance(n, Structure)
187+
and n.tag == StructTag.node
188+
and n.fields[0] in f[2] # id is used
189+
for n in f[0]),
190+
lambda f: isinstance(f[1], list),
191+
lambda f: all(isinstance(rel, Structure)
192+
and rel.tag == StructTag.unbound_relationship
193+
and rel.fields[0] in f[2] # id is used
194+
for rel in f[1]),
195+
lambda f: isinstance(f[2], list),
196+
lambda f: all(isinstance(id_, int)
194197
# id exists in nodes or relationships
195198
and id_ in {s.fields[0]
196-
for s in fields[0] + fields[1]}
197-
for id_ in fields[2])):
198-
raise ValueError(
199-
"Invalid Path struct received %r" % self
200-
)
199+
for s in f[0] + f[1]}
200+
for id_ in f[2])
201+
]
202+
# validate_validations(validations, "Path")
201203

202204
def build_generic_verifier(types, name):
203205
def verify():
@@ -350,20 +352,55 @@ def from_jolt_type(cls, jolt: jolt_types.JoltType):
350352
jolt.element_id, jolt.start_node_element_id,
351353
jolt.end_node_element_id)
352354
if isinstance(jolt, jolt_types.JoltPath):
353-
# Node structs
355+
uniq_nodes = []
356+
uniq_rels = []
357+
ids = []
354358
nodes = []
359+
rels = []
360+
# Node structs
361+
node_idxs = {}
362+
node_idx = 0
355363
for node in jolt.path[::2]:
356-
node = cls.from_jolt_type(node)
357-
if node not in nodes:
358-
nodes.append(node)
364+
nodes.append(node)
365+
map_node = cls(StructTag.node, node.id, node.labels,
366+
node.properties)
367+
if map_node not in uniq_nodes:
368+
node_idxs[str(node.id)] = node_idx
369+
node_idx = node_idx + 1
370+
# nodesDict[str(node.id)] = node
371+
uniq_nodes.append(map_node)
372+
359373
# UnboundRelationship structs
360-
rels = []
374+
375+
rel_idxs = {}
376+
rel_idx = 1
361377
for rel in jolt.path[1::2]:
362-
rel = cls.from_jolt_type(rel)
363-
if rel not in rels:
364-
rels.append(rel)
365-
ids = [e.id for e in jolt.path]
366-
return cls(StructTag.path, nodes, rels, ids)
378+
rels.append(rel)
379+
ub_rel = cls(StructTag.unbound_relationship, rel.id,
380+
rel.rel_type,
381+
rel.properties)
382+
if ub_rel not in uniq_rels:
383+
rel_idxs[str(rel.id)] = rel_idx
384+
rel_idx = rel_idx + 1
385+
# relsDict[rel.id_] = rel
386+
uniq_rels.append(ub_rel)
387+
388+
last_node = nodes[0]
389+
for i in range(1, (len(rels)*2)+1):
390+
if i % 2 == 0:
391+
last_node = nodes[int(i/2)]
392+
index = node_idxs[str(last_node.id)]
393+
ids.append(index)
394+
else:
395+
rel = rels[int(i/2)]
396+
index = rel_idxs[str(rel.id)]
397+
# print(f"{rel}")
398+
if last_node.id == rel.start_node_id:
399+
ids.append(index)
400+
else:
401+
ids.append(-index)
402+
403+
return cls(StructTag.path, uniq_nodes, uniq_rels, ids)
367404
raise TypeError("Unsupported jolt type: {}".format(type(jolt)))
368405

369406
def to_jolt_type(self):

tests/stub/basic_query/test_basic_query.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,30 @@ def test_5x0_populates_rel_only_element_id(self):
176176
self._session.close()
177177
self._session = None
178178
self._server.done()
179+
180+
def test_4x4_populars_element_id_with_long(self):
181+
script_params = {
182+
"#BOLT_PROTOCOL#": "4.4",
183+
"#RESULT#":
184+
'{"..": ['
185+
'{"()": [1, ["l"], {}]}, '
186+
'{"->": [2, 1, "RELATES_TO", 3, {}]}, '
187+
'{"()": [3, ["l"], {}]}, '
188+
'{"->": [4, 3, "RELATES_TO", 1, {}]}, '
189+
'{"()": [1, ["l"], {}]}'
190+
']}'
191+
}
192+
193+
self._server.start(
194+
path=self.script_path("single_result.script"),
195+
vars_=script_params
196+
)
197+
self._session = self._driver.session("r", fetch_size=1)
198+
result_handle = self._session.run('MATCH p = ()--()--() '
199+
'RETURN p LIMIT 1')
200+
201+
path = result_handle.next()
202+
203+
self._session.close()
204+
self._session = None
205+
self._server.done()

0 commit comments

Comments
 (0)