feat(ddl): COMMENT ON TABLE / COLUMN with inline MySQL form - #158
Merged
Conversation
PG and MySQL both support attaching prose to schema objects, but the
two grammars are different surfaces: PG has two standalone statements
(`COMMENT ON TABLE` / `COMMENT ON COLUMN`), and MySQL prefers an
inline `COMMENT 'text'` clause inside `CREATE TABLE` for columns plus
an `ALTER TABLE … COMMENT = '…'` for the table-level form. Surface
both through the same schema DSL so a single `defineTable(..., {
comment: "…" })` + `.comment("…")` per column compiles to the right
flavor per dialect.
- AST: `ColumnDefinitionNode.comment?: string` and a new top-level
`CommentNode` (`{ target: "table" | "column", tableName, columnName?,
comment: string | null }`) added to the `DDLNode` union. A `null`
comment is the drop form (`IS NULL` on PG; `COMMENT = ''` on MySQL).
Table and column comments share one node type because they go
through the same diff path and the same `printCommentOn` dispatcher
— splitting them would have duplicated the dialect-routing logic
without adding any clarity.
- Schema DSL: `ColumnBuilder.comment(text)` and a `comment` field on
`TableOptions` / `TableDefinition` / `NormalizedTable`. Threaded
through `normalizeTableEntry`, `buildNormalized`, and
`columnDefinitionFromBuilder` so the value rides the existing
before/after diff machinery.
- Diff engine: a new `commentNodesForTable` helper emits CommentNodes
for (a) freshly-created tables and (b) shared tables where the
before/after table-level or per-column comment differs. Comment
changes are always additive — metadata edits never trip the
destructive-gate.
- DDL printer: `printCommentOn` emits the dialect-correct standalone
statement (PG: `COMMENT ON …`; MySQL: `ALTER TABLE …`); SQLite and
MSSQL throw via `assertFeature(OBJECT_COMMENTS)`. The
`ColumnDefinitionNode.comment` field is inlined inside `CREATE
TABLE` on MySQL and dropped on the other three (PG emits a
follow-up CommentNode; SQLite/MSSQL have no portable equivalent).
MySQL standalone column-comment statements are also refused — the
underlying `ALTER TABLE … MODIFY COLUMN` requires the column's full
type, which we don't carry through to this layer; callers should
use the inline `.comment("…")` form on the column instead.
- Features matrix: `OBJECT_COMMENTS` (PG, MySQL).
- Tests: new `test/migrate/comments.test.ts` covers schema DSL
round-trip, diff materialization (create / add / edit / drop / no-op),
PG and MySQL printer output (including quote-escaping for `Alice's
note`), and the SQLite / MSSQL refusals. 26 new test cases; total
suite goes from 2150 → 2176 passing.
- Docs: a "Schema comments" section in `docs/recipes.md` shows the
DSL surface, side-by-side PG / MySQL emitted SQL, the
metadata-only diff semantics, and the SQLite / MSSQL dialect-support
story.
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
CommentNodeAST +ColumnDefinitionNode.commentfield. PG emits standaloneCOMMENT ON TABLE/COMMENT ON COLUMN; MySQL inlines column comments insideCREATE TABLEand emitsALTER TABLE … COMMENT = '…'for table comments. SQLite and MSSQL refuse viaOBJECT_COMMENTSfeature flag..comment("…")onColumnBuilderand acommentoption ondefineTable. Threaded through the diff engine so comment edits show up as additive migration steps that never trip the destructive-gate.escapeStringLiteralhelper.Test plan
test/migrate/comments.test.ts— 26 cases covering DSL round-trip, diff materialization, PG/MySQL printer SQL shape, quote escaping, and SQLite/MSSQL refusals.pnpm fmt && pnpm lint && pnpm typecheck && pnpm vitest runall green; suite goes from 2150 → 2176 passing tests.Tradeoff: folded table-comment and column-comment into one
CommentNode(discriminated bytarget: "table" | "column") rather than splitting into two node types — they share the same dialect-routing logic at the printer layer and the same before/after diff path, so splitting would have duplicated code without adding clarity. The downside is thecolumnNamefield is conditionally required (only whentarget === "column"); the printer surfaces this with a clear runtime error if the AST is malformed.Generated with Claude Code