From 2bb07f7be7c651a9416144cfc649dbc7b11a35fa Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Thu, 1 Aug 2019 08:21:25 +0300 Subject: [PATCH 1/5] added list/array support --- redisgraph/query_result.py | 32 ++++++++++++++++++++------------ test.py | 4 ++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/redisgraph/query_result.py b/redisgraph/query_result.py index 1c6a79d..8dd8d45 100644 --- a/redisgraph/query_result.py +++ b/redisgraph/query_result.py @@ -9,12 +9,15 @@ class ResultSetColumnTypes(object): COLUMN_RELATION = 3 class ResultSetScalarTypes(object): - PROPERTY_UNKNOWN = 0 - PROPERTY_NULL = 1 - PROPERTY_STRING = 2 - PROPERTY_INTEGER = 3 - PROPERTY_BOOLEAN = 4 - PROPERTY_DOUBLE = 5 + VALUE_UNKNOWN = 0 + VALUE_NULL = 1 + VALUE_STRING = 2 + VALUE_INTEGER = 3 + VALUE_BOOLEAN = 4 + VALUE_DOUBLE = 5 + VALUE_ARRAY = 6 + VALUE_EDGE = 7 + VALUE_NODE = 8 class QueryResult(object): LABELS_ADDED = 'Labels added' @@ -118,16 +121,16 @@ def parse_scalar(self, cell): value = cell[1] scalar = None - if scalar_type == ResultSetScalarTypes.PROPERTY_NULL: + if scalar_type == ResultSetScalarTypes.VALUE_NULL: scalar = None - elif scalar_type == ResultSetScalarTypes.PROPERTY_STRING: + elif scalar_type == ResultSetScalarTypes.VALUE_STRING: scalar = str(value) - elif scalar_type == ResultSetScalarTypes.PROPERTY_INTEGER: + elif scalar_type == ResultSetScalarTypes.VALUE_INTEGER: scalar = int(value) - elif scalar_type == ResultSetScalarTypes.PROPERTY_BOOLEAN: + elif scalar_type == ResultSetScalarTypes.VALUE_BOOLEAN: value = value.decode() if isinstance(value, bytes) else value if value == "true": scalar = True @@ -136,10 +139,15 @@ def parse_scalar(self, cell): else: print("Unknown boolean type\n") - elif scalar_type == ResultSetScalarTypes.PROPERTY_DOUBLE: + elif scalar_type == ResultSetScalarTypes.VALUE_DOUBLE: scalar = float(value) - elif scalar_type == ResultSetScalarTypes.PROPERTY_UNKNOWN: + elif scalar_type == ResultSetScalarTypes.VALUE_ARRAY: + scalar = [] + for raw_value in value: + scalar.append(self.parse_scalar(raw_value)) + + elif scalar_type == ResultSetScalarTypes.VALUE_UNKNOWN: print("Unknown scalar type\n") return scalar diff --git a/test.py b/test.py index 18d78ed..bed5a32 100644 --- a/test.py +++ b/test.py @@ -33,6 +33,10 @@ def test_graph_creation(self): self.assertEqual(visit.properties, edge.properties) self.assertEqual(country, japan) + query = """RETURN [1, 2.3, "4", true, false, null]""" + result = redis_graph.query(query) + self.assertEqual([1, 2.3, "4", True, False, None], result.result_set[0][0]) + # All done, remove graph. redis_graph.delete() From 18b4eb2eac38752ccc82a1a7740352d32877739b Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 4 Aug 2019 15:59:56 +0300 Subject: [PATCH 2/5] added node and edge parsing as scalars --- redisgraph/query_result.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/redisgraph/query_result.py b/redisgraph/query_result.py index 8dd8d45..95a687d 100644 --- a/redisgraph/query_result.py +++ b/redisgraph/query_result.py @@ -147,6 +147,12 @@ def parse_scalar(self, cell): for raw_value in value: scalar.append(self.parse_scalar(raw_value)) + elif scalar_type == ResultSetScalarTypes.VALUE_NODE: + scalar = self.parse_node(value) + + elif scalar_type == ResultSetScalarTypes.VALUE_EDGE: + scalar = self.parse_edge(value) + elif scalar_type == ResultSetScalarTypes.VALUE_UNKNOWN: print("Unknown scalar type\n") From aeaa8e46861d7d7231d544660291d4142516a7fe Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Sun, 18 Aug 2019 17:37:13 +0300 Subject: [PATCH 3/5] array unit test --- test.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test.py b/test.py index bed5a32..31f677f 100644 --- a/test.py +++ b/test.py @@ -40,5 +40,30 @@ def test_graph_creation(self): # All done, remove graph. redis_graph.delete() + def test_array_functions(self): + redis_graph = Graph('social', self.r) + + query = """CREATE (p:person{name:'a',age:32, array:[0,1,2]})""" + redis_graph.query(query) + + query = """CREATE (p:person{name:'b',age:30, array:[3,4,5]})""" + redis_graph.query(query) + + query = """WITH [0,1,2] as x return x""" + result = redis_graph.query(query) + self.assertEqual([0, 1, 2], result.result_set[0][0]) + + query = """MATCH(n) return collect(n) as x""" + result = redis_graph.query(query) + + a = Node(label='person', properties={'name': 'a', 'age': 32, 'array': [0, 1, 2]}) + b = Node(label='person', properties={'name': 'b', 'age': 30, 'array': [3, 4, 5]}) + + self.assertEqual([a, b], result.result_set[0][0]) + + + # All done, remove graph. + redis_graph.delete() + if __name__ == '__main__': unittest.main() From 94875b66f9b6ac0cadfb15da2efff6275294e0f7 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 4 Sep 2019 09:56:14 +0300 Subject: [PATCH 4/5] array parsing done in place --- redisgraph/query_result.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/redisgraph/query_result.py b/redisgraph/query_result.py index 95a687d..49dc87c 100644 --- a/redisgraph/query_result.py +++ b/redisgraph/query_result.py @@ -2,12 +2,14 @@ from .edge import Edge from prettytable import PrettyTable + class ResultSetColumnTypes(object): COLUMN_UNKNOWN = 0 COLUMN_SCALAR = 1 COLUMN_NODE = 2 COLUMN_RELATION = 3 + class ResultSetScalarTypes(object): VALUE_UNKNOWN = 0 VALUE_NULL = 1 @@ -19,6 +21,7 @@ class ResultSetScalarTypes(object): VALUE_EDGE = 7 VALUE_NODE = 8 + class QueryResult(object): LABELS_ADDED = 'Labels added' NODES_CREATED = 'Nodes created' @@ -37,11 +40,11 @@ def __init__(self, graph, response): self.parse_statistics(response[0]) else: self.parse_results(response) - self.parse_statistics(response[-1]) # Last element. + self.parse_statistics(response[-1]) # Last element. def parse_results(self, raw_result_set): self.header = self.parse_header(raw_result_set) - + # Empty header. if len(self.header) == 0: return @@ -51,7 +54,8 @@ def parse_results(self, raw_result_set): def parse_statistics(self, raw_statistics): self.statistics = {} - stats = [self.LABELS_ADDED, self.NODES_CREATED, self.PROPERTIES_SET, self.RELATIONSHIPS_CREATED, self.NODES_DELETED, self.RELATIONSHIPS_DELETED, self.INTERNAL_EXECUTION_TIME] + stats = [self.LABELS_ADDED, self.NODES_CREATED, self.PROPERTIES_SET, self.RELATIONSHIPS_CREATED, + self.NODES_DELETED, self.RELATIONSHIPS_DELETED, self.INTERNAL_EXECUTION_TIME] for s in stats: v = self._get_value(s, raw_statistics) if v is not None: @@ -84,7 +88,7 @@ def parse_entity_properties(self, props): # [[name, value type, value] X N] properties = {} for prop in props: - prop_name = self.graph.get_property(prop[0]) + prop_name = self.graph.get_property(prop[0]) prop_value = self.parse_scalar(prop[1:]) properties[prop_name] = prop_value @@ -126,7 +130,7 @@ def parse_scalar(self, cell): elif scalar_type == ResultSetScalarTypes.VALUE_STRING: scalar = str(value) - + elif scalar_type == ResultSetScalarTypes.VALUE_INTEGER: scalar = int(value) @@ -143,9 +147,9 @@ def parse_scalar(self, cell): scalar = float(value) elif scalar_type == ResultSetScalarTypes.VALUE_ARRAY: - scalar = [] - for raw_value in value: - scalar.append(self.parse_scalar(raw_value)) + scalar = value + for i in range(len(value)): + scalar[i] = self.parse_scalar(value[i]) elif scalar_type == ResultSetScalarTypes.VALUE_NODE: scalar = self.parse_node(value) @@ -164,6 +168,7 @@ def parse_scalar(self, cell): 2. The row after that will contain the data returned, or 'No Data returned' if there is none. 3. Prints the statistics of the query. """ + def pretty_print(self): if not self.is_empty(): header = [col[1] for col in self.header] @@ -186,7 +191,7 @@ def pretty_print(self): print(str(tbl) + '\n') for stat in self.statistics: - print("%s %s" %(stat, self.statistics[stat])) + print("%s %s" % (stat, self.statistics[stat])) def is_empty(self): return len(self.result_set) == 0 @@ -205,7 +210,7 @@ def _get_stat(self, stat): return self.statistics[stat] if stat in self.statistics else 0 @property - def labels_added(self): + def labels_added(self): return self._get_stat(self.LABELS_ADDED) @property @@ -231,4 +236,3 @@ def relationships_deleted(self): @property def run_time_ms(self): return self._get_stat(self.INTERNAL_EXECUTION_TIME) - From 1d113615a761adbf28b083602f7328033ed32533 Mon Sep 17 00:00:00 2001 From: DvirDukhan Date: Wed, 4 Sep 2019 11:47:13 +0300 Subject: [PATCH 5/5] fixed PR comments --- redisgraph/query_result.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/redisgraph/query_result.py b/redisgraph/query_result.py index 49dc87c..b37e21e 100644 --- a/redisgraph/query_result.py +++ b/redisgraph/query_result.py @@ -147,9 +147,10 @@ def parse_scalar(self, cell): scalar = float(value) elif scalar_type == ResultSetScalarTypes.VALUE_ARRAY: - scalar = value - for i in range(len(value)): - scalar[i] = self.parse_scalar(value[i]) + # array variable is introduced only for readability + scalar = array = value + for i in range(len(array)): + scalar[i] = self.parse_scalar(array[i]) elif scalar_type == ResultSetScalarTypes.VALUE_NODE: scalar = self.parse_node(value)