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
{{ message }}
Repository navigation
Commit f8a1dc5
Browse filesBrowse the repository at this point in the historyBrowse files
feat: bring every port to parity with the 1.3.0 codegen and migration work (#567)
* feat: bring every port to parity with the rc19 work
Codegen and migrations, across the five ports:
- @sequenceStart is honoured forward-only: a changed start sets START WITH and
moves the counter to GREATEST(n, max(id)+1) only when it is below, never back
(TypeScript migrate, the Drizzle identity column, C# design-time services,
Kotlin Exposed). Java and Python write no DDL.
- Output paths keyed by metadata package: Python's package layout, C#'s opt-in
csharp.outputLayout / csharp.packageNamespaces, and a Java/Kotlin refusal when
two metadata packages map to one directory. meta init, metaobjects init and
dotnet meta init scaffold the package layout; engine defaults stay flat.
- A value object is never renamed. One claim registry per run in TypeScript,
C# and Python refuses a real clash with ERR_NAME_COLLISION; a collection-name
clash is ERR_COLLECTION_NAME_COLLISION in every port.
- @collectionName and the naming.collections pluralizer drive REST segments in
Java, Kotlin and Python too.
- TypeScript view lowering: every join LEFT OUTER, @schema-only qualification,
declared-type casts, multi-operator origin filters, projection-extends-
projection, filter paths, multi-hop origin.first, TPH scope, and the view
vocabulary (entity-derived fields, origin @segment, base-row operands,
relative dates, case).
- C#: the EF context declares meta migrate's CHECKs (new check-constraint
corpus), JSON-column comments, entity-derived fields are no column, and
framework references are global::-qualified under package namespaces.
- Gates run in both output layouts; ADR-0015, ADR-0044 and ADR-0056 amended.
* fix: close the pre-gate review findings
C# design-time HasDifferences counts a JSON-column comment change; the
framework qualifier leaves global using and preprocessor lines alone.
TypeScript and Python refuse two shared enums with one name instead of
dropping one; Python refuses a package tree it cannot import. An inlined
origin.first with no outer alias is refused, short-name counts are cached
per root, and the init scaffold says a barrel still claims every name.
* refactor(csharp): reuse the companion and global:: helpers in CSharpNaming
* no-mistakes(review): apply reviewer inline fixes
* no-mistakes(review): read NeutralConfig once per gen/verify invocation
* no-mistakes(review): Restore C# duplicate physical-address guard
* no-mistakes(review): Restore obsolete C# ValueObjectNames.Names shim
* no-mistakes(review): Advance new identity sequence past max(id)
* no-mistakes(review): merge CHANGELOG headings; fix using-statement lexer
* no-mistakes(review): Verify round-7 fixes; no further changes needed
* no-mistakes(review): apply reviewer inline fixes
* no-mistakes(test): apply changes made during test validation
* no-mistakes(document): Docs: LEFT OUTER joins, layout and naming parity
* no-mistakes(document): Docs: claim-registry guidance in generator recipe
Copy file name to clipboardExpand all lines: AGENTS.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,7 +71,7 @@ PyPI has had no product change since `0.25.0` — nothing is broken.
71
71
-**Kotlin** — `codegen-kotlin` (KotlinPoet on JVM): entity + Exposed table + Spring controller + payload + relations + filter allowlist + validator + stored-proc + output-parser generators. `integration-tests-kotlin` runs the persistence-conformance corpus through Exposed against Testcontainers Postgres.
72
72
73
73
**Cross-port conformance corpora** (every port runs the shared corpus):
74
-
- Metamodel: `fixtures/conformance/` (510 fixtures; 38 shared corpora in total — per-corpus counts + the corpus x port matrix live in `docs/CONFORMANCE.md`). TS / C# / Java / Python all green.
74
+
- Metamodel: `fixtures/conformance/` (510 fixtures; 39 shared corpora in total — per-corpus counts + the corpus x port matrix live in `docs/CONFORMANCE.md`). TS / C# / Java / Python all green.
- Persistence: `fixtures/persistence-conformance/`. **Query** scenarios run on every port (TS / C# / Java / Kotlin / Python), each provisioning its test DB by executing the committed, TS-produced `canonical/schema.postgres.sql` (Postgres only — Derby dropped for the cross-port query corpus, ADR-0015; the FR-044 `report-*` scenarios also run on SQLite, MySQL and D1 where a port has the engine, see [docs/CONFORMANCE.md](docs/CONFORMANCE.md)). The **migration** scenarios are exercised by **TS only** (TS owns schema migrations). **The corpus now gates WRITES, not just reads (SP-H):** an `op: roundtrip` scenario type INSERTs through each port's runtime/ORM write codec (NOT raw SQL), reads the row back, and asserts the wire-normalized value. The `AllTypes` entity (`roundtrip-all-types.yaml`) carries one field of **every** persistable `field.*` subtype — string/int/long/double/float/decimal/boolean/date/time/timestamp(+tz)/currency/enum/uuid/object — plus an **array-of-VO** `field.object @isArray @storage:jsonb` column (`labels`, written as 2-element / empty-`[]` / single-element arrays across the three rows) — so every subtype write+read (incl. the array-of-value-object jsonb codec) round-trips through every port against Testcontainers PG. (`field.byte`/`field.short`/`field.class` were cut as non-functional registration-only stubs — the matrix tracks only genuinely-supported subtypes; see `fixtures/registry-conformance/README.md` → "Per-subtype write-round-trip matrix".)
77
77
- API-contract: `fixtures/api-contract-conformance/`. TS / C# / Java / Kotlin / Python all green — each port runs **two lanes**: a hand-rolled reference server AND its **generated** API artifact booted over HTTP (the deployed controller/routes; TS+C# full-stack vs Testcontainers PG, Java/Kotlin/Python generated controller + in-memory repo behind the consumer seam). The generated fan-out found 10 real deployment bugs golden snapshots missed. Three sub-corpora run the **generated lane only, on all five ports** — `write-through/`, `projection/` (F22: a view-only `object.projection` serves GET list + GET by id and answers every write verb with `405 {"error": "method_not_allowed"}`) and `report/` (FR-044: a view-backed `object.report` serves GET list, answers `POST` with that same `405`, and mounts no `/{id}` route). That is deliberate, not a gap: what is under test is whether a port's GENERATOR emits those routes, and a hand-rolled reference server would answer every scenario by construction. The `m2m/` sub-corpus also gates **TPH x M:N together** (base-declared, subtype-declared, abstract-mid-declared, a non-subtype source onto a subtype TARGET, and the cross-subtype source id answering `200 []`) — the two corpora were originally built disjoint (`tph/` had no relationships, `m2m/` no discriminators), which is precisely how that defect class survived.
|[`fixtures/requirement-test-identity-conformance/`](../fixtures/requirement-test-identity-conformance/) (the identity, skip state and digest of each generated requirement test, and the filter seam, ADR-0057) | 26 cases | ✓ (reference) | ✓ | identity function inherits via Java; emitted names asserted by its own generator test | ✓ | ✓ |
|[`fixtures/enum-length-conformance/`](../fixtures/enum-length-conformance/) (a string-stored enum's column length: `@maxLength`, else `enums.maxLength`) | 5 cases + 1 overflow + 5 refusals; run by a port that sizes the column | ✓ | ✓ | inherits via Java (one config reader, one resolver) | ✓ | — (sizes no column: emits no DDL or column type; the config reader accepts and shape-checks the `enums` block) |
63
+
|[`fixtures/check-constraint-conformance/`](../fixtures/check-constraint-conformance/) (the CHECK constraints `meta migrate` derives: name and expression text per dialect) | 1 model, 5 expected files (postgres, sqlite, d1, and both skip-redundant variants) | ✓ (reference, `migrate-ts`) | — (no CHECK in a generated model) | — (same) | ✓ (the EF context declares them; live-Postgres `EnsureCreated` lane) | — (same) |
63
64
|[`fixtures/codegen-noop/`](../fixtures/codegen-noop/) (FR-044 — reporting vocabulary: what is lowered, what stays inert) | 1 model pair (`reporting/with` vs `reporting/without`) | ✓ (codegen + migrate) | ✓ | ✓ | ✓ | ✓ |
64
65
|[`fixtures/cube-model/`](../fixtures/cube-model/) (FR-044 Plan 4 — the `cube-model` generator's golden Cube files, plus the canonical model's golden) | 46 cases (36 trees + 10 errors) + 1 canonical golden | ✓ (the exporter is TypeScript-only, spec R6; its `cube` lane also loads the files into a real Cube) | — | — | — | — |
65
66
|[`fixtures/contract-conformance/`](../fixtures/contract-conformance/) (FR-022 — the `contract-schema` and `openapi` generators' golden trees and refusals) | 19 cases (14 trees + 5 errors) | ✓ (one neutral engine, ADR-0034 Amendment 10; the generated API lanes also hold real traffic to the documents) | — | — | — | — |
@@ -111,27 +112,29 @@ corpora, or between its *vocabulary* and its *behaviour* — never gets a row of
111
112
own, and its boundary ends up discoverable only from the feature doc. The split ones
112
113
are recorded here instead.
113
114
114
-
**`identity.primary @sequenceStart`** (one semantic in every port): on a fresh
115
+
**`identity.primary @sequenceStart`** (one semantic in every port that writes DDL): on a fresh
115
116
database the identity or sequence begins at `@sequenceStart`; when the start changes on an
116
-
existing database, the change sets `START WITH` only. It never `RESTART`s, and in 1.3 it does
117
-
not move the current value, because live rows already hold the ids it has handed out (a later
118
-
release is planned to move a counter below the start forward, never backward). The port TODOs below
119
-
are tracked in [#544](https://github.com/metaobjectsdev/metaobjects/issues/544).
120
-
117
+
existing database, the change sets `START WITH n` and moves the counter FORWARD only, to
118
+
`GREATEST(n, max(id) + 1)` when it sits below that. It never `RESTART`s and never moves a counter
119
+
back, because live rows already hold the ids it handed out. Tracked in
Copy file name to clipboardExpand all lines: docs/features/cube-export.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -568,7 +568,7 @@ there.
568
568
569
569
| Difference | Why | Effect |
570
570
|---|---|---|
571
-
| Joins | Cube compiles every join to a `LEFT JOIN`. The view joins a required belongs-to reference `INNER`. | A fact row whose reference matches no row forms a null group in Cube and is dropped by the view. A foreign key constraint on the column makes such a row impossible. |
571
+
| Joins | Cube compiles every join to a `LEFT JOIN`. The view's joins are `LEFT OUTER` too, everywhere (they inner-joined a required reference before). | A fact row whose reference matches no row forms a null group in Cube and, through the outer join, in the view as well. A foreign key constraint on the column makes such a row impossible on the conformance data. |
572
572
| Query time zone | A Cube query may pass `timezone`. The view is UTC only. | With a zone other than `UTC`, Cube re-buckets instants, which is its feature, and also shifts naive timestamps and dates, which the view buckets as stored. |
573
573
| Grains | Cube offers every granularity on a time dimension. | `@grains` is carried as `meta.grains`, not enforced. |
574
574
| Ad-hoc queries | Cube lets a caller pick any members. | Nothing here checks the numbers for a combination no report declares. |
0 commit comments