feat(ddl): first-class CREATE VIEW / DROP VIEW / MATERIALIZED VIEW - #161
Merged
Conversation
Surface the standard `CREATE VIEW`, `DROP VIEW`, and PG-only `MATERIALIZED VIEW` + `REFRESH MATERIALIZED VIEW` forms via the schema-builder DSL with full dialect-aware rewriting. The embedded SELECT body routes through the same `compile()` pipeline as top-level queries so registered plugins (multi-tenant, soft-delete, CASL) apply automatically — see audit23 for the regression test. Highlights: * `.createView(name).asSelect(query)` — all four dialects * `.orReplace()` — PG / MySQL emit `CREATE OR REPLACE VIEW` * `.orAlter()` — MSSQL emits `CREATE OR ALTER VIEW` (2016 SP1+) * `.materialized()` + `.withData(false)` — PG only * `db.schema.refreshMaterializedView(name).concurrently()` — PG only * `.dropView(name).materialized().ifExists()` — PG DROP MV form `orReplace` and `orAlter` are deliberately separate methods rather than a single API that quietly swaps to MSSQL's spelling. The two forms aren't interchangeable (MSSQL has no `OR REPLACE`; PG/MySQL have no `OR ALTER`) and folding them would obscure dialect-portability mistakes. SQLite has neither and the printer refuses with a pointer at the DROP+CREATE workaround. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
CREATE VIEW,DROP VIEW, PG-onlyMATERIALIZED VIEW+REFRESH MATERIALIZED VIEWvia the schema-builder DSL — no moreunsafeRawExprfor view DDL.compile()pipeline so plugins (multi-tenant, soft-delete, CASL) apply automatically; covered by audit23..orReplace()works on PG/MySQL,.orAlter()works on MSSQL (emitsCREATE OR ALTER VIEW, 2016 SP1+), SQLite refuses both with a pointer atDROP VIEW IF EXISTS + CREATE VIEW.New surface
db.schema.createView(name).asSelect(query)— all four dialects..orReplace()/.orAlter()— mutually exclusive; the two forms aren't interchangeable so we expose them as distinct methods rather than fold MSSQL intoorReplace..materialized()+.withData(false)— PG only; emitsCREATE MATERIALIZED VIEW … WITH NO DATA..temporary(),.ifNotExists(),.columns(...)— standard knobs.db.schema.refreshMaterializedView(name).concurrently().withData(false)— PG only.db.schema.dropView(name).materialized().ifExists()— PGDROP MATERIALIZED VIEW IF EXISTS.Why two methods for OR REPLACE / OR ALTER?
A unified
.orReplace()that silently rewrote to MSSQL'sCREATE OR ALTERwould obscure dialect-portability mistakes (the two forms behave subtly differently —OR ALTERrequires the view's signature to be unchanged on MSSQL,OR REPLACEallows column-list changes within PG's restrictions). Keeping them as distinct builder methods makes the dialect requirement explicit at the call site.Coordination with #160
Agent A's EXCLUDE constraints PR (#160) landed first while this work was in flight. Both touch
src/ast/ddl-nodes.ts,src/dialect/features.ts,src/printer/ddl.ts, anddocs/recipes.md— rebased onto main and the auto-merge resolved cleanly without manual intervention.Test plan
pnpm fmt && pnpm lint && pnpm typecheck— all green.pnpm vitest run— 2247 passed / 58 skipped (+18 new tests intest/ddl/views.test.ts).paramsarray carries the inner SELECT's bound values (DDL print pipeline regression guard).🤖 Generated with Claude Code