# 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

```go
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

```bash
# 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

```dbml
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
```dbml
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
```dbml
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:
```dbml
Ref: posts.user_id > users.id [delete: cascade, update: restrict]
```

### Indexes
```dbml
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:

```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)
  }
}
```

| 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`](../../../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
