fix edge table delete cascade to preserve shared children (#5)#44
fix edge table delete cascade to preserve shared children (#5)#44stalep wants to merge 1 commit intoHyperfoil:mainfrom
Conversation
…il#5) When deleting a node/value with references in edge tables, shared children are now preserved if they have other parents. Fixes the entity/query mismatch in getDependentValues, adds parent count checks before cascading deletes, and cleans up inverse edge rows.
|
This PR claims to fix closure table delete cascade in the main branch but I don't see where the main branch is using a closure table and this PR does not re-introduce a closure table. |
|
yeah, the fix itself is about preserving shared children in these edge tables during delete cascades (checking parent count before removing), but the PR title/description should have said "edge table" instead of "closure table". Updating now. |
There was a problem hiding this comment.
Pull request overview
This PR updates cascade-delete behavior for node_edge and value_edge relationships so that deleting a parent node/value does not incorrectly delete children that still have other parents, and adds regression tests around shared vs exclusive dependents.
Changes:
- Fixes
getDependentValuesto returnValueEntity(previously queried viaNodeEntity). - Adds parent-count checks and explicit edge-table cleanup to
NodeService.deleteandValueService.delete. - Reworks
deleteDescendantValuesandpurgeto avoid deleting values that still have external parents, plus adds tests for these cases.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/test/java/io/hyperfoil/tools/h5m/svc/ValueServiceTest.java |
Adds regression tests covering shared/exclusive child behavior for delete, deleteDescendants, and purge. |
src/test/java/io/hyperfoil/tools/h5m/svc/NodeServiceTest.java |
Adds regression test ensuring shared dependent nodes survive deleting one parent. |
src/main/java/io/hyperfoil/tools/h5m/svc/ValueService.java |
Fixes dependent query type and adds edge-aware cascade logic for deletes/purge/descendant deletion. |
src/main/java/io/hyperfoil/tools/h5m/svc/NodeService.java |
Adds parent counting and edge-aware cascading delete for nodes. |
src/main/java/io/hyperfoil/tools/h5m/svc/EdgeQueries.java |
Introduces shared native-query helpers for edge-table parent counts and cleanup deletes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Map<Long, Long> parentCounts = getNodeParentCounts(dependents.stream().map(n -> n.id).toList()); | ||
| for(NodeEntity dependent : dependents){ | ||
| long parentCount = parentCounts.getOrDefault(dependent.id, 0L); | ||
| if(parentCount <= 1){ | ||
| delete(dependent.id); | ||
| } | ||
| } | ||
| // clean up edge rows where this node is a parent (inverse side not managed by JPA) | ||
| EdgeQueries.deleteParentEdges(em, "node_edge", nodeId); |
| Map<Long, Long> parentCounts = getParentCounts(descendants.stream().map(ValueEntity::getId).toList()); | ||
| int deleted = 0; | ||
| for(ValueEntity v : descendants){ | ||
| if(parentCounts.getOrDefault(v.id, 0L) <= 1){ | ||
| EdgeQueries.deleteParentEdges(em, "value_edge", v.id); |
| if(!hasExternalParent(d, purgeSet)){ | ||
| EdgeQueries.deleteParentEdges(em, "value_edge", d.id); | ||
| EdgeQueries.deleteChildEdges(em, "value_edge", d.id); | ||
| em.createNativeQuery("DELETE FROM value WHERE id = :id") | ||
| .setParameter("id", d.id).executeUpdate(); | ||
| deleted++; |
| Map<Long, Long> parentCounts = getParentCounts(dependents.stream().map(ValueEntity::getId).toList()); | ||
| for(ValueEntity dependent : dependents){ | ||
| long parentCount = parentCounts.getOrDefault(dependent.id, 0L); |
When deleting a node/value with references in edge tables (node_edge, value_edge), shared children are now preserved if they have other parents. Fixes the entity/query mismatch in getDependentValues, adds parent count checks before cascading deletes, and cleans up inverse edge rows.