Skip to content

Commit 467d625

Browse files
authored
Support dicts in parameter values. (#142)
* In dictionaries, keys need to _not_ be quoted. * We process parameter values recursively, so that (nested) lists and dicts are handled.
1 parent bb300e1 commit 467d625

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed

redisgraph/graph.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import redis
22

3-
from redisgraph.util import random_string, quote_string
3+
from redisgraph.util import random_string, quote_string, stringify_param_value
44
from redisgraph.query_result import QueryResult
55
from redisgraph.exceptions import VersionMismatchException
66

@@ -162,13 +162,7 @@ def _build_params_header(self, params):
162162
# Header starts with "CYPHER"
163163
params_header = "CYPHER "
164164
for key, value in params.items():
165-
# If value is string add quotation marks.
166-
if isinstance(value, str):
167-
value = quote_string(value)
168-
# Value is None, replace with "null" string.
169-
elif value is None:
170-
value = "null"
171-
params_header += str(key) + "=" + str(value) + " "
165+
params_header += str(key) + "=" + stringify_param_value(value) + " "
172166
return params_header
173167

174168
def query(self, q, params=None, timeout=None, read_only=False):

redisgraph/util.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import random
22
import string
33

4-
__all__ = ['random_string', 'quote_string']
4+
__all__ = ['random_string', 'quote_string', 'stringify_param_value']
55

66

77
def random_string(length=10):
@@ -28,3 +28,30 @@ def quote_string(v):
2828
v = v.replace('"', '\\"')
2929

3030
return '"{}"'.format(v)
31+
32+
33+
def stringify_param_value(value):
34+
"""
35+
Turn a parameter value into a string suitable for the params header of
36+
a Cypher command.
37+
38+
You may pass any value that would be accepted by `json.dumps()`.
39+
40+
Ways in which output differs from that of `str()`:
41+
* Strings are quoted.
42+
* None --> "null".
43+
* In dictionaries, keys are _not_ quoted.
44+
45+
:param value: The parameter value to be turned into a string.
46+
:return: string
47+
"""
48+
if isinstance(value, str):
49+
return quote_string(value)
50+
elif value is None:
51+
return "null"
52+
elif isinstance(value, (list, tuple)):
53+
return f'[{",".join(map(stringify_param_value, value))}]'
54+
elif isinstance(value, dict):
55+
return f'{{{",".join(f"{k}:{stringify_param_value(v)}" for k, v in value.items())}}}'
56+
else:
57+
return str(value)

tests/unit/test_util.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,28 @@ def test_quote_string(self):
1717
self.assertEqual(util.quote_string('\"'), '"\\\""')
1818
self.assertEqual(util.quote_string('"'), '"\\""')
1919
self.assertEqual(util.quote_string('a"a'), '"a\\"a"')
20+
21+
def test_stringify_param_value(self):
22+
cases = [
23+
[
24+
"abc", '"abc"'
25+
],
26+
[
27+
None, "null"
28+
],
29+
[
30+
["abc", 123, None],
31+
'["abc",123,null]'
32+
],
33+
[
34+
{'age': 2, 'color': 'orange'},
35+
'{age:2,color:"orange"}'
36+
],
37+
[
38+
[{'age': 2, 'color': 'orange'}, {'age': 7, 'color': 'gray'}, ],
39+
'[{age:2,color:"orange"},{age:7,color:"gray"}]'
40+
],
41+
]
42+
for param, expected in cases:
43+
observed = util.stringify_param_value(param)
44+
self.assertEqual(observed, expected)

0 commit comments

Comments
 (0)