Files
warkanum 161ac317f0
Release / test (push) Successful in 1m45s
Release / release (push) Successful in 12m24s
Release / pkg-rpm (push) Successful in 2m3s
Release / pkg-deb (push) Successful in 2m17s
Release / pkg-aur (push) Successful in 2m47s
feat(dbml): support multiline table notes in DBML
* Add parsing for triple-quoted table notes in DBML
* Update writer to format multiline notes correctly
* Enhance tests for multiline table notes handling
2026-09-09 21:38:11 +02:00
..

DBML Writer

Generates Database Markup Language (DBML) files from database schema information.

Overview

The DBML Writer converts RelSpec's internal database model representation into DBML syntax, suitable for use with dbdiagram.io and other DBML-compatible tools.

Features

  • Generates DBML syntax
  • Creates table definitions with columns
  • Defines relationships
  • Includes indexes
  • Adds notes and documentation
  • Supports enums

Usage

Basic Example

package main

import (
    "git.warky.dev/wdevs/relspecgo/pkg/models"
    "git.warky.dev/wdevs/relspecgo/pkg/writers"
    "git.warky.dev/wdevs/relspecgo/pkg/writers/dbml"
)

func main() {
    options := &writers.WriterOptions{
        OutputPath: "schema.dbml",
    }

    writer := dbml.NewWriter(options)
    err := writer.WriteDatabase(db)
    if err != nil {
        panic(err)
    }
}

CLI Examples

# Generate DBML from PostgreSQL database
relspec --input pgsql \
  --conn "postgres://localhost/mydb" \
  --output dbml \
  --out-file schema.dbml

# Convert GORM models to DBML
relspec --input gorm --in-file models.go --output dbml --out-file database.dbml

# Convert JSON to DBML for visualization
relspec --input json --in-file schema.json --output dbml --out-file diagram.dbml

Generated DBML Example

Project MyDatabase {
  database_type: 'PostgreSQL'
}

Table users {
  id bigserial [pk, increment]
  username varchar(50) [not null, unique]
  email varchar(100) [not null]
  bio text [null]
  created_at timestamp [not null, default: `now()`]

  Note: 'Users table'

  indexes {
    email [name: 'idx_users_email']
  }
}

Table posts {
  id bigserial [pk, increment]
  user_id bigint [not null]
  title varchar(200) [not null]
  content text [null]
  created_at timestamp [default: `now()`]

  indexes {
    user_id [name: 'idx_posts_user_id']
    (user_id, created_at) [name: 'idx_posts_user_created']
  }
}

Ref: posts.user_id > users.id [delete: cascade, update: no action]

DBML Features

Table Definitions

Table table_name {
  column_name type [attributes]
}

Column Attributes

  • pk - Primary key
  • increment - Auto-increment
  • not null - NOT NULL constraint
  • null - Nullable (explicit)
  • unique - Unique constraint
  • default: value - Default value
  • note: 'text' - Column note

Relationships

Ref: table1.column > table2.column
Ref: table1.column < table2.column
Ref: table1.column - table2.column

Relationship types:

  • > - Many-to-one
  • < - One-to-many
  • - - One-to-one

Relationship actions:

Ref: posts.user_id > users.id [delete: cascade, update: restrict]

Indexes

indexes {
  column_name
  (column1, column2) [name: 'idx_name', unique]
}

Dialect directives

Dialect directives stored on a model object's Metadata (namespace postgres, sqlite, …) are re-emitted verbatim, one line per directive, at the location they belong to:

@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)
  }
}
Emitted at From
Before the first table Database.Metadata
After a column line, as @ns(col): … Column.Metadata
After an index line, inside indexes { } Index.Metadata
After the indexes block, before Note: Table.Metadata

Output is deterministic (ordered by namespace, then source line, then args), so a DBML → model → DBML round-trip is idempotent. See docs/DBML_DIRECTIVES.md for the grammar and the list of directives the PostgreSQL and SQLite writers translate to SQL.

Type Mapping

SQL Type DBML Type
bigint bigint
integer int
varchar(n) varchar(n)
text text
boolean boolean
timestamp timestamp
date date
json json
uuid uuid

Notes

  • DBML is designed for database visualization
  • Can be imported into dbdiagram.io
  • Human-readable format
  • Schema names can be included in table names
  • Comments and notes are preserved
  • Ideal for documentation and sharing designs