Commit f487278
fix(#213): emit the entity read-view's replica view (isWriteThrough → one emitter)
#213 hole 2 (the missing-view half): a write-through entity (FR-024 §7 — a writable
table source PLUS a non-primary read-only view source + derived origin.* fields) never
got its replica view emitted. `isWriteThrough` was defined, exported, and tested but
had ZERO call sites; buildProjectionViews walked isProjection only, so migrate never
generated or owned the view — reads had nowhere to resolve the derived columns from.
Now the entity is a second host for the ONE canonical view emitter ("one emitter, two
hosts"):
- extract-view-spec: a write-through entity IS its own base (isWriteThrough → base =
the entity), and buildSelectSpec exposes its EFFECTIVE field set (o.* incl.
extends-inherited fields) — stored fields project from the base alias, derived
(origin.*) fields from the joins. A plain projection keeps its declared-own-set
exposure + extends-anchored base, unchanged.
- build-projection-views: a second walk over isWriteThrough entities feeds them through
a shared emitViewFor() tail (the projection loop now uses it too — no duplication).
Only a plain `view` read source synthesizes DDL (matview/proc/tableFunction stay
hand-managed, same as projections). isProjection and isWriteThrough are mutually
exclusive, so the walks never overlap.
Together with the write-side exclusions (6a58732), a `SELECT o.*, extra` legacy view
now models cleanly as an entity read-view: writes → the table (no derived columns),
reads → the emitted view. The #206 docs on-ramp becomes drivable.
Verified: new view-emission test (view produced; SELECT = o.* stored fields from the
base + the derived join column; derived col never projects from o.*); codegen-ts 962
pass; typecheck exit 0; canonical schema.postgres.sql drift gate byte-identical (its
view is a projection, not write-through — no overlap).
Follow-up verification (before any release): a migrate round-trip PG/SQLite gate for a
write-through entity (emit → apply → introspect → re-diff EMPTY) + a
persistence-conformance write-through fixture — the emitter is already round-trip-gated
for projections, but the entity host wants its own gate. Known limitation: a flattened
field.object on a write-through entity is not yet handled in the entity-host SELECT
(scalars + derived joins are). The cross-port §7 codegen-half (other ports' ORM/DTO
derived-field exclusions + read routing + the entity read TYPE) remains a separate
coordinated issue.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGQ7oSuNcjhsMHWwZzhBwr1 parent 6a58732 commit f487278
3 files changed
Lines changed: 130 additions & 23 deletions
File tree
- server/typescript/packages/codegen-ts
- src/projection
- test/projection
Lines changed: 45 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
136 | 140 | | |
137 | 141 | | |
138 | 142 | | |
139 | 143 | | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
140 | 170 | | |
141 | 171 | | |
142 | 172 | | |
| |||
Lines changed: 19 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | | - | |
| 47 | + | |
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
52 | 55 | | |
53 | 56 | | |
54 | 57 | | |
| |||
625 | 628 | | |
626 | 629 | | |
627 | 630 | | |
628 | | - | |
629 | | - | |
630 | | - | |
631 | | - | |
632 | | - | |
633 | | - | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
634 | 642 | | |
635 | 643 | | |
636 | 644 | | |
| |||
863 | 871 | | |
864 | 872 | | |
865 | 873 | | |
866 | | - | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
867 | 878 | | |
868 | 879 | | |
869 | 880 | | |
| |||
Lines changed: 66 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
0 commit comments