feat(dbml): @postgres/@sqlite dialect directives (#19)
Add parseable `@<namespace>[(<target>)]: <args>` directives embedded in DBML.
They are stored losslessly on each object's Metadata, round-trip unchanged
through the DBML writer, and are translated to SQL only by the writer for the
matching dialect.
- models: Directive type + catalog; Metadata map added to Column and Index
- dbml reader: parse and attach directives at database/table/column/index
level; line-numbered errors; repeatable by default with singleton duplicate
detection. Fixes a preexisting bug where an `indexes {}` closing brace ended
the table early, dropping trailing Note: and directive lines.
- dbml writer: re-emit directives at their location; idempotent output
- pgsql writer: PARTITION BY / INHERITS / WITH / TABLESPACE (table),
STORAGE / COMPRESSION / identity (column), WITH / TABLESPACE (index)
- sqlite writer: WITHOUT ROWID / STRICT (table), COLLATE (column)
- --strict-directives flag on ReaderOptions and WriterOptions
- docs/DBML_DIRECTIVES.md + reader/writer READMEs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ss2MY5J11cRGwEz86ZXk7d
This commit is contained in:
@@ -93,6 +93,50 @@ Ref: posts.user_id > users.id [delete: cascade]
|
||||
- Indexes and composite indexes
|
||||
- Table notes and column notes
|
||||
- Enums
|
||||
- Dialect directives (`@postgres:` / `@sqlite:` — see below)
|
||||
|
||||
## Dialect directives
|
||||
|
||||
Lines of the form `@<namespace>[(<column>)]: <args>` embed database-specific
|
||||
features that plain DBML cannot express (partitioning, `WITHOUT ROWID`,
|
||||
tablespaces, index storage parameters, …). They are stored losslessly on the
|
||||
relevant object's `Metadata` and round-trip unchanged through the DBML writer;
|
||||
the PostgreSQL and SQLite writers translate the ones they understand to SQL.
|
||||
|
||||
```dbml
|
||||
@postgres: search_path myapp
|
||||
|
||||
Table myapp.events {
|
||||
id bigint [pk]
|
||||
created_at timestamp [not null]
|
||||
@postgres(id): identity always
|
||||
@postgres: partition by RANGE (created_at)
|
||||
@sqlite: without rowid
|
||||
|
||||
indexes {
|
||||
(created_at) [name: 'idx_events_created']
|
||||
@postgres: with (fillfactor=90)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Position | Attaches to |
|
||||
|----------|-------------|
|
||||
| Before the first `Table {` | database |
|
||||
| Table body, no `(target)` | that table |
|
||||
| Table body, `(col)` target | column `col` (error if unknown) |
|
||||
| Inside `indexes { }` | the most recently listed index entry |
|
||||
|
||||
`args` is preserved verbatim; the **key** (lowercased first token) drives
|
||||
duplicate detection. Repeated directives are kept in order; catalog "singleton"
|
||||
keys error on a second occurrence at the same location. All errors are
|
||||
line-numbered.
|
||||
|
||||
`ReaderOptions.StrictDirectives` (CLI `--strict-directives`) turns an unknown
|
||||
namespace or key into an error instead of preserving it silently.
|
||||
|
||||
See [`docs/DBML_DIRECTIVES.md`](../../../docs/DBML_DIRECTIVES.md) for the full
|
||||
grammar and the supported-directive matrix.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user