Skip to content

Commit

Permalink
fix query
Browse files Browse the repository at this point in the history
  • Loading branch information
ajtmccarty committed Nov 25, 2024
1 parent fa55c0a commit 5db5c68
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 26 deletions.
2 changes: 1 addition & 1 deletion backend/infrahub/core/diff/merger/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ async def serialize_diff(
if node.conflict and node.conflict.selected_branch is ConflictSelection.BASE_BRANCH:
continue
node_action = self._get_action(action=node.action, conflict=node.conflict)
if node.action is DiffAction.REMOVED:
if node_action is DiffAction.REMOVED:
serialized_node_diffs.append(
NodeMergeDict(
uuid=node.uuid,
Expand Down
52 changes: 27 additions & 25 deletions backend/infrahub/core/diff/query/merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,58 +89,60 @@ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None:
// ------------------------------
// shortcut to delete all attributes and relationships for this node if the node is deleted
// ------------------------------
WITH n, node_rel_status WHERE node_rel_status = "deleted"
CALL {
WITH n
WITH n, node_rel_status
WITH n, node_rel_status
WHERE node_rel_status = "deleted"
CALL {
WITH n
MATCH (n)-[rel1:IS_RELATED]-(:Relationship)-[rel2]-(p)
OPTIONAL MATCH (n)-[rel1:IS_RELATED]-(:Relationship)-[rel2]-(p)
WHERE (p.uuid IS NULL OR n.uuid <> p.uuid)
AND rel1.branch = $target_branch
AND rel2.branch = $target_branch
AND rel1.status = "active"
AND rel2.status = "active"
RETURN rel1, rel2
UNION
MATCH (n)-[rel1:HAS_ATTRIBUTE]->(:Attribute)-[rel2]->()
WITH n
OPTIONAL MATCH (n)-[rel1:HAS_ATTRIBUTE]->(:Attribute)-[rel2]->()
WHERE type(rel2) <> "HAS_ATTRIBUTE"
AND rel1.branch = $target_branch
AND rel2.branch = $target_branch
AND rel1.status = "active"
AND rel2.status = "active"
RETURN rel1, rel2
}
WITH rel1, rel2
WITH n, rel1, rel2
WHERE rel1.to IS NULL
AND rel2.to IS NULL
AND rel1.from <= $at
AND rel2.from <= $at
SET rel1.to = $at
SET rel2.to = $at
}
WITH n
// ------------------------------
// and delete HAS_OWNER and HAS_SOURCE edges to this node if the node is deleted
// ------------------------------
CALL {
// ------------------------------
// and delete HAS_OWNER and HAS_SOURCE edges to this node if the node is deleted
// ------------------------------
WITH n
CALL {
WITH n
MATCH (n)<-[rel:HAS_OWNER]-()
WHERE rel.branch = $target_branch
AND rel.status = "active"
AND rel.from <= $at
AND rel.to IS NULL
RETURN rel
UNION
MATCH (n)<-[rel:HAS_SOURCE]-()
WHERE rel.branch = $target_branch
AND rel.status = "active"
AND rel.from <= $at
AND rel.to IS NULL
RETURN rel
CALL {
WITH n
MATCH (n)<-[rel:HAS_OWNER]-()
WHERE rel.branch = $target_branch
AND rel.status = "active"
AND rel.from <= $at
AND rel.to IS NULL
RETURN rel
UNION
MATCH (n)<-[rel:HAS_SOURCE]-()
WHERE rel.branch = $target_branch
AND rel.status = "active"
AND rel.from <= $at
AND rel.to IS NULL
RETURN rel
}
SET rel.to = $at
}
SET rel.to = $at
}
}
WITH n, node_diff_map
Expand Down
41 changes: 41 additions & 0 deletions backend/tests/unit/core/diff/test_diff_and_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,3 +695,44 @@ async def test_delete_with_many_relationship_added(
# including the relationship connecting car_1 and person_1 is deleted,
# requires a special query b/c TestCar has no relationship to TestPerson in the schema
await verify_all_linked_edges_deleted(db=db, node_uuid=person_1.id, branch_name=default_branch.name)

@pytest.mark.parametrize("selection", [ConflictSelection.BASE_BRANCH, ConflictSelection.DIFF_BRANCH])
async def test_attribute_update_with_conflict(
self,
db: InfrahubDatabase,
default_branch: Branch,
diff_repository: DiffRepository,
person_john_main: Node,
selection: ConflictSelection,
):
main_value = 200
branch_value = 150
branch2 = await create_branch(db=db, branch_name="branch2")
person_main = await NodeManager.get_one(db=db, branch=default_branch, id=person_john_main.id)
person_main.height.value = main_value
await person_main.save(db=db)
person_branch = await NodeManager.get_one(db=db, branch=branch2, id=person_john_main.id)
person_branch.height.value = branch_value
await person_branch.save(db=db)

# set the conflict resolution
diff_coordinator = await self._get_diff_coordinator(db=db, branch=branch2)
enriched_diff = await diff_coordinator.update_branch_diff(base_branch=default_branch, diff_branch=branch2)
conflicts_map = enriched_diff.get_all_conflicts()
assert len(conflicts_map) == 1
expected_path = f"data/{person_john_main.id}/height/value"
assert expected_path in conflicts_map
conflict = conflicts_map[expected_path]
await diff_repository.update_conflict_by_id(conflict_id=conflict.uuid, selection=selection)

# merge the branch
at = Timestamp()
diff_merger = await self._get_diff_merger(db=db, branch=branch2)
await diff_merger.merge_graph(at=at)

# validate that person has correct age
updated_person = await NodeManager.get_one(db=db, branch=default_branch, id=person_john_main.id)
if selection is ConflictSelection.DIFF_BRANCH:
assert updated_person.height.value == branch_value
else:
assert updated_person.height.value == main_value

0 comments on commit 5db5c68

Please sign in to comment.