1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
# This file is part of rhizi, a collaborative knowledge graph editor.
# Copyright (C) 2014-2015 Rhizi
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from neo4j_cypher import Query_Struct_Type, DB_Query
from neo4j_util import rzdoc__ns_label, rzdoc__meta_ns_label
from neo4j_cypher_parser import p_path, p_node
from db_op import DBO_rzdoc__clone, DB_op
import re
import neo4j_schema
class Query_Transformation(object):
"""
DB_op / DB_Query transformation
"""
def __call__(self, value):
"""
Apply transformation to either a DB_op or a DB_Query
"""
if isinstance(value, DB_Query):
return self.apply_to_db_op(value)
if isinstance(value, DB_op):
return self.apply_to_db_op(value)
def apply_to_db_op(self, op):
for dbq in op: # apply to sub queries
self.apply_to_single_query(dbq)
return op
def apply_to_single_query(self, dbq): pass # subclass hook
class QT_RZDOC_NS_Filter__common(Query_Transformation):
"""
Add RZDoc name-space filter:
- inject NS labels into node patterns
- [!] ignore nodes which are part of path patterns to avoid overriding bound references
"""
def __init__(self, ns_label):
self.ns_label = ns_label
def deco__process_q_ret__n_label_set(self, label_set):
ret = [lbl for lbl in label_set if lbl != self.ns_label]
return ret
def apply_to_db_op(self, op):
ret = Query_Transformation.apply_to_db_op(self, op)
# override DBO_rzdoc__clone.process_q_ret__n_label_set hook
if op.__class__ == DBO_rzdoc__clone:
op.process_q_ret__n_label_set = self.deco__process_q_ret__n_label_set
return ret
def apply_to_single_query(self, dbq):
q_type = dbq.query_struct_type
clause_set = []
if Query_Struct_Type.w == q_type:
clause_set += dbq.pt_root.clause_set_by_kw('create')
if Query_Struct_Type.r == q_type:
clause_set += dbq.pt_root.clause_set_by_kw('match')
if Query_Struct_Type.rw == q_type:
clause_set += dbq.pt_root.clause_set_by_kw('create')
clause_set += dbq.pt_root.clause_set_by_kw('match')
for c in clause_set:
n_exp_set = c.sub_exp_set_by_type(p_node, recurse=True)
for n_exp in n_exp_set:
if n_exp.parent.__class__ == p_path:
continue;
lbl_set = n_exp.label_set
if not lbl_set: # add label set if necessary
lbl_set = n_exp.spawn_label_set()
lbl_set.add_label(self.ns_label)
# log.debug('db_q trans: in clause: %s, out clause: %s' % (cur_clause, new_clause))
class QT_RZDOC_NS_Filter(QT_RZDOC_NS_Filter__common):
def __init__(self, rzdoc):
ns_label = rzdoc__ns_label(rzdoc)
super(QT_RZDOC_NS_Filter, self).__init__(ns_label)
class QT_RZDOC_Meta_NS_Filter(QT_RZDOC_NS_Filter__common):
def __init__(self, rzdoc):
ns_label = rzdoc__meta_ns_label(rzdoc)
super(QT_RZDOC_Meta_NS_Filter, self).__init__(ns_label)
class QT_Node_Filter__meta_label_set(Query_Transformation):
# TODO: impl
# 'where 0 = length(filter(_lbl in labels(n) where _lbl =~ \'^__.*$\'))', # filter nodes with meta labels
pass
|