infrahub-server 1.1.5__py3-none-any.whl → 1.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/api/oidc.py +1 -0
- infrahub/core/attribute.py +4 -1
- infrahub/core/branch/tasks.py +7 -4
- infrahub/core/diff/calculator.py +21 -39
- infrahub/core/diff/combiner.py +11 -7
- infrahub/core/diff/coordinator.py +49 -70
- infrahub/core/diff/data_check_synchronizer.py +86 -7
- infrahub/core/diff/enricher/aggregated.py +3 -3
- infrahub/core/diff/enricher/cardinality_one.py +1 -6
- infrahub/core/diff/enricher/labels.py +13 -3
- infrahub/core/diff/enricher/path_identifier.py +2 -8
- infrahub/core/diff/ipam_diff_parser.py +1 -1
- infrahub/core/diff/merger/merger.py +5 -3
- infrahub/core/diff/merger/serializer.py +15 -8
- infrahub/core/diff/model/path.py +42 -24
- infrahub/core/diff/query/all_conflicts.py +5 -2
- infrahub/core/diff/query/diff_get.py +19 -23
- infrahub/core/diff/query/field_specifiers.py +2 -0
- infrahub/core/diff/query/field_summary.py +2 -1
- infrahub/core/diff/query/filters.py +12 -1
- infrahub/core/diff/query/has_conflicts_query.py +5 -2
- infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +3 -3
- infrahub/core/diff/query/roots_metadata.py +8 -1
- infrahub/core/diff/query/save.py +148 -63
- infrahub/core/diff/query/summary_counts_enricher.py +220 -0
- infrahub/core/diff/query/time_range_query.py +2 -1
- infrahub/core/diff/query_parser.py +49 -24
- infrahub/core/diff/repository/deserializer.py +74 -71
- infrahub/core/diff/repository/repository.py +119 -30
- infrahub/core/node/__init__.py +6 -1
- infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
- infrahub/core/node/ipam.py +6 -1
- infrahub/core/node/permissions.py +4 -0
- infrahub/core/query/diff.py +223 -230
- infrahub/core/query/node.py +8 -2
- infrahub/core/query/relationship.py +2 -1
- infrahub/core/query/resource_manager.py +3 -1
- infrahub/core/relationship/model.py +1 -1
- infrahub/core/schema/schema_branch.py +16 -7
- infrahub/core/utils.py +1 -0
- infrahub/core/validators/uniqueness/query.py +20 -17
- infrahub/database/__init__.py +13 -0
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
- infrahub/dependencies/builder/diff/coordinator.py +0 -2
- infrahub/git/integrator.py +10 -6
- infrahub/graphql/mutations/computed_attribute.py +3 -1
- infrahub/graphql/mutations/diff.py +28 -4
- infrahub/graphql/mutations/main.py +11 -6
- infrahub/graphql/mutations/relationship.py +29 -1
- infrahub/graphql/mutations/tasks.py +6 -3
- infrahub/graphql/queries/resource_manager.py +7 -3
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/types.py +26 -0
- infrahub/proposed_change/tasks.py +6 -1
- infrahub/storage.py +6 -5
- {infrahub_server-1.1.5.dist-info → infrahub_server-1.1.7.dist-info}/METADATA +41 -7
- {infrahub_server-1.1.5.dist-info → infrahub_server-1.1.7.dist-info}/RECORD +64 -64
- infrahub_testcontainers/container.py +12 -3
- infrahub_testcontainers/docker-compose.test.yml +22 -3
- infrahub_testcontainers/haproxy.cfg +43 -0
- infrahub_testcontainers/helpers.py +85 -1
- infrahub/core/diff/enricher/summary_counts.py +0 -105
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +0 -8
- {infrahub_server-1.1.5.dist-info → infrahub_server-1.1.7.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.5.dist-info → infrahub_server-1.1.7.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.5.dist-info → infrahub_server-1.1.7.dist-info}/entry_points.txt +0 -0
infrahub/core/node/__init__.py
CHANGED
|
@@ -633,6 +633,7 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
633
633
|
related_node_ids: set | None = None,
|
|
634
634
|
filter_sensitive: bool = False,
|
|
635
635
|
permissions: dict | None = None,
|
|
636
|
+
include_properties: bool = True,
|
|
636
637
|
) -> dict:
|
|
637
638
|
"""Generate GraphQL Payload for all attributes
|
|
638
639
|
|
|
@@ -686,10 +687,14 @@ class Node(BaseNode, metaclass=BaseNodeMeta):
|
|
|
686
687
|
related_node_ids=related_node_ids,
|
|
687
688
|
filter_sensitive=filter_sensitive,
|
|
688
689
|
permissions=permissions,
|
|
690
|
+
include_properties=include_properties,
|
|
689
691
|
)
|
|
690
692
|
else:
|
|
691
693
|
response[field_name] = await field.to_graphql(
|
|
692
|
-
db=db,
|
|
694
|
+
db=db,
|
|
695
|
+
filter_sensitive=filter_sensitive,
|
|
696
|
+
permissions=permissions,
|
|
697
|
+
include_properties=include_properties,
|
|
693
698
|
)
|
|
694
699
|
|
|
695
700
|
for relationship_schema in self.get_schema().relationships:
|
|
@@ -35,7 +35,7 @@ class NodeGroupedUniquenessConstraint(NodeConstraintInterface):
|
|
|
35
35
|
self.branch = branch
|
|
36
36
|
self.schema_branch = registry.schema.get_schema_branch(branch.name)
|
|
37
37
|
|
|
38
|
-
def _build_query_request(
|
|
38
|
+
async def _build_query_request(
|
|
39
39
|
self,
|
|
40
40
|
updated_node: Node,
|
|
41
41
|
node_schema: MainSchemaTypes,
|
|
@@ -51,9 +51,16 @@ class NodeGroupedUniquenessConstraint(NodeConstraintInterface):
|
|
|
51
51
|
if attribute_path.related_schema and attribute_path.relationship_schema:
|
|
52
52
|
if filters and attribute_path.relationship_schema.name in filters:
|
|
53
53
|
include_in_query = True
|
|
54
|
+
|
|
55
|
+
relationship_manager: RelationshipManager = getattr(
|
|
56
|
+
updated_node, attribute_path.relationship_schema.name
|
|
57
|
+
)
|
|
58
|
+
related_node = await relationship_manager.get_peer(db=self.db)
|
|
59
|
+
related_node_id = related_node.get_id() if related_node else None
|
|
54
60
|
query_relationship_paths.add(
|
|
55
61
|
QueryRelationshipAttributePath(
|
|
56
62
|
identifier=attribute_path.relationship_schema.get_identifier(),
|
|
63
|
+
value=related_node_id,
|
|
57
64
|
)
|
|
58
65
|
)
|
|
59
66
|
continue
|
|
@@ -158,7 +165,7 @@ class NodeGroupedUniquenessConstraint(NodeConstraintInterface):
|
|
|
158
165
|
) -> None:
|
|
159
166
|
schema_branch = self.db.schema.get_schema_branch(name=self.branch.name)
|
|
160
167
|
path_groups = node_schema.get_unique_constraint_schema_attribute_paths(schema_branch=schema_branch)
|
|
161
|
-
query_request = self._build_query_request(
|
|
168
|
+
query_request = await self._build_query_request(
|
|
162
169
|
updated_node=node, node_schema=node_schema, path_groups=path_groups, filters=filters
|
|
163
170
|
)
|
|
164
171
|
if not query_request:
|
infrahub/core/node/ipam.py
CHANGED
|
@@ -20,9 +20,14 @@ class BuiltinIPPrefix(Node):
|
|
|
20
20
|
related_node_ids: Optional[set] = None,
|
|
21
21
|
filter_sensitive: bool = False,
|
|
22
22
|
permissions: Optional[dict] = None,
|
|
23
|
+
include_properties: bool = True,
|
|
23
24
|
) -> dict:
|
|
24
25
|
response = await super().to_graphql(
|
|
25
|
-
db,
|
|
26
|
+
db,
|
|
27
|
+
fields=fields,
|
|
28
|
+
related_node_ids=related_node_ids,
|
|
29
|
+
filter_sensitive=filter_sensitive,
|
|
30
|
+
include_properties=include_properties,
|
|
26
31
|
)
|
|
27
32
|
|
|
28
33
|
if fields:
|
|
@@ -18,6 +18,7 @@ class CoreGlobalPermission(Node):
|
|
|
18
18
|
related_node_ids: Optional[set] = None,
|
|
19
19
|
filter_sensitive: bool = False,
|
|
20
20
|
permissions: Optional[dict] = None,
|
|
21
|
+
include_properties: bool = True,
|
|
21
22
|
) -> dict:
|
|
22
23
|
response = await super().to_graphql(
|
|
23
24
|
db,
|
|
@@ -25,6 +26,7 @@ class CoreGlobalPermission(Node):
|
|
|
25
26
|
related_node_ids=related_node_ids,
|
|
26
27
|
filter_sensitive=filter_sensitive,
|
|
27
28
|
permissions=permissions,
|
|
29
|
+
include_properties=include_properties,
|
|
28
30
|
)
|
|
29
31
|
|
|
30
32
|
if fields:
|
|
@@ -43,6 +45,7 @@ class CoreObjectPermission(Node):
|
|
|
43
45
|
related_node_ids: Optional[set] = None,
|
|
44
46
|
filter_sensitive: bool = False,
|
|
45
47
|
permissions: Optional[dict] = None,
|
|
48
|
+
include_properties: bool = True,
|
|
46
49
|
) -> dict:
|
|
47
50
|
response = await super().to_graphql(
|
|
48
51
|
db,
|
|
@@ -50,6 +53,7 @@ class CoreObjectPermission(Node):
|
|
|
50
53
|
related_node_ids=related_node_ids,
|
|
51
54
|
filter_sensitive=filter_sensitive,
|
|
52
55
|
permissions=permissions,
|
|
56
|
+
include_properties=include_properties,
|
|
53
57
|
)
|
|
54
58
|
|
|
55
59
|
if fields:
|
infrahub/core/query/diff.py
CHANGED
|
@@ -98,221 +98,6 @@ class DiffCountChanges(Query):
|
|
|
98
98
|
return branch_count_map
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
class DiffAllPathsQuery(DiffQuery):
|
|
102
|
-
"""Gets the required Cypher paths for a diff"""
|
|
103
|
-
|
|
104
|
-
name = "diff_node"
|
|
105
|
-
type = QueryType.READ
|
|
106
|
-
|
|
107
|
-
def __init__(
|
|
108
|
-
self,
|
|
109
|
-
base_branch: Branch,
|
|
110
|
-
diff_branch_from_time: Timestamp,
|
|
111
|
-
current_node_field_specifiers: list[tuple[str, str]] | None = None,
|
|
112
|
-
new_node_field_specifiers: list[tuple[str, str]] | None = None,
|
|
113
|
-
**kwargs: Any,
|
|
114
|
-
):
|
|
115
|
-
self.base_branch = base_branch
|
|
116
|
-
self.diff_branch_from_time = diff_branch_from_time
|
|
117
|
-
self.current_node_field_specifiers = current_node_field_specifiers
|
|
118
|
-
self.new_node_field_specifiers = new_node_field_specifiers
|
|
119
|
-
|
|
120
|
-
super().__init__(**kwargs)
|
|
121
|
-
|
|
122
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
|
|
123
|
-
from_str = self.diff_from.to_string()
|
|
124
|
-
self.params.update(
|
|
125
|
-
{
|
|
126
|
-
"base_branch_name": self.base_branch.name,
|
|
127
|
-
"branch_name": self.branch.name,
|
|
128
|
-
"global_branch_name": GLOBAL_BRANCH_NAME,
|
|
129
|
-
"branch_from_time": self.diff_branch_from_time.to_string(),
|
|
130
|
-
"from_time": from_str,
|
|
131
|
-
"to_time": self.diff_to.to_string(),
|
|
132
|
-
"branch_local": BranchSupportType.LOCAL.value,
|
|
133
|
-
"branch_aware": BranchSupportType.AWARE.value,
|
|
134
|
-
"branch_agnostic": BranchSupportType.AGNOSTIC.value,
|
|
135
|
-
"new_node_field_specifiers": self.new_node_field_specifiers,
|
|
136
|
-
"current_node_field_specifiers": self.current_node_field_specifiers,
|
|
137
|
-
}
|
|
138
|
-
)
|
|
139
|
-
query = """
|
|
140
|
-
WITH CASE
|
|
141
|
-
WHEN $new_node_field_specifiers IS NULL AND $current_node_field_specifiers IS NULL THEN [[NULL, $from_time]]
|
|
142
|
-
WHEN $new_node_field_specifiers IS NULL OR size($new_node_field_specifiers) = 0 THEN [[$current_node_field_specifiers, $from_time]]
|
|
143
|
-
WHEN $current_node_field_specifiers IS NULL OR size($current_node_field_specifiers) = 0 THEN [[$new_node_field_specifiers, $branch_from_time]]
|
|
144
|
-
ELSE [[$new_node_field_specifiers, $branch_from_time], [$current_node_field_specifiers, $from_time]]
|
|
145
|
-
END AS diff_filter_params_list
|
|
146
|
-
UNWIND diff_filter_params_list AS diff_filter_params
|
|
147
|
-
WITH diff_filter_params[0] AS node_field_specifiers_list, diff_filter_params[1] AS from_time
|
|
148
|
-
CALL {
|
|
149
|
-
// -------------------------------------
|
|
150
|
-
// These lists contain duplicate data, but vastly improve querying speed below
|
|
151
|
-
// -------------------------------------
|
|
152
|
-
WITH node_field_specifiers_list
|
|
153
|
-
UNWIND node_field_specifiers_list AS nfs
|
|
154
|
-
WITH nfs[0] AS uuid, nfs[1] AS field_name
|
|
155
|
-
WITH collect(DISTINCT uuid) as uuids, collect(DISTINCT field_name) AS field_names
|
|
156
|
-
RETURN uuids AS node_ids_list, field_names AS field_names_list
|
|
157
|
-
}
|
|
158
|
-
CALL {
|
|
159
|
-
WITH node_field_specifiers_list, node_ids_list, field_names_list, from_time
|
|
160
|
-
CALL {
|
|
161
|
-
WITH node_field_specifiers_list, node_ids_list, field_names_list, from_time
|
|
162
|
-
// -------------------------------------
|
|
163
|
-
// Identify properties added/removed on branch
|
|
164
|
-
// -------------------------------------
|
|
165
|
-
MATCH diff_rel_path = (root:Root)<-[r_root:IS_PART_OF]-(n:Node)-[r_node]-(p)-[diff_rel {branch: $branch_name}]->(q)
|
|
166
|
-
WHERE (
|
|
167
|
-
(from_time <= diff_rel.from < $to_time)
|
|
168
|
-
OR (from_time <= diff_rel.to < $to_time)
|
|
169
|
-
)
|
|
170
|
-
AND (size(node_ids_list) = 0 OR n.uuid IN node_ids_list)
|
|
171
|
-
AND (size(field_names_list) = 0 OR p.name IN field_names_list)
|
|
172
|
-
// exclude attributes and relationships under added/removed nodes, attrs, and rels b/c they are covered above
|
|
173
|
-
AND ALL(
|
|
174
|
-
r in [r_root, r_node]
|
|
175
|
-
WHERE r.from <= from_time AND r.branch IN [$branch_name, $base_branch_name]
|
|
176
|
-
)
|
|
177
|
-
AND p.branch_support = $branch_aware
|
|
178
|
-
AND any(l in labels(p) WHERE l in ["Attribute", "Relationship"])
|
|
179
|
-
AND type(diff_rel) IN ["IS_VISIBLE", "IS_PROTECTED", "HAS_SOURCE", "HAS_OWNER", "HAS_VALUE"]
|
|
180
|
-
AND any(l in labels(q) WHERE l in ["Boolean", "Node", "AttributeValue"])
|
|
181
|
-
AND type(r_node) IN ["HAS_ATTRIBUTE", "IS_RELATED"]
|
|
182
|
-
AND (node_field_specifiers_list IS NULL OR [n.uuid, p.name] IN node_field_specifiers_list)
|
|
183
|
-
AND ALL(
|
|
184
|
-
r_pair IN [[r_root, r_node], [r_node, diff_rel]]
|
|
185
|
-
// filter out paths where a base branch edge follows a branch edge
|
|
186
|
-
WHERE ((r_pair[0]).branch = $base_branch_name OR (r_pair[1]).branch = $branch_name)
|
|
187
|
-
// filter out paths where an active edge follows a deleted edge
|
|
188
|
-
AND ((r_pair[0]).status = "active" OR (r_pair[1]).status = "deleted")
|
|
189
|
-
// filter out paths where an earlier from time follows a later from time
|
|
190
|
-
AND (r_pair[0]).from <= (r_pair[1]).from
|
|
191
|
-
// require adjacent edge pairs to have overlapping times, but only if on the same branch
|
|
192
|
-
AND (
|
|
193
|
-
(r_pair[0]).branch <> (r_pair[1]).branch
|
|
194
|
-
OR (r_pair[0]).to IS NULL
|
|
195
|
-
OR (r_pair[0]).to >= (r_pair[1]).from
|
|
196
|
-
)
|
|
197
|
-
)
|
|
198
|
-
AND [%(id_func)s(n), type(r_node)] <> [%(id_func)s(q), type(diff_rel)]
|
|
199
|
-
WITH diff_rel_path, r_root, n, r_node, p, diff_rel, from_time
|
|
200
|
-
ORDER BY
|
|
201
|
-
%(id_func)s(n) DESC,
|
|
202
|
-
%(id_func)s(p) DESC,
|
|
203
|
-
type(diff_rel),
|
|
204
|
-
r_node.branch = diff_rel.branch DESC,
|
|
205
|
-
r_root.branch = diff_rel.branch DESC,
|
|
206
|
-
diff_rel.from DESC,
|
|
207
|
-
r_node.from DESC,
|
|
208
|
-
r_root.from DESC
|
|
209
|
-
WITH n, p, from_time, diff_rel, diff_rel_path
|
|
210
|
-
CALL {
|
|
211
|
-
// -------------------------------------
|
|
212
|
-
// Exclude properties under nodes and attributes/relationship deleted
|
|
213
|
-
// on this branch in the timeframe because those were all handled above
|
|
214
|
-
// -------------------------------------
|
|
215
|
-
WITH n, p, from_time
|
|
216
|
-
CALL {
|
|
217
|
-
WITH n, from_time
|
|
218
|
-
OPTIONAL MATCH (root:Root)<-[r_root_deleted:IS_PART_OF {branch: $branch_name}]-(n)
|
|
219
|
-
WHERE from_time <= r_root_deleted.from < $to_time
|
|
220
|
-
WITH r_root_deleted
|
|
221
|
-
ORDER BY r_root_deleted.status DESC
|
|
222
|
-
LIMIT 1
|
|
223
|
-
RETURN COALESCE(r_root_deleted.status = "deleted", FALSE) AS node_deleted
|
|
224
|
-
}
|
|
225
|
-
WITH n, p, from_time, node_deleted
|
|
226
|
-
CALL {
|
|
227
|
-
WITH n, p, from_time
|
|
228
|
-
OPTIONAL MATCH (n)-[r_node_deleted {branch: $branch_name}]-(p)
|
|
229
|
-
WHERE from_time <= r_node_deleted.from < $to_time
|
|
230
|
-
AND type(r_node_deleted) IN ["HAS_ATTRIBUTE", "IS_RELATED"]
|
|
231
|
-
WITH r_node_deleted
|
|
232
|
-
ORDER BY r_node_deleted.status DESC
|
|
233
|
-
LIMIT 1
|
|
234
|
-
RETURN COALESCE(r_node_deleted.status = "deleted", FALSE) AS field_deleted
|
|
235
|
-
}
|
|
236
|
-
RETURN node_deleted OR field_deleted AS node_or_field_deleted
|
|
237
|
-
}
|
|
238
|
-
WITH n, p, diff_rel, diff_rel_path, node_or_field_deleted
|
|
239
|
-
WHERE node_or_field_deleted = FALSE
|
|
240
|
-
WITH n, p, type(diff_rel) AS drt, head(collect(diff_rel_path)) AS deepest_diff_path
|
|
241
|
-
RETURN deepest_diff_path
|
|
242
|
-
}
|
|
243
|
-
RETURN deepest_diff_path AS diff_path
|
|
244
|
-
}
|
|
245
|
-
WITH DISTINCT diff_path AS diff_path
|
|
246
|
-
CALL {
|
|
247
|
-
WITH diff_path
|
|
248
|
-
WITH diff_path, nodes(diff_path) AS d_nodes, relationships(diff_path) AS d_rels
|
|
249
|
-
WITH diff_path, d_rels[0] AS r_root, d_nodes[1] AS n, d_rels[1] AS r_node, d_nodes[2] AS attr_rel, d_rels[2] AS r_prop
|
|
250
|
-
// -------------------------------------
|
|
251
|
-
// add base branch paths before branched_from, if they exist
|
|
252
|
-
// -------------------------------------
|
|
253
|
-
WITH n, attr_rel, r_node, r_prop
|
|
254
|
-
OPTIONAL MATCH latest_base_path = (:Root)<-[base_r_root:IS_PART_OF {branch: $base_branch_name}]
|
|
255
|
-
-(n)-[base_r_node {branch: $base_branch_name}]
|
|
256
|
-
-(attr_rel)-[base_r_prop {branch: $base_branch_name}]->(base_prop)
|
|
257
|
-
WHERE type(base_r_node) = type(r_node)
|
|
258
|
-
AND type(base_r_prop) = type(r_prop)
|
|
259
|
-
AND [%(id_func)s(n), type(base_r_node)] <> [%(id_func)s(base_prop), type(base_r_prop)]
|
|
260
|
-
AND all(
|
|
261
|
-
r in relationships(latest_base_path)
|
|
262
|
-
WHERE r.from < $branch_from_time
|
|
263
|
-
)
|
|
264
|
-
WITH latest_base_path, base_r_root, base_r_node, base_r_prop
|
|
265
|
-
ORDER BY base_r_prop.from DESC, base_r_node.from DESC, base_r_root.from DESC
|
|
266
|
-
LIMIT 1
|
|
267
|
-
RETURN latest_base_path
|
|
268
|
-
}
|
|
269
|
-
WITH diff_path, latest_base_path
|
|
270
|
-
UNWIND [diff_path, latest_base_path] AS penultimate_path
|
|
271
|
-
WITH penultimate_path
|
|
272
|
-
CALL {
|
|
273
|
-
WITH penultimate_path
|
|
274
|
-
WITH penultimate_path, nodes(penultimate_path) AS d_nodes, relationships(penultimate_path) AS d_rels
|
|
275
|
-
WITH penultimate_path, d_rels[0] AS r_root, d_nodes[1] AS n, d_rels[1] AS r_node, d_nodes[2] AS attr_rel, d_rels[2] AS r_prop
|
|
276
|
-
// -------------------------------------
|
|
277
|
-
// Add peer-side of any relationships to get the peer's ID
|
|
278
|
-
// -------------------------------------
|
|
279
|
-
WITH r_root, n, r_node, attr_rel, r_prop
|
|
280
|
-
OPTIONAL MATCH peer_path = (
|
|
281
|
-
(:Root)<-[peer_r_root:IS_PART_OF]-(n)-[peer_r_node:IS_RELATED]-(attr_rel:Relationship)-[r_peer:IS_RELATED]-(peer:Node)
|
|
282
|
-
)
|
|
283
|
-
WHERE type(r_prop) <> "IS_RELATED"
|
|
284
|
-
AND %(id_func)s(peer_r_root) = %(id_func)s(r_root)
|
|
285
|
-
AND %(id_func)s(peer_r_node) = %(id_func)s(r_node)
|
|
286
|
-
AND [%(id_func)s(n), type(peer_r_node)] <> [%(id_func)s(peer), type(r_peer)]
|
|
287
|
-
AND r_peer.from < $to_time
|
|
288
|
-
// filter out paths where an earlier from time follows a later from time
|
|
289
|
-
AND peer_r_node.from <= r_peer.from
|
|
290
|
-
// filter out paths where a base branch edge follows a branch edge
|
|
291
|
-
AND (peer_r_node.branch = $base_branch_name OR r_peer.branch = $branch_name)
|
|
292
|
-
// filter out paths where an active edge follows a deleted edge
|
|
293
|
-
AND (peer_r_node.status = "active" OR r_peer.status = "deleted")
|
|
294
|
-
// require adjacent edge pairs to have overlapping times, but only if on the same branch
|
|
295
|
-
AND (
|
|
296
|
-
peer_r_node.branch <> r_peer.branch
|
|
297
|
-
OR peer_r_node.to IS NULL
|
|
298
|
-
OR peer_r_node.to >= r_peer.from
|
|
299
|
-
)
|
|
300
|
-
WITH peer_path, r_peer, r_prop
|
|
301
|
-
ORDER BY r_peer.branch = r_prop.branch DESC, r_peer.from DESC
|
|
302
|
-
LIMIT 1
|
|
303
|
-
RETURN peer_path
|
|
304
|
-
}
|
|
305
|
-
WITH penultimate_path, peer_path
|
|
306
|
-
WITH reduce(
|
|
307
|
-
diff_rel_paths = [], item IN [penultimate_path, peer_path] |
|
|
308
|
-
CASE WHEN item IS NULL THEN diff_rel_paths ELSE diff_rel_paths + [item] END
|
|
309
|
-
) AS diff_rel_paths
|
|
310
|
-
UNWIND diff_rel_paths AS diff_path
|
|
311
|
-
""" % {"id_func": db.get_id_function_name()}
|
|
312
|
-
self.add_to_query(query)
|
|
313
|
-
self.return_labels = ["DISTINCT diff_path AS diff_path"]
|
|
314
|
-
|
|
315
|
-
|
|
316
101
|
class DiffCalculationQuery(DiffQuery):
|
|
317
102
|
type = QueryType.READ
|
|
318
103
|
insert_limit = False
|
|
@@ -352,6 +137,14 @@ CALL {
|
|
|
352
137
|
r in relationships(latest_base_path)
|
|
353
138
|
WHERE r.from < $branch_from_time
|
|
354
139
|
)
|
|
140
|
+
// ------------------------
|
|
141
|
+
// special handling for nodes that had their kind updated,
|
|
142
|
+
// the migration leaves two nodes with the same UUID linked to the same Relationship
|
|
143
|
+
// ------------------------
|
|
144
|
+
AND (
|
|
145
|
+
n.uuid IS NULL OR base_prop.uuid IS NULL OR n.uuid <> base_prop.uuid
|
|
146
|
+
OR type(base_r_node) <> "IS_RELATED" OR type(base_r_prop) <> "IS_RELATED"
|
|
147
|
+
)
|
|
355
148
|
WITH latest_base_path, base_r_root, base_r_node, base_r_prop
|
|
356
149
|
ORDER BY base_r_prop.from DESC, base_r_node.from DESC, base_r_root.from DESC
|
|
357
150
|
LIMIT 1
|
|
@@ -361,7 +154,7 @@ CALL {
|
|
|
361
154
|
relationship_peer_side_query = """
|
|
362
155
|
WITH diff_path, latest_base_path, has_more_data
|
|
363
156
|
UNWIND [diff_path, latest_base_path] AS penultimate_path
|
|
364
|
-
WITH penultimate_path, has_more_data
|
|
157
|
+
WITH DISTINCT penultimate_path, has_more_data
|
|
365
158
|
CALL {
|
|
366
159
|
WITH penultimate_path
|
|
367
160
|
WITH penultimate_path, nodes(penultimate_path) AS d_nodes, relationships(penultimate_path) AS d_rels
|
|
@@ -390,8 +183,13 @@ CALL {
|
|
|
390
183
|
OR peer_r_node.to IS NULL
|
|
391
184
|
OR peer_r_node.to >= r_peer.from
|
|
392
185
|
)
|
|
186
|
+
// ------------------------
|
|
187
|
+
// special handling for nodes that had their kind updated,
|
|
188
|
+
// the migration leaves two nodes with the same UUID linked to the same Relationship
|
|
189
|
+
// ------------------------
|
|
190
|
+
AND (n.uuid IS NULL OR peer.uuid IS NULL OR n.uuid <> peer.uuid)
|
|
393
191
|
WITH peer_path, r_peer, r_prop
|
|
394
|
-
ORDER BY r_peer.branch = r_prop.branch DESC, r_peer.from DESC
|
|
192
|
+
ORDER BY r_peer.branch = r_prop.branch DESC, r_peer.status = r_prop.status DESC, r_peer.from DESC, r_peer.status ASC
|
|
395
193
|
LIMIT 1
|
|
396
194
|
RETURN peer_path
|
|
397
195
|
}
|
|
@@ -456,21 +254,20 @@ AND (
|
|
|
456
254
|
(
|
|
457
255
|
($new_node_ids_list IS NOT NULL AND p.uuid IN $new_node_ids_list)
|
|
458
256
|
AND (
|
|
459
|
-
($branch_from_time <= diff_rel.from < $to_time)
|
|
257
|
+
($branch_from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
460
258
|
OR ($branch_from_time <= diff_rel.to < $to_time)
|
|
461
259
|
)
|
|
462
260
|
)
|
|
463
261
|
OR (
|
|
464
|
-
(
|
|
262
|
+
(
|
|
263
|
+
($current_node_ids_list IS NOT NULL AND p.uuid IN $current_node_ids_list)
|
|
264
|
+
OR ($current_node_ids_list IS NULL AND $new_node_ids_list IS NULL)
|
|
265
|
+
)
|
|
465
266
|
AND (
|
|
466
|
-
($from_time <= diff_rel.from < $to_time)
|
|
267
|
+
($from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
467
268
|
OR ($from_time <= diff_rel.to < $to_time)
|
|
468
269
|
)
|
|
469
270
|
)
|
|
470
|
-
OR (
|
|
471
|
-
($from_time <= diff_rel.from < $to_time)
|
|
472
|
-
OR ($from_time <= diff_rel.to < $to_time)
|
|
473
|
-
)
|
|
474
271
|
)
|
|
475
272
|
// -------------------------------------
|
|
476
273
|
// Limit the number of nodes
|
|
@@ -525,6 +322,14 @@ CALL {
|
|
|
525
322
|
AND [%(id_func)s(p), type(r_node)] <> [%(id_func)s(prop), type(r_prop)]
|
|
526
323
|
AND top_diff_rel.status = r_node.status
|
|
527
324
|
AND top_diff_rel.status = r_prop.status
|
|
325
|
+
// ------------------------
|
|
326
|
+
// special handling for nodes that had their kind updated,
|
|
327
|
+
// the migration leaves two nodes with the same UUID linked to the same Relationship
|
|
328
|
+
// ------------------------
|
|
329
|
+
AND (
|
|
330
|
+
p.uuid IS NULL OR prop.uuid IS NULL OR p.uuid <> prop.uuid
|
|
331
|
+
OR type(r_node) <> "IS_RELATED" OR type(r_prop) <> "IS_RELATED"
|
|
332
|
+
)
|
|
528
333
|
WITH path, p, node, prop, r_prop, r_node, type(r_node) AS rel_type, row_from_time
|
|
529
334
|
// -------------------------------------
|
|
530
335
|
// Exclude attributes/relationships added then removed on branch within timeframe
|
|
@@ -616,22 +421,26 @@ AND (
|
|
|
616
421
|
OR ($current_node_field_specifiers_map IS NULL AND $new_node_field_specifiers_map IS NULL)
|
|
617
422
|
)
|
|
618
423
|
AND (r_root.from < $from_time OR p.branch_support = $branch_agnostic)
|
|
619
|
-
AND (
|
|
620
|
-
|
|
424
|
+
AND (
|
|
425
|
+
($from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
426
|
+
OR ($from_time <= diff_rel.to < $to_time)
|
|
427
|
+
)
|
|
621
428
|
)
|
|
622
429
|
// time-based filters for new nodes
|
|
623
430
|
OR (
|
|
624
431
|
($new_node_field_specifiers_map IS NOT NULL AND q.name IN $new_node_field_specifiers_map[p.uuid])
|
|
625
432
|
AND (r_root.from < $branch_from_time OR p.branch_support = $branch_agnostic)
|
|
626
|
-
AND (
|
|
627
|
-
|
|
433
|
+
AND (
|
|
434
|
+
($branch_from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
435
|
+
OR ($branch_from_time <= diff_rel.to < $to_time)
|
|
436
|
+
)
|
|
628
437
|
)
|
|
629
438
|
)
|
|
630
439
|
// -------------------------------------
|
|
631
440
|
// Limit the number of paths
|
|
632
441
|
// -------------------------------------
|
|
633
442
|
WITH root, r_root, p, diff_rel, q
|
|
634
|
-
ORDER BY p.uuid, q.uuid, diff_rel.branch, diff_rel.from
|
|
443
|
+
ORDER BY r_root.from, p.uuid, q.uuid, diff_rel.branch, diff_rel.from
|
|
635
444
|
SKIP $offset
|
|
636
445
|
LIMIT $limit
|
|
637
446
|
// -------------------------------------
|
|
@@ -695,17 +504,26 @@ CALL {
|
|
|
695
504
|
AND [%(id_func)s(p), type(mid_diff_rel)] <> [%(id_func)s(prop), type(r_prop)]
|
|
696
505
|
// exclude paths where an active edge is below a deleted edge
|
|
697
506
|
AND (mid_diff_rel.status = "active" OR r_prop.status = "deleted")
|
|
507
|
+
// ------------------------
|
|
508
|
+
// special handling for nodes that had their kind updated,
|
|
509
|
+
// the migration leaves two nodes with the same UUID linked to the same Relationship
|
|
510
|
+
// ------------------------
|
|
511
|
+
AND (
|
|
512
|
+
p.uuid IS NULL OR prop.uuid IS NULL OR p.uuid <> prop.uuid
|
|
513
|
+
OR type(mid_diff_rel) <> "IS_RELATED" OR type(r_prop) <> "IS_RELATED"
|
|
514
|
+
)
|
|
698
515
|
WITH path, prop, r_prop, mid_r_root
|
|
699
516
|
ORDER BY
|
|
700
517
|
type(r_prop),
|
|
701
518
|
mid_r_root.branch = mid_diff_rel.branch DESC,
|
|
519
|
+
(mid_diff_rel.status = r_prop.status AND mid_diff_rel.branch = r_prop.branch) DESC,
|
|
702
520
|
r_prop.from DESC,
|
|
703
521
|
mid_r_root.from DESC
|
|
704
522
|
WITH prop, type(r_prop) AS type_r_prop, head(collect(path)) AS latest_prop_path
|
|
705
523
|
RETURN latest_prop_path
|
|
706
524
|
}
|
|
707
525
|
// -------------------------------------
|
|
708
|
-
// Exclude properties within the timeframe
|
|
526
|
+
// Exclude properties added and deleted within the timeframe
|
|
709
527
|
// -------------------------------------
|
|
710
528
|
WITH q, nodes(latest_prop_path)[3] AS prop, type(relationships(latest_prop_path)[2]) AS rel_type, latest_prop_path, has_more_data, row_from_time
|
|
711
529
|
CALL {
|
|
@@ -725,3 +543,178 @@ WHERE intra_branch_update = FALSE
|
|
|
725
543
|
self.add_to_query(self.get_relationship_peer_side_query(db=db))
|
|
726
544
|
self.add_to_query("UNWIND diff_rel_paths AS diff_path")
|
|
727
545
|
self.return_labels = ["DISTINCT diff_path AS diff_path", "has_more_data"]
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
class DiffPropertyPathsQuery(DiffCalculationQuery):
|
|
549
|
+
name = "diff_property_paths"
|
|
550
|
+
|
|
551
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
|
|
552
|
+
params_dict = self.get_params()
|
|
553
|
+
self.params.update(params_dict)
|
|
554
|
+
|
|
555
|
+
self.params.update(
|
|
556
|
+
{
|
|
557
|
+
"current_node_field_specifiers_map": {
|
|
558
|
+
node_uuid: list(field_names)
|
|
559
|
+
for node_uuid, field_names in self.current_node_field_specifiers.items()
|
|
560
|
+
}
|
|
561
|
+
if self.current_node_field_specifiers is not None
|
|
562
|
+
else None,
|
|
563
|
+
"new_node_field_specifiers_map": {
|
|
564
|
+
node_uuid: list(field_names) for node_uuid, field_names in self.new_node_field_specifiers.items()
|
|
565
|
+
}
|
|
566
|
+
if self.new_node_field_specifiers is not None
|
|
567
|
+
else None,
|
|
568
|
+
}
|
|
569
|
+
)
|
|
570
|
+
properties_path_query = """
|
|
571
|
+
// -------------------------------------
|
|
572
|
+
// Identify properties added/removed on branch
|
|
573
|
+
// -------------------------------------
|
|
574
|
+
MATCH diff_rel_path = (root:Root)<-[r_root:IS_PART_OF]-(n:Node)-[r_node]-(p)-[diff_rel {branch: $branch_name}]->(q)
|
|
575
|
+
WHERE p.branch_support = $branch_aware
|
|
576
|
+
AND any(l in labels(p) WHERE l in ["Attribute", "Relationship"])
|
|
577
|
+
AND type(diff_rel) IN ["IS_VISIBLE", "IS_PROTECTED", "HAS_SOURCE", "HAS_OWNER", "HAS_VALUE"]
|
|
578
|
+
AND any(l in labels(q) WHERE l in ["Boolean", "Node", "AttributeValue"])
|
|
579
|
+
AND type(r_node) IN ["HAS_ATTRIBUTE", "IS_RELATED"]
|
|
580
|
+
// node ID and field name filtering first pass
|
|
581
|
+
AND (
|
|
582
|
+
(
|
|
583
|
+
$current_node_field_specifiers_map IS NOT NULL
|
|
584
|
+
AND $current_node_field_specifiers_map[n.uuid] IS NOT NULL
|
|
585
|
+
AND p.name IN $current_node_field_specifiers_map[n.uuid]
|
|
586
|
+
) OR (
|
|
587
|
+
$new_node_field_specifiers_map IS NOT NULL
|
|
588
|
+
AND $new_node_field_specifiers_map[n.uuid] IS NOT NULL
|
|
589
|
+
AND p.name IN $new_node_field_specifiers_map[n.uuid]
|
|
590
|
+
) OR (
|
|
591
|
+
$current_node_field_specifiers_map IS NULL
|
|
592
|
+
AND $new_node_field_specifiers_map IS NULL
|
|
593
|
+
)
|
|
594
|
+
)
|
|
595
|
+
// node ID and field name filtering second pass
|
|
596
|
+
AND (
|
|
597
|
+
// time-based filters for nodes already included in the diff or fresh changes
|
|
598
|
+
(
|
|
599
|
+
(
|
|
600
|
+
($current_node_field_specifiers_map IS NOT NULL AND p.name IN $current_node_field_specifiers_map[n.uuid])
|
|
601
|
+
OR ($current_node_field_specifiers_map IS NULL AND $new_node_field_specifiers_map IS NULL)
|
|
602
|
+
)
|
|
603
|
+
AND (
|
|
604
|
+
($from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
605
|
+
OR ($from_time <= diff_rel.to < $to_time)
|
|
606
|
+
)
|
|
607
|
+
// skip paths where nodes/attrs/rels are updated after $from_time, those are handled in other queries
|
|
608
|
+
AND (
|
|
609
|
+
r_root.from <= $from_time AND (r_root.to IS NULL OR r_root.branch <> diff_rel.branch OR r_root.to <= $from_time)
|
|
610
|
+
AND r_node.from <= $from_time AND (r_node.to IS NULL OR r_node.branch <> diff_rel.branch OR r_node.to <= $from_time)
|
|
611
|
+
)
|
|
612
|
+
)
|
|
613
|
+
// time-based filters for new nodes
|
|
614
|
+
OR (
|
|
615
|
+
($new_node_field_specifiers_map IS NOT NULL AND p.name IN $new_node_field_specifiers_map[n.uuid])
|
|
616
|
+
AND (
|
|
617
|
+
($branch_from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
618
|
+
OR ($branch_from_time <= diff_rel.to < $to_time)
|
|
619
|
+
)
|
|
620
|
+
// skip paths where nodes/attrs/rels are updated after $branch_from_time, those are handled in other queries
|
|
621
|
+
AND (
|
|
622
|
+
r_root.from <= $branch_from_time AND (r_root.to IS NULL OR r_root.branch <> diff_rel.branch OR r_root.to <= $branch_from_time)
|
|
623
|
+
AND r_node.from <= $branch_from_time AND (r_node.to IS NULL OR r_node.branch <> diff_rel.branch OR r_node.to <= $branch_from_time)
|
|
624
|
+
)
|
|
625
|
+
)
|
|
626
|
+
)
|
|
627
|
+
// ------------------------
|
|
628
|
+
// special handling for nodes that had their kind updated,
|
|
629
|
+
// the migration leaves two nodes with the same UUID linked to the same Relationship
|
|
630
|
+
// ------------------------
|
|
631
|
+
AND (
|
|
632
|
+
n.uuid IS NULL OR q.uuid IS NULL OR n.uuid <> q.uuid
|
|
633
|
+
OR type(r_node) <> "IS_RELATED" OR type(diff_rel) <> "IS_RELATED"
|
|
634
|
+
)
|
|
635
|
+
AND ALL(
|
|
636
|
+
r_pair IN [[r_root, r_node], [r_node, diff_rel]]
|
|
637
|
+
// filter out paths where a base branch edge follows a branch edge
|
|
638
|
+
WHERE ((r_pair[0]).branch = $base_branch_name OR (r_pair[1]).branch = $branch_name)
|
|
639
|
+
// filter out paths where an active edge follows a deleted edge
|
|
640
|
+
AND ((r_pair[0]).status = "active" OR (r_pair[1]).status = "deleted")
|
|
641
|
+
// filter out paths where an earlier from time follows a later from time
|
|
642
|
+
AND (r_pair[0]).from <= (r_pair[1]).from
|
|
643
|
+
// require adjacent edge pairs to have overlapping times, but only if on the same branch
|
|
644
|
+
AND (
|
|
645
|
+
(r_pair[0]).branch <> (r_pair[1]).branch
|
|
646
|
+
OR (r_pair[0]).to IS NULL
|
|
647
|
+
OR (r_pair[0]).to >= (r_pair[1]).from
|
|
648
|
+
)
|
|
649
|
+
)
|
|
650
|
+
AND [%(id_func)s(n), type(r_node)] <> [%(id_func)s(q), type(diff_rel)]
|
|
651
|
+
// -------------------------------------
|
|
652
|
+
// Limit the number of paths
|
|
653
|
+
// -------------------------------------
|
|
654
|
+
WITH diff_rel_path, r_root, n, r_node, p, diff_rel
|
|
655
|
+
ORDER BY r_root.from, n.uuid, p.uuid, type(diff_rel), diff_rel.branch, diff_rel.from
|
|
656
|
+
SKIP $offset
|
|
657
|
+
LIMIT $limit
|
|
658
|
+
// -------------------------------------
|
|
659
|
+
// Add flag to indicate if there is more data after this
|
|
660
|
+
// -------------------------------------
|
|
661
|
+
WITH collect([diff_rel_path, r_root, n, r_node, p, diff_rel]) AS limited_results
|
|
662
|
+
WITH limited_results, size(limited_results) = $limit AS has_more_data
|
|
663
|
+
UNWIND limited_results AS one_result
|
|
664
|
+
WITH one_result[0] AS diff_rel_path, one_result[1] AS r_root, one_result[2] AS n,
|
|
665
|
+
one_result[3] AS r_node, one_result[4] AS p, one_result[5] AS diff_rel, has_more_data
|
|
666
|
+
// -------------------------------------
|
|
667
|
+
// Add correct from_time for row
|
|
668
|
+
// -------------------------------------
|
|
669
|
+
WITH diff_rel_path, r_root, n, r_node, p, diff_rel, has_more_data, CASE
|
|
670
|
+
WHEN $new_node_field_specifiers_map IS NOT NULL AND p.name IN $new_node_field_specifiers_map[n.uuid] THEN $branch_from_time
|
|
671
|
+
ELSE $from_time
|
|
672
|
+
END AS row_from_time
|
|
673
|
+
WITH diff_rel_path, r_root, n, r_node, p, diff_rel, has_more_data, row_from_time
|
|
674
|
+
ORDER BY
|
|
675
|
+
%(id_func)s(n) DESC,
|
|
676
|
+
%(id_func)s(p) DESC,
|
|
677
|
+
type(diff_rel),
|
|
678
|
+
r_node.branch = diff_rel.branch DESC,
|
|
679
|
+
r_root.branch = diff_rel.branch DESC,
|
|
680
|
+
diff_rel.from DESC,
|
|
681
|
+
r_node.from DESC,
|
|
682
|
+
r_root.from DESC
|
|
683
|
+
WITH n, p, row_from_time, diff_rel, diff_rel_path, has_more_data
|
|
684
|
+
CALL {
|
|
685
|
+
// -------------------------------------
|
|
686
|
+
// Exclude properties under nodes and attributes/relationships deleted
|
|
687
|
+
// on this branch in the timeframe because those were all handled above
|
|
688
|
+
// -------------------------------------
|
|
689
|
+
WITH n, p, row_from_time
|
|
690
|
+
CALL {
|
|
691
|
+
WITH n, row_from_time
|
|
692
|
+
OPTIONAL MATCH (root:Root)<-[r_root_deleted:IS_PART_OF {branch: $branch_name}]-(n)
|
|
693
|
+
WHERE row_from_time <= r_root_deleted.from < $to_time
|
|
694
|
+
WITH r_root_deleted
|
|
695
|
+
ORDER BY r_root_deleted.status DESC
|
|
696
|
+
LIMIT 1
|
|
697
|
+
RETURN COALESCE(r_root_deleted.status = "deleted", FALSE) AS node_deleted
|
|
698
|
+
}
|
|
699
|
+
WITH n, p, row_from_time, node_deleted
|
|
700
|
+
CALL {
|
|
701
|
+
WITH n, p, row_from_time
|
|
702
|
+
OPTIONAL MATCH (n)-[r_node_deleted {branch: $branch_name}]-(p)
|
|
703
|
+
WHERE row_from_time <= r_node_deleted.from < $to_time
|
|
704
|
+
AND type(r_node_deleted) IN ["HAS_ATTRIBUTE", "IS_RELATED"]
|
|
705
|
+
WITH r_node_deleted
|
|
706
|
+
ORDER BY r_node_deleted.status DESC
|
|
707
|
+
LIMIT 1
|
|
708
|
+
RETURN COALESCE(r_node_deleted.status = "deleted", FALSE) AS field_deleted
|
|
709
|
+
}
|
|
710
|
+
RETURN node_deleted OR field_deleted AS node_or_field_deleted
|
|
711
|
+
}
|
|
712
|
+
WITH n, p, diff_rel, diff_rel_path, has_more_data, node_or_field_deleted
|
|
713
|
+
WHERE node_or_field_deleted = FALSE
|
|
714
|
+
WITH n, p, type(diff_rel) AS drt, head(collect(diff_rel_path)) AS diff_path, has_more_data
|
|
715
|
+
""" % {"id_func": db.get_id_function_name()}
|
|
716
|
+
self.add_to_query(properties_path_query)
|
|
717
|
+
self.add_to_query(self.get_previous_base_path_query(db=db))
|
|
718
|
+
self.add_to_query(self.get_relationship_peer_side_query(db=db))
|
|
719
|
+
self.add_to_query("UNWIND diff_rel_paths AS diff_path")
|
|
720
|
+
self.return_labels = ["DISTINCT diff_path AS diff_path", "has_more_data"]
|
infrahub/core/query/node.py
CHANGED
|
@@ -479,11 +479,17 @@ class NodeListGetAttributeQuery(Query):
|
|
|
479
479
|
self.return_labels = ["n", "a", "av", "r1", "r2"]
|
|
480
480
|
|
|
481
481
|
# Add Is_Protected and Is_visible
|
|
482
|
+
rel_isv_branch_filter, _ = self.branch.get_query_filter_path(
|
|
483
|
+
at=self.at, branch_agnostic=self.branch_agnostic, variable_name="rel_isv"
|
|
484
|
+
)
|
|
485
|
+
rel_isp_branch_filter, _ = self.branch.get_query_filter_path(
|
|
486
|
+
at=self.at, branch_agnostic=self.branch_agnostic, variable_name="rel_isp"
|
|
487
|
+
)
|
|
482
488
|
query = """
|
|
483
489
|
MATCH (a)-[rel_isv:IS_VISIBLE]-(isv:Boolean)
|
|
484
490
|
MATCH (a)-[rel_isp:IS_PROTECTED]-(isp:Boolean)
|
|
485
|
-
WHERE
|
|
486
|
-
""" % {"
|
|
491
|
+
WHERE (%(rel_isv_branch_filter)s) AND (%(rel_isp_branch_filter)s)
|
|
492
|
+
""" % {"rel_isv_branch_filter": rel_isv_branch_filter, "rel_isp_branch_filter": rel_isp_branch_filter}
|
|
487
493
|
self.add_to_query(query)
|
|
488
494
|
|
|
489
495
|
self.return_labels.extend(["isv", "isp", "rel_isv", "rel_isp"])
|