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
source-kinds.md pointed straight at object.projection for any read-only view, so
an adopter migrating a legacy SQL-view-heavy schema reached for a projection and
immediately hit "enumerate every column." But the most common legacy shape —
`SELECT A.*, extras FROM A JOIN …` — is not a projection; it is the entity with a
read route (FR-024 §7 entity read-view, shipped + gated by
error-derived-field-no-read-source across all ports).
Surfaces entity read-views as the FIRST answer for that shape (verified-loadable
example: writable table source + non-primary view source + one derived
origin.passthrough for the extra; writes→table, reads→view, DDL emitted by the
same assembly logic as a projection view), adds an entity-vs-projection decision
table, and states the two boundaries that still push to a projection: renamed base
columns (one @column per paradigm) and row-filtered views (no view-level WHERE yet
— tracked by the #207@filter FR). Docs-only; no metamodel change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGQ7oSuNcjhsMHWwZzhBwr
A derived field must be **providable** — a read-capable source must be able to carry it. A
86
+
derived field on a table-only entity (no read source) is a load error
87
+
(`ERR_DERIVED_FIELD_NO_READ_SOURCE`).
88
+
89
+
### Entity read-view vs projection — which to reach for
90
+
91
+
| Use an **entity read-view** when | Use a **projection** when |
92
+
|---|---|
93
+
| the extras sit over the entity's **own** table | it is an independent **exposure contract**|
94
+
| same read trust-domain — a new entity field appearing in the view is correct, not a leak | a subset / **renamed** columns / versioned / external consumers |
95
+
| you can still INSERT the base and it is the record of truth | keyless, multi-base, or proc-backed; all-derived; borrowed / no identity |
96
+
97
+
Two boundaries still push you to a projection (or a later FR):
98
+
99
+
-**Renamed base columns.** A field carries one `@column` per paradigm, so renaming a base
100
+
column *in the view* is the projection's whole point — a projection field maps an
101
+
`extends`-bound source column to a new `@column`.
102
+
-**Row-filtered views** (`… WHERE status = 'active'`, soft-delete) have no view-level `WHERE`
103
+
slot yet — tracked by the view-level `@filter` FR ([#207](https://github.com/metaobjectsdev/metaobjects/issues/207)).
104
+
48
105
### View — projection over an existing entity
49
106
50
-
A read-only view is declared as an `object.projection`, not an `object.entity` (an
51
-
entity's primary source must be writable). A projection's identity is optional and, when
107
+
When the read shape is an **independent exposure contract** (a subset, renamed columns, a
108
+
versioned or externally-consumed shape — see the decision table above) rather than the
109
+
owning entity's own columns, declare it as an `object.projection`, not an `object.entity`
110
+
(an entity's primary source must be writable). A projection's identity is optional and, when
52
111
present, MUST extend an entity identity; the example below omits it (a keyless read
53
112
model).
54
113
@@ -251,6 +310,10 @@ The following conformance fixtures gate this feature's behavior across ports:
251
310
-[`fixtures/conformance/source-db-view-projection/`](../../fixtures/conformance/source-db-view-projection/) — view with origins
252
311
-[`fixtures/conformance/source-db-view-with-schema/`](../../fixtures/conformance/source-db-view-with-schema/) — `@schema` on view
253
312
313
+
**Entity read-view (derived field must be providable)**
314
+
315
+
-[`fixtures/conformance/error-derived-field-no-read-source/`](../../fixtures/conformance/error-derived-field-no-read-source/) — a derived (`origin.*`) field on a table-only entity (no read-capable source) is `ERR_DERIVED_FIELD_NO_READ_SOURCE`
316
+
254
317
**Multi-source via `@role`**
255
318
256
319
-[`fixtures/conformance/source-multi-source-roles/`](../../fixtures/conformance/source-multi-source-roles/) — primary + secondary sources on one object
0 commit comments