Skip to content

Commit 287a6cc

Browse files
docs: replace dry_run with safemode workflow and Diagram.counts()
Remove references to the deleted dry_run parameter from delete() and drop(). Document the built-in safemode safety workflow (transaction + preview + confirmation + rollback) and Diagram.cascade().counts() for programmatic preview. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c034302 commit 287a6cc

2 files changed

Lines changed: 18 additions & 17 deletions

File tree

src/about/whats-new-22.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -276,20 +276,27 @@ When a child has multiple restricted ancestors, convergence depends on the mode:
276276

277277
When a child references the same parent through multiple foreign keys (e.g., `source_mouse` and `target_mouse` both referencing `Mouse`), these paths always combine with OR regardless of the mode — each FK path is an independent reason for the child row to be affected.
278278

279-
### Dry Run
279+
### Safe Delete Workflow
280280

281-
`Table.delete()` and `Table.drop()` accept a `dry_run` parameter that returns affected row counts without modifying data:
281+
With `safemode=True` (the default), `delete()` provides a built-in preview-and-confirm workflow:
282+
283+
1. Builds the cascade diagram and computes all affected tables
284+
2. Executes the deletes inside a transaction
285+
3. Logs every affected table and its row count
286+
4. Asks **"Commit deletes?"** — declining **rolls back** all changes
287+
288+
This is safer than a pre-transaction preview because it reflects the actual database state at delete time, including triggers and concurrent changes.
289+
290+
For programmatic preview without executing, use `Diagram` directly:
282291

283292
```python
284-
# Preview what would be deleted
285-
(Session & {'subject_id': 'M001'}).delete(dry_run=True)
293+
diag = dj.Diagram(schema)
294+
counts = diag.cascade(Session & {'subject_id': 'M001'}).counts()
286295
# {'`lab`.`session`': 3, '`lab`.`trial`': 45, '`lab`.`processed_data`': 45}
287-
288-
# Preview what would be dropped
289-
Session.drop(dry_run=True)
290-
# {'`lab`.`session`': 100, '`lab`.`trial`': 5000}
291296
```
292297

298+
The `drop()` method follows the same safemode pattern — previewing affected tables and asking for confirmation before proceeding.
299+
293300
### Unloaded Schema Detection
294301

295302
If a descendant table lives in a schema that hasn't been activated, the graph-driven delete won't know about it. When the final `DELETE` fails with a foreign key error, DataJoint catches it and produces an actionable error message identifying which schema needs to be activated — rather than the opaque crash of the prior implementation.
@@ -326,7 +333,7 @@ The graph-driven approach resolves every known limitation of the prior error-dri
326333
| Part integrity enforcement | Post-hoc check after delete | Data-driven post-check (no false positives) |
327334
| Unloaded schemas | Crash with opaque error | Clear error: "activate schema X" |
328335
| Reusability | Delete-only | Delete, drop, export, prune |
329-
| Inspectability | Opaque recursive cascade | `counts()` / `dry_run` before executing |
336+
| Inspectability | Opaque recursive cascade | `counts()` preview + safemode confirmation before commit |
330337

331338
## See Also
332339

src/how-to/delete-data.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,9 @@ print(f"Deleted {count} subjects")
194194
!!! version-added "New in 2.2"
195195
Cascade inspection via `dj.Diagram` was added in DataJoint 2.2.
196196

197-
For a quick preview, `table.delete(dry_run=True)` returns the affected row counts without deleting anything:
197+
With `safemode=True` (the default), `delete()` provides a built-in safety workflow: it executes the cascade inside a transaction, shows all affected tables and row counts, and asks **"Commit deletes?"** before committing. Declining rolls back all changes.
198198

199-
```python
200-
# Quick preview of what would be deleted
201-
(Session & {'subject_id': 'M001'}).delete(dry_run=True)
202-
# {'`lab`.`session`': 3, '`lab`.`trial`': 45, '`lab`.`processed_data`': 45}
203-
```
204-
205-
For more complex scenarios — working across schemas, chaining multiple restrictions, or visualizing the dependency graph — use `dj.Diagram` to build and inspect the cascade explicitly:
199+
For programmatic preview without executing, or for complex scenarios — working across schemas, chaining multiple restrictions, or visualizing the dependency graph — use `dj.Diagram` to build and inspect the cascade explicitly:
206200

207201
```python
208202
import datajoint as dj

0 commit comments

Comments
 (0)