Public access to hidden attributes (_job_*, _prov): no reader exists
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Anfängerfreundlichkeit
- 35/100
- Issue-Typ
- Feature
- Klarheit
- Größtenteils klar
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- mysql, postgresql, python
- Bereich
- backend-api-design, database
Rechercherichtung
Start with expression.py, heading.py, and the pinned cases in test_hidden_job_metadata.py and test_entry_provenance.py; compare the proposed hidden view with the narrow-reader alternative before choosing an API. Trace matching, projection, joins, restrictions, and insert handling, then run the listed tests on MySQL and PostgreSQL. Done means decoded hidden values are readable without changing default output, joins, restrictions, DDL round-trips, or singleton behavior.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Platform-managed columns — _job_start_time, _job_duration, _job_version, _prov, _singleton — are stored per row and have no public reader. to_arrays('_job_start_time') and proj('_prov') both raise DataJointError: Attribute '...' not found., because Heading.attributes (heading.py:258-267) excludes hidden names and every accessor derives from it.
reference/specs/job-metadata.md documented to_arrays('_job_start_time', ...) as the access path. That call has never worked; the docs are corrected in datajoint/datajoint-docs#288 to describe the SQL workaround until this lands. Supersedes datajoint-docs#1553.
Deferred out of 2.3.4 deliberately — the mechanism touches query machinery and should not be designed under release pressure.
What works today, so the gap is scoped correctly
Measured on MySQL 8.0, not assumed:
Restrict, string form — & "_prov IS NULL" |
works |
Restrict, mapping form — & {"_prov.system": ...} |
silently returns every row — #1561 |
make_sql(["subject_id", "_prov"]) + decode_attribute |
works, composes with restrictions, decodes JSON to a dict on both backends |
to_arrays('_prov'), proj('_prov'), heading['_prov'] |
raise |
So the missing piece is reading values through a supported surface. Restriction already works in its string form, and a correctly decoded read is reachable today in about six lines — which means the design can be judged on ergonomics and safety rather than on feasibility.
Proposed direction: QueryExpression.hidden
A property returning a copy whose heading also carries the hidden attributes:
Analysis.hidden.to_dicts() # includes _job_* and a decoded _prov
Analysis.hidden.proj('_job_version')
Target.insert(Source.hidden) # INSERT ... SELECT carries them
Returning a copy is what makes it safe: describe(), alter(), diagram and every un-opted query keep the heading they have now.
The invariant
.hidden changes what is selected and returned. It never changes what is matched on. Join and restriction keys must keep coming from the visible set unconditionally. Three findings make that non-negotiable:
expression.py:398,430build theUSINGlist fromheading.names. Hidden namesakes there reproduce exactly the NATURAL JOIN defect the USING clause was introduced to prevent (specs/job-metadata.md, "Excluding Hidden Attributes from Binary Operators").- Hidden attributes never get a lineage row (
lineage.py:366-369skips any column starting with_), soassert_join_compatibility(condition.py:264-289) would raise "lineage missing on one side" for every join of two metadata-bearing tables. condition.py:441selects restriction keys the same way, and that one fails silently.
Where the work is
heading.py— an opt-in flag pluswith_hidden(); an unconditionally-filtered name list for matching;select()(:641) must carry hidden through,join()(:698) must not._attributesalready holds everything with correctjson/uuid/codec/dtypeflags (:499-503), so nothing new is loaded.expression.py— thehiddenproperty (copy idiom at:1507-1516);proj's validator at:572-576.table.py:877-886— theINSERT ... SELECTbranch currently appends_provby name. Generalizing it is tempting but needs thought: copying_singleton, or_job_*from one table to another, is not meaningful. The_prov-specific carry may be correct because it is specific.
Two defects found on this path
expression.py:578-583is a dead validator.next(a for a in mentions if not self.heading.names)tests whether the heading is empty, not whetherais in it. It never fires, for any name.proj(x='_prov')silently drops the column —_provmatchesrename_pattern, bypassing the positional check, andHeading.select's loop never reaches it. No error, no column. Same family as #1561.
The alternative worth taking seriously
Keep hidden attributes fully hidden and add a narrow documented reader instead — a function taking an expression and attribute names, doing the SELECT and decode_attribute itself. It serves the known consumer (provenance-export, which needs _job_version and _prov per row for audit packets) with decoded values and restriction composition, and touches no query machinery.
The case for it is not weak: attributes' filter currently does five distinct jobs — join-key selection, restriction-key selection, output shaping, insert validation, and DDL round-tripping through describe() ↔ prepare_declare ↔ alter. Splitting them is where silent breakage comes from. The case against is that it is a second way to query, outside the algebra.
Decide between them before implementing.
What must not change
| Behavior | Pinned at |
|---|---|
_job_* absent from heading.names and to_dicts() |
test_hidden_job_metadata.py:184-201 |
| Hidden attributes absent from a join result | test_hidden_job_metadata.py:208-224 |
_prov out of heading, fetch, joins |
test_entry_provenance.py:140-152 |
An author cannot write _prov |
test_entry_provenance.py:155-158 |
Config.heading.primary_key == [] for a singleton |
test_declare.py:421 |
describe() omits _singleton |
test_declare.py:477-490 |
| Users cannot declare an underscore attribute | tests/unit/test_declare_hidden_attribute.py |
.hidden would expose _singleton, so primary_key becomes ['_singleton'] in the opted-in view. Correct, but keys() and restriction run off the primary key — verify on a singleton table.
Acceptance
- Reading returns a decoded
_provdict on both MySQL (json) and PostgreSQL (jsonb); backend-consistent decoding is the likeliest thing to break. - Default
to_dicts()byte-identical to today. A * Bwith_job_*on both sides joins on the visible key only, no lineage error.describe()andalter()round-trip unchanged, including a singleton.test_entry_provenance.py's raw-SQL_raw_provhelper is replaced by the new API — that is the real acceptance test.- Also closes the
declare.py:965error message, which tells users to "useproj()" — currently false.
- Vorherrschende Sprache
- Python
- Sterne
- 197
- Forks
- 98
- Ø Merge
- 23 Std. 9 Min.
- Gemergte PRs (30 T.)
- 6
Entwicklungsumgebung
- Enthält ein Dockerfile oder eine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus datajoint/datajoint-python
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
datajoint/datajoint-python#1539 · 3 Kommentare ·
-
Python 3.15 ships Oct 9 and we cap below it; 3.10 went EOL Oct 1Evtl. vergeben @dimitri-yatsenko hat das heute übernommen. Offenenhancement
datajoint/datajoint-python#1569 · 1 zugewiesene Person ·
-
bug
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 75/100
datajoint/datajoint-python#1564 ·
-
bug
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 68/100
datajoint/datajoint-python#1563 ·
-
bug
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 75/100
datajoint/datajoint-python#1561 · 1 Kommentar ·
Alle Issues in datajoint/datajoint-python
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 Ein halber Tag Anfängerfreundlichkeit 70/100
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
Qiskit/qiskit-ibm-runtime#3431 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
[Lesson] A compatibility-gate rejection is a verdict, not something to overwrite with --accept-riskOffenlesson-submission needs-ac pending-review
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
Ikalus1988/MisakaNet#2870 ·
Maintainer antworten meist innerhalb von 1 Tag
-
feature:LinkChecker
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 66/100
digitalfabrik/integreat-cms#4594 ·
Maintainer antworten meist innerhalb von 5 Tagen