summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/neo4j_util.py201
1 files changed, 81 insertions, 120 deletions
diff --git a/src/server/neo4j_util.py b/src/server/neo4j_util.py
index 1b9943b0..b0eabc0a 100644
--- a/src/server/neo4j_util.py
+++ b/src/server/neo4j_util.py
@@ -3,7 +3,6 @@
"""
import json
-import logging
import six
import string
import time
@@ -13,9 +12,8 @@ import model
from six.moves.urllib import request
import six.moves.urllib_error as urllib_error
from util import debug_log_duration
-
-
-log = logging.getLogger('rhizi')
+import re
+from neo4j_cypher import Cypher_Parser
class Neo4JException(Exception):
def __init__(self, error_set):
@@ -24,55 +22,6 @@ class Neo4JException(Exception):
def __str__(self):
return 'neo4j error set: ' + str(self.error_set)
-class DB_Query(object):
-
- def __init__(self, q_str_or_array, param_set={}):
- """
- @param q_str_or_array: cypher query to add - if passed as an array ' '.join(q_str_or_array)
- is used to convert it to string type
- """
- if type(q_str_or_array) is list:
- q_str_or_array = ' '.join(q_str_or_array)
-
- q_str = q_str_or_array
- self.statement = q_str
- self.param_set = param_set
-
- def __str__(self):
- return 'q: %s, params: %s' % (self.statement, str(self.param_set))
-
- __repr__ = __str__
-
-class DB_row(object):
- def __init__(self, data):
- self.data = data
-
- def __iter__(self):
- for column_val in self.data:
- yield column_val
-
- def items(self):
- return [x for x in self]
-
- def __str__(self):
- return str(self.items())
-
- def __repr__(self):
- return repr(self.items())
-
-class DB_result_set(object):
- def __init__(self, data):
- self.data = data
-
- def __iter__(self):
- for db_row_dict in self.data['data']:
- # example: dict: {u'row': [{u'title': u'foo'}]}
- assert None != db_row_dict['row']
-
- yield DB_row(db_row_dict['row'])
-
- def items(self):
- return [x for x in self]
class Cypher_String_Formatter(string.Formatter):
"""
@@ -91,50 +40,33 @@ class Cypher_String_Formatter(string.Formatter):
val = "{" + field_name + "}", field_name
return val
-def cfmt(fmt_str, *args, **kwargs):
- return Cypher_String_Formatter().format(fmt_str, *args, **kwargs)
+def __type_check_link_or_node_map(x_map):
+ for k, v in x_map.iteritems(): # do some type sanity checking
+ assert isinstance(k, six.string_types)
+ assert isinstance(v, list)
-def quote__backtick(label):
+def __type_check_filter_attr_map(filter_attr_map):
"""
- quote label (possibly containing spaces) with backticks
+ # type sanity check an attribute filter map
"""
- return '`' + label + '`'
+ assert isinstance(filter_attr_map, dict)
+ for k, v in filter_attr_map.items():
+ assert isinstance(k, six.string_types)
+ assert isinstance(v, list)
-def post_neo4j(url, data):
+def cfmt(fmt_str, *args, **kwargs):
+ return Cypher_String_Formatter().format(fmt_str, *args, **kwargs)
+
+def db_query_set_to_REST_form(db_query_set):
"""
- @return dict object from the neo4j json POST response
+ Transform DB_Query set to Neo4J's REST API request format
+
+ ref: http://neo4j.com/docs/stable/rest-api.html
"""
- ret = post(url, data)
- ret_data = json.load(ret)
-
- # [!] do not raise exception if ret_data['errors'] is not empty -
- # this allows query-sets to partially succeed
-
- return ret_data
-
-def post(url, data):
- assert(isinstance(data, dict)) # make sure we're not handed json strings
-
- post_data_json = json.dumps(data)
-
- req = request.Request(url)
- req.add_header('User-Agent', 'rhizi-server/0.1')
- req.add_header('Accept', 'application/json; charset=UTF-8')
- req.add_header('Content-Type', 'application/json')
-
- req.add_header('X-Stream', 'true') # enable neo4j JSON streaming
-
- try:
- ret = request.urlopen(req, post_data_json)
- except urllib_error.HTTPError as e:
- raise Exception('post request failed: code: {0}, reason: {1}'.format(e.code, e.reason))
-
- return ret
-def statement_set_to_REST_form(statement_set):
- assert isinstance(statement_set, list)
+ assert isinstance(db_query_set, list)
- def _adapt_single_statement_to_REST_form(query, parameters={}):
+ def _adapt_single_query_to_REST_form(query, parameters={}):
"""
turn cypher query to neo4j json API format
"""
@@ -146,15 +78,16 @@ def statement_set_to_REST_form(statement_set):
else:
assert isinstance(parameters, dict)
- return {'statement' : query, 'parameters': parameters}
+ return {'statement' : query,
+ 'parameters': parameters}
- rest_statement_set = []
- for db_query in statement_set:
- rest_statement = _adapt_single_statement_to_REST_form(db_query.statement,
+ rest_query_set = []
+ for db_query in db_query_set:
+ rest_query = _adapt_single_query_to_REST_form(db_query.str__cypher_query(),
db_query.param_set)
- rest_statement_set.append(rest_statement)
+ rest_query_set.append(rest_query)
- return {'statements': rest_statement_set}
+ return {'statements': rest_query_set}
def gen_clause_attr_filter_from_filter_attr_map(filter_attr_map, node_label="n"):
if not filter_attr_map:
@@ -212,11 +145,11 @@ def gen_query_create_from_node_map(node_map, input_to_DB_property_map=lambda _:
__type_check_link_or_node_map(node_map)
ret = []
- for label, n_set in node_map.items():
+ for n_label, n_set in node_map.items():
- assert valid_label(label), 'malformed label: ' + label
+ validate_label(n_label)
- q_arr = ['create (n:%s {node_attr})' % (quote__backtick(label)),
+ q_arr = ['create (n:%s {node_attr})' % (quote__backtick(n_label)),
'with n',
'order by n.id',
'return {id: n.id, __label_set: labels(n)}'
@@ -247,13 +180,13 @@ def gen_query_create_from_link_map(link_map, input_to_DB_property_map=lambda _:
ret = []
for l_type, l_set in link_map.items():
- assert valid_label(l_type), 'malformed label: ' + l_type
+ validate_label(l_type);
- q_arr = ['match (src {id: {src}.id}),(dst {id: {dst}.id})',
+ q_arr = ['match (src {id: {src}.id}), (dst {id: {dst}.id})',
'create (src)-[r:%(__type)s {link_attr}]->(dst)' % {'__type': quote__backtick(l_type)},
'with r, src, dst',
'order by r.id',
- 'return { id: r.id, __src_id: src.id, __dst_id: dst.id, __type: type(r)}',
+ 'return {id: r.id, __src_id: src.id, __dst_id: dst.id, __type: type(r)}',
]
for link in l_set:
@@ -278,6 +211,50 @@ def gen_query_create_from_link_map(link_map, input_to_DB_property_map=lambda _:
return ret
+def generate_random_id__uuid():
+ """
+ generate a random UUID based string ID
+ """
+ return str(uuid.uuid4())
+
+def post_neo4j(url, data):
+ """
+ @return dict object from the neo4j json POST response
+ """
+ ret = post(url, data)
+ ret_data = json.load(ret)
+
+ # [!] do not raise exception if ret_data['errors'] is not empty -
+ # this allows query-sets to partially succeed
+
+ return ret_data
+
+def post(url, data):
+ assert(isinstance(data, dict)) # make sure we're not handed json strings
+
+ post_data_json = json.dumps(data)
+
+ req = request.Request(url)
+ req.add_header('User-Agent', 'rhizi-server/0.1')
+ req.add_header('Accept', 'application/json; charset=UTF-8')
+ req.add_header('Content-Type', 'application/json')
+
+ req.add_header('X-Stream', 'true') # enable neo4j JSON streaming
+
+ try:
+ ret = request.urlopen(req, post_data_json)
+ except urllib_error.HTTPError as e:
+ raise Exception('post request failed: code: {0}, reason: {1}'.format(e.code, e.reason))
+
+ return ret
+
+def quote__backtick(label):
+ """
+ quote label (possibly containing spaces) with backticks
+ """
+ return '`' + label + '`'
+
+
def meta_attr_list_to_meta_attr_map(e_set, meta_attr='__label_set'):
"""
convert a list of maps each containing a meta_attr key into a
@@ -320,22 +297,6 @@ def meta_attr_list_to_meta_attr_map(e_set, meta_attr='__label_set'):
return ret
-def generate_random_id__uuid():
- """
- generate a random UUID based string ID
- """
- return str(uuid.uuid4())
-
-def __type_check_link_or_node_map(x_map):
- for k, v in x_map.iteritems(): # do some type sanity checking
- assert isinstance(k, six.string_types)
- assert isinstance(v, list)
-
-def __type_check_filter_attr_map(filter_attr_map):
- """
- # type sanity check an attribute filter map
- """
- assert isinstance(filter_attr_map, dict)
- for k, v in filter_attr_map.items():
- assert isinstance(k, six.string_types)
- assert isinstance(v, list)
+def validate_label(label):
+ assert len(label) > 0 and (label[0].isupper() or label[0] == '_'), 'malformed label: ' + label
+ pass