Skip to content

Commit 3494ec0

Browse files
docs: rename Diagram.preview() to counts() everywhere
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f353a6a commit 3494ec0

File tree

3 files changed

+17
-17
lines changed

3 files changed

+17
-17
lines changed

src/about/whats-new-22.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ In prior versions, `dj.Diagram` existed solely for visualization — drawing the
213213
- **PostgreSQL** aborts the entire transaction on any error, requiring `SAVEPOINT` / `ROLLBACK TO SAVEPOINT` round-trips for each failed delete attempt.
214214
- **Fragile error parsing** across MySQL versions and privilege levels, where different configurations produce different error message formats.
215215

216-
In 2.2, `Table.delete()` and `Table.drop()` use `dj.Diagram` internally to compute the dependency graph and walk it in reverse topological order — deleting leaves first, with no trial-and-error needed. The user-facing behavior of `Table.delete()` is unchanged. The Diagram's `cascade()` and `preview()` methods are available as a public inspection API for understanding cascade impact before executing.
216+
In 2.2, `Table.delete()` and `Table.drop()` use `dj.Diagram` internally to compute the dependency graph and walk it in reverse topological order — deleting leaves first, with no trial-and-error needed. The user-facing behavior of `Table.delete()` is unchanged. The Diagram's `cascade()` and `counts()` methods are available as a public inspection API for understanding cascade impact before executing.
217217

218218
### The Preview-Then-Execute Pattern
219219

@@ -225,7 +225,7 @@ diag = dj.Diagram(schema)
225225
restricted = diag.cascade(Session & {'subject_id': 'M001'})
226226

227227
# Inspect: what tables and how many rows would be affected?
228-
counts = restricted.preview()
228+
counts = restricted.counts()
229229
# {'`lab`.`session`': 3, '`lab`.`trial`': 45, '`lab`.`processed_data`': 45}
230230

231231
# Execute via Table.delete() after reviewing the blast radius
@@ -238,11 +238,11 @@ This is valuable when working with unfamiliar pipelines, large datasets, or mult
238238

239239
The diagram supports two restriction propagation modes designed for fundamentally different tasks.
240240

241-
**`cascade()` prepares a delete.** It takes a single restricted table expression, propagates the restriction downstream through all descendants, and **trims the diagram** to the resulting subgraph — ancestors and unrelated tables are removed entirely. Convergence uses OR: a descendant row is marked for deletion if *any* ancestor path reaches it, because if any reason exists to remove a row, it should be removed. `cascade()` is one-shot and is always followed by `preview()` or `delete()`.
241+
**`cascade()` prepares a delete.** It takes a single restricted table expression, propagates the restriction downstream through all descendants, and **trims the diagram** to the resulting subgraph — ancestors and unrelated tables are removed entirely. Convergence uses OR: a descendant row is marked for deletion if *any* ancestor path reaches it, because if any reason exists to remove a row, it should be removed. `cascade()` is one-shot and is always followed by `counts()` or `delete()`.
242242

243243
When the cascade encounters a part table whose master is not yet included in the cascade, the behavior depends on the `part_integrity` setting. With `"enforce"` (the default), `delete()` raises an error if part rows would be deleted without their master — preventing orphaned master rows. With `"cascade"`, the restriction propagates *upward* from the part to its master: the restricted part rows identify which master rows are affected, those masters receive a restriction, and that restriction then propagates back downstream to all sibling parts — deleting the entire compositional unit, not just the originally matched part rows.
244244

245-
**`restrict()` selects a data subset.** It propagates a restriction downstream but **preserves the full diagram**, allowing `restrict()` to be called again from a different seed table. This makes it possible to build up multi-condition subsets incrementally — for example, restricting by species from one table and by date from another. Convergence uses AND: a descendant row is included only if *all* restricted ancestors match, because an export should contain only rows satisfying every condition. After chaining restrictions, use `prune()` to remove empty tables and `preview()` to inspect the result.
245+
**`restrict()` selects a data subset.** It propagates a restriction downstream but **preserves the full diagram**, allowing `restrict()` to be called again from a different seed table. This makes it possible to build up multi-condition subsets incrementally — for example, restricting by species from one table and by date from another. Convergence uses AND: a descendant row is included only if *all* restricted ancestors match, because an export should contain only rows satisfying every condition. After chaining restrictions, use `prune()` to remove empty tables and `counts()` to inspect the result.
246246

247247
The two modes are mutually exclusive on the same diagram — DataJoint raises an error if you attempt to mix `cascade()` and `restrict()`, or if you call `cascade()` more than once. This prevents accidental mixing of incompatible semantics: a delete diagram should never be reused for subsetting, and vice versa.
248248

@@ -256,7 +256,7 @@ export = (dj.Diagram(schema)
256256
.restrict(Session & 'session_date > "2024-01-01"')
257257
.prune())
258258

259-
export.preview() # only tables with matching rows
259+
export.counts() # only tables with matching rows
260260
export # visualize the export subgraph
261261
```
262262

@@ -312,7 +312,7 @@ Each yielded `FreeTable` carries any cascade or restrict conditions that have be
312312

313313
### Architecture
314314

315-
`Table.delete()` constructs a `Diagram` internally, calls `cascade()` to compute the affected subgraph, then iterates `reversed(diagram)` to delete leaves first. The Diagram is purely a graph computation and inspection tool — it computes the cascade and provides `preview()` and iteration, but all mutation logic (transactions, SQL execution, prompts) lives in `Table.delete()` and `Table.drop()`.
315+
`Table.delete()` constructs a `Diagram` internally, calls `cascade()` to compute the affected subgraph, then iterates `reversed(diagram)` to delete leaves first. The Diagram is purely a graph computation and inspection tool — it computes the cascade and provides `counts()` and iteration, but all mutation logic (transactions, SQL execution, prompts) lives in `Table.delete()` and `Table.drop()`.
316316

317317
### Advantages over Error-Driven Cascade
318318

@@ -326,7 +326,7 @@ The graph-driven approach resolves every known limitation of the prior error-dri
326326
| Part integrity enforcement | Post-hoc check after delete | Data-driven post-check (no false positives) |
327327
| Unloaded schemas | Crash with opaque error | Clear error: "activate schema X" |
328328
| Reusability | Delete-only | Delete, drop, export, prune |
329-
| Inspectability | Opaque recursive cascade | `preview()` / `dry_run` before executing |
329+
| Inspectability | Opaque recursive cascade | `counts()` / `dry_run` before executing |
330330

331331
## See Also
332332

src/how-to/delete-data.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ diag = dj.Diagram(schema)
212212
restricted = diag.cascade(Session & {'subject_id': 'M001'})
213213

214214
# 2. Preview: see affected tables and row counts
215-
counts = restricted.preview()
215+
counts = restricted.counts()
216216
# {'`lab`.`session`': 3, '`lab`.`trial`': 45, '`lab`.`processed_data`': 45}
217217

218218
# 3. Visualize the cascade subgraph (in Jupyter)
@@ -226,7 +226,7 @@ restricted
226226

227227
- **Preview blast radius**: Understand what a cascade delete will affect before committing
228228
- **Multi-schema inspection**: Build a diagram spanning multiple schemas to visualize cascade impact
229-
- **Programmatic control**: Use `preview()` return values to make decisions in automated workflows
229+
- **Programmatic control**: Use `counts()` return values to make decisions in automated workflows
230230

231231
For simple single-table deletes, `(Table & restriction).delete()` remains the simplest approach. The diagram API is for when you need more visibility before executing.
232232

src/reference/specs/diagram.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ dj.Diagram(Subject) + dj.Diagram(analysis).collapse()
120120
## Operational Methods
121121

122122
!!! version-added "New in 2.2"
123-
Operational methods (`cascade`, `restrict`, `preview`, `prune`) were added in DataJoint 2.2.
123+
Operational methods (`cascade`, `restrict`, `counts`, `prune`) were added in DataJoint 2.2.
124124

125125
Diagrams can propagate restrictions through the dependency graph and inspect affected data using the graph structure. These methods turn Diagram from a visualization tool into a graph computation and inspection component. All mutation operations (delete, drop) are executed by `Table.delete()` and `Table.drop()`, which use Diagram internally.
126126

@@ -130,7 +130,7 @@ Diagrams can propagate restrictions through the dependency graph and inspect aff
130130
diag.cascade(table_expr, part_integrity="enforce")
131131
```
132132

133-
Prepare a cascading delete. Starting from a restricted table expression, propagate the restriction downstream through all descendants using **OR** semantics — a descendant row is marked for deletion if *any* ancestor path reaches it. The returned Diagram is **trimmed** to the cascade subgraph: only the seed table and its descendants remain; all ancestors and unrelated tables are removed. The trimmed diagram is ready for `preview()` and `delete()`.
133+
Prepare a cascading delete. Starting from a restricted table expression, propagate the restriction downstream through all descendants using **OR** semantics — a descendant row is marked for deletion if *any* ancestor path reaches it. The returned Diagram is **trimmed** to the cascade subgraph: only the seed table and its descendants remain; all ancestors and unrelated tables are removed. The trimmed diagram is ready for `counts()` and `delete()`.
134134

135135
| Parameter | Type | Default | Description |
136136
|-----------|------|---------|-------------|
@@ -189,13 +189,13 @@ restricted = (diag
189189
.restrict(Session & 'session_date > "2024-01-01"'))
190190
```
191191

192-
### `preview()`
192+
### `counts()`
193193

194194
```python
195-
diag.preview()
195+
diag.counts()
196196
```
197197

198-
Show affected tables and row counts without modifying data. Works with both `cascade()` and `restrict()` restrictions.
198+
Return affected row counts per table without modifying data. Works with both `cascade()` and `restrict()` restrictions.
199199

200200
**Returns:** `dict[str, int]` — mapping of full table names to affected row counts.
201201

@@ -204,7 +204,7 @@ Show affected tables and row counts without modifying data. Works with both `cas
204204
```python
205205
diag = dj.Diagram(schema)
206206
restricted = diag.cascade(Session & {'subject_id': 'M001'})
207-
counts = restricted.preview()
207+
counts = restricted.counts()
208208
# {'`lab`.`session`': 3, '`lab`.`trial`': 45, '`lab`.`processed_data`': 45}
209209
```
210210

@@ -227,7 +227,7 @@ export = (dj.Diagram(schema)
227227
.restrict(Session & 'session_date > "2024-01-01"')
228228
.prune())
229229

230-
export.preview() # only tables with matching rows
230+
export.counts() # only tables with matching rows
231231
export # visualize the export subgraph
232232
```
233233

@@ -453,7 +453,7 @@ combined = dj.Diagram.from_sequence([schema1, schema2, schema3])
453453

454454
## Dependencies
455455

456-
Operational methods (`cascade`, `restrict`, `preview`, `prune`) use `networkx`, which is always installed as a core dependency.
456+
Operational methods (`cascade`, `restrict`, `counts`, `prune`) use `networkx`, which is always installed as a core dependency.
457457

458458
Diagram **visualization** requires optional dependencies:
459459

0 commit comments

Comments
 (0)