Problem
Every domain table in mdl/catalog/tables.go (~30 tables) carries the same eight columns:
ProjectId, ProjectName,
SnapshotId, SnapshotDate, SnapshotSource,
SourceId, SourceBranch, SourceRevision
The projects and snapshots lookup tables already exist as proper normalized tables — six of those columns (ProjectName, SnapshotDate, SnapshotSource, SourceId, SourceBranch, SourceRevision) are pure denormalization of snapshots.
This costs:
- Storage — six redundant TEXT columns × ~30 tables × N rows.
- Write code — every
builder_*.go threads snapshot metadata into every INSERT (~70 references across 16 builder files; builder_modules.go alone has 24).
- Drift risk — a row's
SnapshotDate can disagree with snapshots.SnapshotDate if a future builder forgets to update it. No single source of truth.
- Schema noise —
tables.go is 1082 lines, much of it the same six column lines repeated.
Investigation
No external consumers of the denormalized columns:
| Location |
Hits |
Relevant? |
mdl/catalog/ (Go) |
~70 |
yes — builders + views |
mdl/linter/, mdl/executor/, mdl-examples/ |
a few |
no — unrelated ProjectName Go fields / microflow parameters |
reference/mendix-repl/templates/ (user skills) |
0 |
nothing user-facing depends on these |
docs/ (excluding archived proposals) |
0 |
undocumented for users |
Proposed Approach
- Drop the six denormalized columns from every domain table. Keep
ProjectId and SnapshotId as FKs.
ProjectId stays alongside SnapshotId so direct project filtering doesn't force a JOIN — pragmatic, one column of denormalization for ergonomics on the most common filter.
- Replace each table with a view to preserve query compatibility: rename
entities → entities_data, then create entities as SELECT e.*, s.ProjectName, s.SnapshotDate, … FROM entities_data e LEFT JOIN snapshots s …. Existing queries — including the objects UNION view and ad-hoc WHERE SnapshotSource = 'git' queries — keep working unchanged.
Out of scope
- No change to Mendix BSON, MPR format, or any Mendix version. Pure SQLite-side refactor of the local catalog cache.
- Catalog is a cache, not source-of-truth: existing caches regenerate on next build (bump
schemaVersion).
Proposal
Full design, file-by-file plan, test plan, and open questions in docs/11-proposals/PROPOSAL_normalize_catalog_tables.md (to be merged with this issue's branch).
Open questions
- In-place
ALTER TABLE migration vs. bump schemaVersion and regenerate?
- Naming for the underlying storage table —
entities_data, _entities, entities_raw?
objects UNION view performance with 20+ JOINs — measure on a large fixture before merging.
🤖 Generated with Claude Code
Problem
Every domain table in
mdl/catalog/tables.go(~30 tables) carries the same eight columns:The
projectsandsnapshotslookup tables already exist as proper normalized tables — six of those columns (ProjectName,SnapshotDate,SnapshotSource,SourceId,SourceBranch,SourceRevision) are pure denormalization ofsnapshots.This costs:
builder_*.gothreads snapshot metadata into every INSERT (~70 references across 16 builder files;builder_modules.goalone has 24).SnapshotDatecan disagree withsnapshots.SnapshotDateif a future builder forgets to update it. No single source of truth.tables.gois 1082 lines, much of it the same six column lines repeated.Investigation
No external consumers of the denormalized columns:
mdl/catalog/(Go)mdl/linter/,mdl/executor/,mdl-examples/ProjectNameGo fields / microflow parametersreference/mendix-repl/templates/(user skills)docs/(excluding archived proposals)Proposed Approach
ProjectIdandSnapshotIdas FKs.ProjectIdstays alongsideSnapshotIdso direct project filtering doesn't force a JOIN — pragmatic, one column of denormalization for ergonomics on the most common filter.entities→entities_data, then createentitiesasSELECT e.*, s.ProjectName, s.SnapshotDate, … FROM entities_data e LEFT JOIN snapshots s …. Existing queries — including theobjectsUNION view and ad-hocWHERE SnapshotSource = 'git'queries — keep working unchanged.Out of scope
schemaVersion).Proposal
Full design, file-by-file plan, test plan, and open questions in
docs/11-proposals/PROPOSAL_normalize_catalog_tables.md(to be merged with this issue's branch).Open questions
ALTER TABLEmigration vs. bumpschemaVersionand regenerate?entities_data,_entities,entities_raw?objectsUNION view performance with 20+ JOINs — measure on a large fixture before merging.🤖 Generated with Claude Code