@@ -205,50 +205,20 @@ def get_relationship_properties_dict(self, status: RelationshipStatus) -> dict[s
205205 rel_prop_dict ["hierarchy" ] = self .schema .hierarchical
206206 return rel_prop_dict
207207
208-
209- class RelationshipCreateQuery (RelationshipQuery ):
210- name = "relationship_create"
211-
212- type : QueryType = QueryType .WRITE
213-
214- def __init__ (
215- self ,
216- destination : Node = None ,
217- destination_id : UUID | None = None ,
218- ** kwargs ,
219- ):
220- if not destination and not destination_id :
221- raise ValueError ("Either destination or destination_id must be provided." )
222-
223- super ().__init__ (destination = destination , destination_id = destination_id , ** kwargs )
224-
225- async def query_init (self , db : InfrahubDatabase , ** kwargs ) -> None : # noqa: ARG002
226- self .params ["source_id" ] = self .source_id
227- self .params ["destination_id" ] = self .destination_id
228- self .params ["name" ] = self .schema .identifier
229- self .params ["branch_support" ] = self .schema .branch .value
230-
231- self .params ["uuid" ] = str (UUIDT ())
232-
233- self .params ["branch" ] = self .branch .name
234- self .params ["branch_level" ] = self .branch .hierarchy_level
235- self .params ["at" ] = self .at .to_string ()
236-
237- self .params ["is_protected" ] = self .rel .is_protected
238- self .params ["is_visible" ] = self .rel .is_visible
239-
240- source_branch = self .source .get_branch_based_on_support_type ()
208+ def add_source_match_to_query (self , source_branch : Branch ) -> None :
209+ self .params ["source_id" ] = self .source_id or self .source .get_id ()
241210 if source_branch .is_global or source_branch .is_default :
242211 source_query_match = """
243212 MATCH (s:Node { uuid: $source_id })
244- WHERE NOT exists((s)-[:IS_PART_OF {status: "deleted", branch: $source_branch}]->(:Root))
213+ OPTIONAL MATCH (s)-[delete_edge:IS_PART_OF {status: "deleted", branch: $source_branch}]->(:Root)
214+ WHERE delete_edge.from <= $at
215+ WITH *, s WHERE delete_edge IS NULL
245216 """
246217 self .params ["source_branch" ] = source_branch .name
247- else :
248- source_filter , source_filter_params = source_branch .get_query_filter_path (
249- at = self .at , variable_name = "r" , params_prefix = "src_"
250- )
251- source_query_match = """
218+ source_filter , source_filter_params = source_branch .get_query_filter_path (
219+ at = self .at , variable_name = "r" , params_prefix = "src_"
220+ )
221+ source_query_match = """
252222 MATCH (s:Node { uuid: $source_id })
253223 CALL {
254224 WITH s
@@ -258,16 +228,19 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
258228 ORDER BY r.from DESC
259229 LIMIT 1
260230 }
261- WITH s WHERE s_is_active = TRUE
231+ WITH *, s WHERE s_is_active = TRUE
262232 """ % {"source_filter" : source_filter }
263- self .params .update (source_filter_params )
233+ self .params .update (source_filter_params )
264234 self .add_to_query (source_query_match )
265235
266- destination_branch = self .destination .get_branch_based_on_support_type ()
236+ def add_dest_match_to_query (self , destination_branch : Branch , destination_id : str ) -> None :
237+ self .params ["destination_id" ] = destination_id
267238 if destination_branch .is_global or destination_branch .is_default :
268239 destination_query_match = """
269240 MATCH (d:Node { uuid: $destination_id })
270- WHERE NOT exists((d)-[:IS_PART_OF {status: "deleted", branch: $destination_branch}]->(:Root))
241+ OPTIONAL MATCH (d)-[delete_edge:IS_PART_OF {status: "deleted", branch: $destination_branch}]->(:Root)
242+ WHERE delete_edge.from <= $at
243+ WITH *, d WHERE delete_edge IS NULL
271244 """
272245 self .params ["destination_branch" ] = destination_branch .name
273246 else :
@@ -284,11 +257,46 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
284257 ORDER BY r.from DESC
285258 LIMIT 1
286259 }
287- WITH s , d WHERE d_is_active = TRUE
260+ WITH * , d WHERE d_is_active = TRUE
288261 """ % {"destination_filter" : destination_filter }
289262 self .params .update (destination_filter_params )
290263 self .add_to_query (destination_query_match )
291264
265+
266+ class RelationshipCreateQuery (RelationshipQuery ):
267+ name = "relationship_create"
268+
269+ type : QueryType = QueryType .WRITE
270+
271+ def __init__ (
272+ self ,
273+ destination : Node = None ,
274+ destination_id : UUID | None = None ,
275+ ** kwargs ,
276+ ):
277+ if not destination and not destination_id :
278+ raise ValueError ("Either destination or destination_id must be provided." )
279+
280+ super ().__init__ (destination = destination , destination_id = destination_id , ** kwargs )
281+
282+ async def query_init (self , db : InfrahubDatabase , ** kwargs ) -> None : # noqa: ARG002
283+ self .params ["name" ] = self .schema .identifier
284+ self .params ["branch_support" ] = self .schema .branch .value
285+
286+ self .params ["uuid" ] = str (UUIDT ())
287+
288+ self .params ["branch" ] = self .branch .name
289+ self .params ["branch_level" ] = self .branch .hierarchy_level
290+ self .params ["at" ] = self .at .to_string ()
291+
292+ self .params ["is_protected" ] = self .rel .is_protected
293+ self .params ["is_visible" ] = self .rel .is_visible
294+
295+ self .add_source_match_to_query (source_branch = self .source .get_branch_based_on_support_type ())
296+ self .add_dest_match_to_query (
297+ destination_branch = self .destination .get_branch_based_on_support_type (),
298+ destination_id = self .destination_id or self .destination .get_id (),
299+ )
292300 self .query_add_all_node_property_match ()
293301
294302 self .params ["rel_prop" ] = self .get_relationship_properties_dict (status = RelationshipStatus .ACTIVE )
@@ -433,7 +441,6 @@ def __init__(
433441
434442 async def query_init (self , db : InfrahubDatabase , ** kwargs ) -> None : # noqa: ARG002
435443 self .params ["source_id" ] = self .source_id
436- self .params ["destination_id" ] = self .data .peer_id
437444 self .params ["rel_node_id" ] = self .data .rel_node_id
438445 self .params ["name" ] = self .schema .identifier
439446 self .params ["branch" ] = self .branch .name
@@ -443,9 +450,10 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
443450 # -----------------------------------------------------------------------
444451 # Match all nodes, including properties
445452 # -----------------------------------------------------------------------
453+
454+ self .add_source_match_to_query (source_branch = self .source .get_branch_based_on_support_type ())
455+ self .add_dest_match_to_query (destination_branch = self .branch , destination_id = self .data .peer_id )
446456 query = """
447- MATCH (s:Node { uuid: $source_id })
448- MATCH (d:Node { uuid: $destination_id })
449457 MATCH (rl:Relationship { uuid: $rel_node_id })
450458 """
451459 self .add_to_query (query )
@@ -497,8 +505,6 @@ def __init__(self, **kwargs):
497505
498506 async def query_init (self , db : InfrahubDatabase , ** kwargs ) -> None : # noqa: ARG002
499507 rel_filter , rel_params = self .branch .get_query_filter_path (at = self .at , variable_name = "edge" )
500- self .params ["source_id" ] = self .source_id
501- self .params ["destination_id" ] = self .destination_id
502508 self .params ["rel_id" ] = self .rel .id
503509 self .params ["branch" ] = self .branch .name
504510 self .params ["rel_prop" ] = self .get_relationship_properties_dict (status = RelationshipStatus .DELETED )
@@ -509,9 +515,14 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
509515 r1 = f"{ arrows .left .start } [r1:{ self .rel_type } $rel_prop ]{ arrows .left .end } "
510516 r2 = f"{ arrows .right .start } [r2:{ self .rel_type } $rel_prop ]{ arrows .right .end } "
511517
518+ self .add_source_match_to_query (source_branch = self .source .get_branch_based_on_support_type ())
519+ self .add_dest_match_to_query (
520+ destination_branch = self .destination .get_branch_based_on_support_type (),
521+ destination_id = self .destination_id or self .destination .get_id (),
522+ )
512523 query = """
513- MATCH (s:Node { uuid: $source_id } )-[:IS_RELATED]-(rl:Relationship {uuid: $rel_id})-[:IS_RELATED]-(d:Node { uuid: $destination_id } )
514- WITH s, rl, d
524+ MATCH (s)-[:IS_RELATED]-(rl:Relationship {uuid: $rel_id})-[:IS_RELATED]-(d)
525+ WITH DISTINCT s, rl, d
515526 LIMIT 1
516527 CREATE (s)%(r1)s(rl)
517528 CREATE (rl)%(r2)s(d)
@@ -853,8 +864,6 @@ class RelationshipGetQuery(RelationshipQuery):
853864 type : QueryType = QueryType .READ
854865
855866 async def query_init (self , db : InfrahubDatabase , ** kwargs ) -> None : # noqa: ARG002
856- self .params ["source_id" ] = self .source_id
857- self .params ["destination_id" ] = self .destination_id
858867 self .params ["name" ] = self .schema .identifier
859868 self .params ["branch" ] = self .branch .name
860869
@@ -868,9 +877,12 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
868877 r1 = f"{ arrows .left .start } [r1:{ self .rel .rel_type } ]{ arrows .left .end } "
869878 r2 = f"{ arrows .right .start } [r2:{ self .rel .rel_type } ]{ arrows .right .end } "
870879
880+ self .add_source_match_to_query (source_branch = self .source .get_branch_based_on_support_type ())
881+ self .add_dest_match_to_query (
882+ destination_branch = self .destination .get_branch_based_on_support_type (),
883+ destination_id = self .destination_id or self .destination .get_id (),
884+ )
871885 query = """
872- MATCH (s:Node { uuid: $source_id })
873- MATCH (d:Node { uuid: $destination_id })
874886 MATCH (s)%s(rl:Relationship { name: $name })%s(d)
875887 WHERE %s
876888 """ % (
@@ -1097,7 +1109,11 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
10971109 CALL {
10981110 WITH rl
10991111 MATCH (rl)-[active_edge:IS_RELATED]->(n)
1100- WHERE %(active_rel_filter)s AND active_edge.status ="active"
1112+ WHERE %(active_rel_filter)s
1113+ WITH rl, active_edge, n
1114+ ORDER BY %(id_func)s(rl), %(id_func)s(n), active_edge.from DESC
1115+ WITH rl, n, head(collect(active_edge)) AS active_edge
1116+ WHERE active_edge.status = "active"
11011117 CREATE (rl)-[deleted_edge:IS_RELATED $rel_prop]->(n)
11021118 SET deleted_edge.hierarchy = active_edge.hierarchy
11031119 WITH rl, active_edge, n
@@ -1113,7 +1129,11 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
11131129
11141130 WITH rl
11151131 MATCH (rl)<-[active_edge:IS_RELATED]-(n)
1116- WHERE %(active_rel_filter)s AND active_edge.status ="active"
1132+ WHERE %(active_rel_filter)s
1133+ WITH rl, active_edge, n
1134+ ORDER BY %(id_func)s(rl), %(id_func)s(n), active_edge.from DESC
1135+ WITH rl, n, head(collect(active_edge)) AS active_edge
1136+ WHERE active_edge.status = "active"
11171137 CREATE (rl)<-[deleted_edge:IS_RELATED $rel_prop]-(n)
11181138 SET deleted_edge.hierarchy = active_edge.hierarchy
11191139 WITH rl, active_edge, n
@@ -1126,9 +1146,7 @@ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG
11261146 "inbound" as rel_direction
11271147 }
11281148 RETURN DISTINCT uuid, kind, rel_identifier, rel_direction
1129- """ % {
1130- "active_rel_filter" : active_rel_filter ,
1131- }
1149+ """ % {"active_rel_filter" : active_rel_filter , "id_func" : db .get_id_function_name ()}
11321150
11331151 self .add_to_query (query )
11341152
0 commit comments