SQL DDL → ER: a CREATE TABLE front-end with PK/FK/UK badges - #12
Conversation
Adds SQLDDLParser.parse(_:), a Swift front-end that turns a SQL schema dump into
the ERDiagram IR, so it renders through the same layered layout as a Mermaid
erDiagram. Parses the structural core — CREATE TABLE, typed columns, PRIMARY /
FOREIGN / UNIQUE keys (inline and table-level), and REFERENCES — mapping each
foreign key to a one-to-many crow's-foot relationship. Dialect quoting ("x",
`x`, [x]), comments, and unknown clauses (CHECK/INDEX/DEFAULT/engine options) are
handled or ignored, never fatal; malformed/huge/hostile input returns nil under
the shared maxTextSize/maxEdges caps.
IR + render: ERDiagram.Attribute gains a `keys: [Key]` field (PK/FK/UK), rendered
as a compact right-aligned badge in the entity box. The badge/width code is a
strict no-op when keys is empty, so Mermaid erDiagram output is unchanged (its
parser still leaves keys empty) — no gallery/perf regen triggered.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JoLDcosyaHg3tAKhU5SQaw
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 22 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 528511290a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let table = t[i].text; i += 1 | ||
| guard isPunct("(", at: i) else { skipStatement(); return } // e.g. CREATE TABLE x AS SELECT … |
There was a problem hiding this comment.
Parse qualified table names before requiring the body
For schema-qualified DDL such as CREATE TABLE public.customer (...), the lexer drops the dot and produces two word tokens; this line records public as the table name, and the next line then sees customer instead of ( and skips the whole statement. That means common pg_dump/MySQL dump inputs with qualified names parse as nil or miss most tables instead of producing an ER diagram.
Useful? React with 👍 / 👎.
| case "unique": | ||
| p += 1 | ||
| for col in parenCols(item, &p) { addKey(.unique, to: col, in: &attrs, indexOf: indexOf) } |
There was a problem hiding this comment.
Handle named UNIQUE table constraints
When a dump uses MySQL-style table constraints like UNIQUE KEY email_idx (email) or UNIQUE INDEX ..., p points at KEY/INDEX rather than (, so parenCols returns an empty list and the column never gets a UK badge. This misses a common form of table-level unique constraint even though the parser advertises table-level UNIQUE support.
Useful? React with 👍 / 👎.
| if p < item.count, item[p].word { | ||
| type = item[p].text; p += 1 |
There was a problem hiding this comment.
Preserve multi-word SQL column types
This only captures the first word of a type and only attaches a size clause when it immediately follows that word, so valid dump output like character varying(255), double precision, or timestamp without time zone is rendered as just character, double, or timestamp. For schemas using these common PostgreSQL types, the generated ER attributes show incorrect type information.
Useful? React with 👍 / 👎.
…n bad fixture - SQLDDLParserTests imported CoreGraphics unconditionally (landed in #12, macOS- only gating missed it) → Linux CI red since. Guard it like DOTParserTests (#if canImport(CoreGraphics) … #else import Foundation). Restores Linux green. - DeterminismSignatureTests: XCTUnwrap parse + rasterize instead of skip/nil, so a fixture that silently fails can't make the determinism diff pass vacuously (CodeRabbit). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JoLDcosyaHg3tAKhU5SQaw
A third front-end (after DOT and Dippin): point a SQL schema dump at MermaidKit and get an ER diagram.
SQLDDLParser.parse(_:)turnsCREATE TABLE …into theERDiagramIR, rendered through the same layered layout as a MermaiderDiagram.What it parses
CREATE TABLE t (col TYPE, …), including size clauses (VARCHAR(100),DECIMAL(10,2)).PRIMARY KEY/UNIQUE/FOREIGN KEY, both inline and table-level (incl.CONSTRAINT name …), shown as compactPK/FK/UKbadges.REFERENCES/FOREIGN KEYmaps to a one-to-many crow's-foot relation (parent ||--o{ child)."x",`x`,[x];--and/* */comments; unknown clauses (CHECK,INDEX,DEFAULT, engine options) ignored, never fatal.nilunder the sharedmaxTextSize/maxEdgescaps; forward-progress guards throughout.Example
→ two entity boxes with PK/UK/FK badges and a
customer ||--o{ ordersrelationship (rendered image in the thread).IR change
ERDiagram.Attributegainskeys: [Key](PK/FK/UK), drawn as a right-aligned badge. The badge/width code is a strict no-op whenkeysis empty, and the MermaiderDiagramparser still leaves it empty — so existing ER output is byte-identical (no gallery/perf regen).keyshas a defaulted initializer, so no existingAttribute(type:name:)call site changes.311 tests, 0 failures (12 new). Platform-free parser in
MermaidLayout, besideDOTParser/DippinParser.🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.