MemberJunction / MemberJunction/MJ
Layered base views: platform-neutral metadata enables a SQL-Server-only feature, and PG CodeGen throws on it
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 323
Description
## One sentence
`metadata/entities/.layered-base-views.json` sets `GeneratedBaseViewName` on two core entities and ships through the normal metadata tree to every install, but `PostgreSQLCodeGenProvider` throws by design when any entity has that field set — so a PostgreSQL install that receives this metadata fails on its next `mj codegen`.
## The two halves
**The metadata is platform-neutral and ships everywhere.** `metadata/entities/.layered-base-views.json` lives inside the normally-pushed `metadata/` tree (`entities` is in `.mj-sync.json`'s `directoryOrder`), so `mj sync push` applies it and the next `Metadata_Sync` migration carries it to all installations. It sets:
| Entity | GeneratedBaseViewName |
|---|---|
| MJ: Version Installations | `vwVersionInstallationsGenerated` |
| MJ: User View Run Details | `vwUserViewRunDetailsGenerated` |
**The feature is SQL-Server-only, enforced by a hard throw.** `packages/CodeGenLib/src/Database/providers/postgresql/PostgreSQLCodeGenProvider.ts` → `assertLayeredBaseViewSupported()`:
> `Entity "..." sets GeneratedBaseViewName = '...', but layered base views are not supported on PostgreSQL. PostgreSQL freezes a view's column list at creation and has no sp_refreshview equivalent, so the application-owned view "..." would silently stop gaining columns that the generated view underneath it picks up. Clear GeneratedBaseViewName and use a fully custom base view (BaseViewGenerated = 0) instead...`
That throw is deliberate and well-reasoned — the problem is not the guard, it is that nothing prevents the enabling metadata from reaching PostgreSQL in the first place.
## Impact
A PostgreSQL installation that applies this metadata and then runs `mj codegen` fails with the error above. The failure is loud rather than silent, which is good, but it is a hard stop on a supported platform triggered by shipped metadata.
## How it surfaced
Found while producing the missing PostgreSQL counterparts for the 6.x migrations (#3471). `V202608050105__v6.1.x__Layered_Base_Views_Pilot` has no viable PG counterpart for exactly this reason: its inner "...Generated" views can never be produced on PostgreSQL. `V202608050100`'s bake correctly omits them, which is why the pilot's wrapper views have nothing to wrap.
Separately and consistent with this: on PostgreSQL, `DROP VIEW __mj."vwVersionInstallations"` fails outright because `spCreateVersionInstallation` / `spUpdateVersionInstallation` are declared to return that view's row type — PostgreSQL tracks a dependency SQL Server does not. So even the wrapper half of the pilot does not translate directly.
## Options (needs a decision — I am not picking one)
1. **Scope the metadata per platform** so PostgreSQL installs never receive `GeneratedBaseViewName`. Needs a mechanism that does not exist today; the metadata layer is deliberately platform-neutral.
2. **Port layered base views to PostgreSQL.** The guard's own text explains why this is hard (frozen view column lists, no `sp_refreshview`); it would need a regeneration strategy for the outer view.
3. **Soften the guard** to a warning that skips layering on PG and generates a normal base view instead. Diverges generated output per platform, which may be worse than failing.
4. **Hold the pilot** until one of the above is settled — revert the metadata, keep the `GeneratedBaseViewName` column (additive and harmless).
Option 4 is the cheapest way to unblock the 6.x PostgreSQL story if a decision is not imminent; the column itself is portable and already handled.
## Related
- #3471 — the missing 6.x PostgreSQL counterparts
- #3253 — the earlier PG metadata gap, for the general class
🤖 Filed with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_019EfGkq8cW9drueo1vEN4sM
Contributor guide
Research direction
Start with metadata/entities/.layered-base-views.json and .mj-sync.json, then read PostgreSQLCodeGenProvider.ts and assertLayeredBaseViewSupported(). Review #3471 and #3253 for platform-specific metadata context. Done means the shipped metadata no longer makes supported PostgreSQL code generation fail, with the chosen behavior documented and verified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, typescript
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100