Skip to content

Commit d2c0360

Browse files
docs: add write caveat for hidden attributes (insert/update1/raw-SQL)
Expand §3.4 with a write caveat covering the three observed behaviors: 1. update1 raises "Attribute '_name' not found" — heading.names is filtered (heading.py:232). 2. insert raises "Field '_name' not in table heading" — Heading.__iter__ walks the filtered view (heading.py:367). 3. insert(..., ignore_extra_fields=True) silently *drops* the hidden key without writing it. Less obvious than the loud error and easy to miss. Also note that platform-managed hidden columns (_job_start_time, etc.) are populated by DataJoint internals via raw SQL during populate() (autopopulate.py:786), not via insert/update1. There is no public-API path to write to a hidden column today; users with a declared hidden column must reach for connection.query() or compute the value inside an auto_populate step. Tracks the write side of the gap that #1441 leaves open.
1 parent 4a07530 commit d2c0360

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

src/reference/specs/table-declaration.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,13 @@ class TaskParams(dj.Manual):
197197
| Natural-join namesake matching | Excluded |
198198
| Dict restriction `Table & {"_name": value}` | Silently ignored |
199199
| String restriction `Table & "_name = ..."` | Included (passes to SQL) |
200-
| `insert()`, `insert1()`, `update1()` | Rejected — key not in heading |
201-
| `describe()` / reverse-engineered definition | **Excluded** — see caveat below |
200+
| `insert()`, `insert1()`, `update1()` | Rejected — see write caveat below |
201+
| `insert(..., ignore_extra_fields=True)` | Silently dropped (key not written) |
202+
| `describe()` / reverse-engineered definition | **Excluded** — see round-trip caveat below |
202203
| `unique index (..., _name)` | Allowed |
203204

205+
**Write caveat.** Neither `insert`/`insert1` nor `update1` accepts hidden attributes through the public API. `update1` raises `DataJointError: Attribute '_name' not found.` `insert` raises `Field '_name' not in table heading` — unless `ignore_extra_fields=True` is passed, in which case the hidden key is *silently dropped* and never written. There is currently no public-API path to populate a user-defined hidden column. Platform-managed hidden columns (the `_job_*` group) are populated by DataJoint internals via raw SQL during the `populate()` lifecycle (see `autopopulate.py`), not via the user-facing `insert`/`update1` methods. If you declare a user-defined hidden column today and need to populate it, you must do so via `connection.query()` with a raw `INSERT` or `UPDATE`, or compute it from a non-hidden column inside an `auto_populate` step.
206+
204207
**Round-trip caveat.** `describe()` walks `heading.attributes`, so it omits hidden attributes from the regenerated definition. For platform-managed hidden columns this is harmless: re-declaring a `Computed` or `Imported` table re-injects `_job_*` automatically. For *user-defined* hidden columns (such as `_params_hash` above), the regenerated definition is incomplete — re-applying it would create a table without the hidden column. Treat `describe()` output as a starting point for review, not as a faithful round-trip when user-defined hidden columns are present.
205208

206209
**Accessing hidden attributes:**

0 commit comments

Comments
 (0)