Skip to content

meta migrate does not implement FR-024 §7 on the schema path: derived entity fields leak into the table DDL and the read-view is never emitted #213

Description

@dmealing

Summary

FR-024 §7 "view behavior on the entity" is doctrine-complete and loader-validated — an object.entity may carry a non-primary read-only source.rdb @kind:view plus derived (origin.*) fields; writes route to the table, reads to the view, derived fields are read-only + excluded from write codecs, and the design promises the view DDL is emitted ("one emitter, two hosts"). The loader even licenses it (ERR_DERIVED_FIELD_NO_READ_SOURCE). But the schema pipeline never implements it, in two places:

1. Derived fields leak into the write table. migrate-ts/src/expected-schema.ts:377 builds a column for every entity.fields() — it never excludes origin-bearing (derived) fields:

for (const field of entity.fields()) {
  // … flattenObjectField / buildColumn — no check for an origin child
}

So a field whose data comes from a join (origin.passthrough @from:"Other.col" @via:"…") gets a spurious column on the write table. Worse: when that column name matches the read-view's own SELECT alias (SELECT E.*, O.col AS col …), the generated CREATE VIEW collides on a duplicate column.

2. The read-view is never emitted. isWriteThrough() (codegen-ts/src/projection/projection-detector.ts:24) is defined, exported (index.ts:83), and tested — but has no call site. buildProjectionViews only walks isProjection objects, so a write-through entity's replica-view DDL is never emitted or owned, despite FR-024 §7.

Impact

An adopter following the FR-024 §7 / entity-read-view on-ramp (model the join extras as derived fields on the entity, the intended clean modeling) gets a wrong table — derived join columns leak in, and can collide with the view — and no view is created. That is a silent-corruption class, more severe than a docs gap. It's the exact reason a downstream migration currently has to quarantine the view-only columns out of the entity's field set as a workaround instead of modeling them properly.

Proposal

  1. Exclude origin-bearing fields from the column loop in expected-schema.ts (a field with an origin.* child is derived → read-only → not a write-table column).
  2. Wire isWriteThrough entities into buildProjectionViews so a write-through entity's replica-view DDL is emitted and owned exactly like a projection's view — reuse the one canonical emitter ("one emitter, two hosts"). The dead-but-tested isWriteThrough is presumably the intended hook.

Not covered by the open issues

This is the schema-pipeline half of FR-024 §7. The entity-read-view docs issue is on-ramp docs only; the view-level-filter and join-type issues extend the view emitter but don't wire the write-through host. So without this, the whole "add the read source and the derived fields" story produces incorrect schema.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions