docs(examples): pgpm projections — one schema, every shape, one meaning - #1582
Merged
Conversation
The capstone example for the import/transform/diff dials work (planning #1340 Part C / #1329). A single blog schema (blog_app + blog_sec) is imported into a pgpm module and then projected along every axis: - granularity: object / consolidated (and atomic) via pgpm transform - partition: split into app + security modules via pgpm import --partition - diff: schema.sql -> schema-v2.sql as a generated migration via pgpm diff - output: one diff run emits a pgpm module AND a linear .sql at once A database-free jest suite runs the real CLI and proves the invariants at the identity-keyed model: object == consolidated (granularity-invariant), core + security == single module (partition-invariant), the v1->v2 diff is exactly the real changes (2 new tables, 1 new policy, changed posts table, changed function body) with nothing guessed, and the linear SQL projection is dependency-ordered with no CREATE OR REPLACE. Deploy-level catalog equivalence for every granularity (incl. atomic) is already covered against live Postgres by pgpm/cli transform-e2e (dial parity) and diff-e2e. Runs in the no-services 'unit-tests (pglite ...)' CI batch. The lockfile gets only the new package's importer entry (surgical, all workspace:^ links) to avoid the unrelated full-lockfile rewrite a clean install produces on main. Note: atomic authorship emits standalone ADD CONSTRAINT statements whose names Postgres assigns at deploy time; the semantic normalizer does not yet fold those back into the owning table, so atomic is catalog-equivalent rather than AST-identical to object/consolidated. Tracked in constructive-planning.
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The capstone example for the
pgpm import/transform/diffdials work (planning #1340 Part C, #1329). It demonstrates the whole story on one small, realistic schema: normalize a schema to an identity-keyed object set, then everything downstream is a projection of that one model — a projection changes the representation, never the meaning.examples/pgpm-projections/— a two-schema blog platform (blog_app+blog_sec) authored as plain SQL, projected along every axis:A database-free jest suite runs the real CLI (
node pgpm/cli/dist/index.js) and compares the emitted artifacts semantically at the identity-keyed model:object≡consolidated(empty diff)blog-core+blog-securityrecombine ≡ single module (empty diff)v1 → v2yields precisely:added{tags, post_tags tables; audit_log_insert policy},modified{posts table, published_post_count function},removed{} — nothing guessed.sql, dependency-ordered,not.toMatch(/CREATE OR REPLACE/)Deploy-level catalog equivalence for every granularity — including
atomic— is already proven against live Postgres bypgpm/clitransform-e2e(dial parity) anddiff-e2e, so this example stays DB-free and runs in the no-servicesunit-tests (pglite …)batch.Notes for the reviewer
workspace:^links). A cleanpnpm installonmainrewrites ~7k lines ofpnpm-lock.yamlfor unrelated reasons (stale committed lockfile); I deliberately avoided that churn.pnpm install --frozen-lockfilepasses and leaves the lockfile unchanged.atomiccaveat (README + commit):atomicauthorship emits standaloneALTER TABLE … ADD CONSTRAINTstatements whose names Postgres assigns at deploy time. The semantic normalizer folds standalone columns back into their table (covered bysemantic-diff-driverunit test) but not yet standalone constraints, soatomicis guaranteed catalog-equivalent rather than AST-identical toobject/consolidated. That's why the DB-free suite asserts AST-identity only forobject/consolidated/partition. Tightening the normalizer to fold standalone constraints (makingatomicAST-invariant too) is filed as a follow-up inconstructive-planning.Open decision
Built inside
constructive/examples/(reversible). If you'd prefer a standaloneconstructive-io/pgpm-projections-examplerepo, I can lift it out — say the word and pick public/private.Link to Devin session: https://app.devin.ai/sessions/798445577ac8487abf80e28f9ff7a916
Requested by: @pyramation