You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apply cascade restriction and propagate downstream. Returns a new `Diagram`. One-shot — cannot be called twice or mixed with `restrict()`.
113
+
Prepare a cascading delete. Propagate a restriction downstream, then trim the diagram to the cascade subgraph. Returns a new `Diagram` containing only the seed table and its descendants. One-shot — cannot be called twice or mixed with `restrict()`.
114
114
115
115
1. Verify no existing cascade or restrict restrictions
116
116
2. Copy diagram, seed `_cascade_restrictions[root]` with `list(table_expr.restriction)`
117
117
3. Propagate via `_propagate_restrictions(root, mode="cascade", part_integrity=part_integrity)`
118
+
4. Trim graph: keep only nodes in `_cascade_restrictions` plus alias nodes connecting them; remove all ancestors and unrelated tables
118
119
119
120
### `restrict(self, table_expr) -> Diagram`
120
121
121
-
Apply restrict condition and propagate downstream. Returns a new `Diagram`. Chainable — can be called multiple times. Cannot be mixed with `cascade()`.
122
+
Select a data subset for export or inspection. Propagate a restriction downstream but preserve the full diagram (ancestors and unrelated tables remain). Returns a new `Diagram`. Chainable — can be called multiple times from different seed tables. Cannot be mixed with `cascade()`.
122
123
123
124
1. Verify no existing cascade restrictions
124
125
2. Copy diagram, seed/extend `_restrict_conditions[root]` with `table_expr.restriction`
@@ -129,10 +130,10 @@ Apply restrict condition and propagate downstream. Returns a new `Diagram`. Chai
1. If `dry_run`: return `preview()` without modifying data
132
-
2. Get non-alias nodes with restrictions in topological order
133
+
2. Get all non-alias nodes in topological order (graph is already trimmed by `cascade()`)
133
134
3. If `prompt`: show preview (table name + row count for each)
134
135
4. Start transaction
135
-
5. Delete in **reverse** topological order (leaves first) via `_restrict_freetable()` + `delete_quick()`
136
+
5. Delete in **reverse** topological order (leaves first) via `_restricted_table()` + `delete_quick()`
136
137
6. On `IntegrityError`: cancel transaction, parse FK error for actionable message about unloaded schemas
137
138
7. Post-check `part_integrity="enforce"`: if any part table had rows deleted but its master did not, cancel transaction and raise
138
139
8. Confirm/commit, return count from the root table
@@ -143,15 +144,15 @@ Drop all tables in `nodes_to_show` in reverse topological order. Pre-checks `par
143
144
144
145
### `preview(self) -> dict[str, int]`
145
146
146
-
Return `{full_table_name: row_count}` for each node with a restriction. Requires `cascade()` or `restrict()` first. Uses `_restrict_freetable()` to apply restrictions with correct OR/AND semantics.
147
+
Return `{full_table_name: row_count}` for each node with a restriction. Requires `cascade()` or `restrict()` first. Uses `_restricted_table()` to apply restrictions with correct OR/AND semantics.
147
148
148
149
### `prune(self) -> Diagram`
149
150
150
151
Remove tables with zero matching rows. With restrictions, removes nodes where the restricted query yields zero rows. Without restrictions, removes physically empty tables. Idempotent and chainable.
0 commit comments