Skip to main content

Module System

A single DBML file can grow very large, making it difficult to navigate, maintain, and collaborate on. The module system lets you split a schema across multiple files — keeping things organized by domain, sharing common definitions across projects, and importing only what you need.

Overview

Use use to import elements from another file:

use {
type name
} from './path-to-file'
  • type — the element type: table, enum, tablepartial, note, schema, or tablegroup. See Supported Import Types.
  • name — the element name as declared in the source file
  • ./path-to-file — a relative path to the source file; the .dbml extension is optional ('./types' and './types.dbml' both work)
// types.dbml
Enum job_status {
pending running done
}
// jobs.dbml
use {
enum job_status
} from './types'

Table jobs {
id int [pk]
status job_status
}

Each file is isolated by default — nothing is visible across files unless explicitly imported.

Import All

When you want everything a file exports, use * instead of listing each element.

// base.dbml
Table users {
id int [pk]
}

Table orders {
id int [pk]
}
// Everything from ./base.dbml will be imported
use * from './base'

Ref: orders.user_id > users.id

use * and selective imports from the same file can coexist; any duplicate names are deduplicated automatically.

Selective Import

You can selectively pick some elements from another file to import into the current file.

// shared.dbml
Table users {
id int [pk]
}

Enum role {
admin member
}

Table products {
id int [pk]
user_id int [ref: > users.id]
}
// products won't be imported here
use {
table users
enum role
} from './shared'

Supported Import Types

KeywordWhat is imported
tableTable (records and refs come along with it)
enumEnum
tablepartialTablePartial
noteSticky Note
schemaAll elements under that schema
tablegroupTableGroup (all tables in the group)

Element type keywords are case-insensitive (Table, TABLE, and table are all valid).

// auth.dbml
Table auth.users {
id int [pk]
email varchar
}

Table auth.roles {
id int [pk]
name varchar
}

Table auth.sessions {
id int [pk]
}

TableGroup auth_core {
auth.users
auth.roles
}
// u is available as a table here
use {
table auth.users as u
} from './auth'

// auth.users, auth.roles, auth.sessions are available here
use {
schema auth
} from './auth'

// auth_core, auth.user, auth.roles are available here
use {
tablegroup auth_core
} from './auth'

Import Aliases

When two files define elements with the same name, use as to rename imports and avoid conflicts.

// auth.dbml
Table users {
id int [pk]
email varchar
}
// billing.dbml
Table users {
id int [pk]
amount decimal
}
// Alias the tables to avoid name conflicts
use {
table users as auth_users
} from './auth'

use {
table users as billing_users
} from './billing'

Once aliased, only the alias name is accessible — the original name is not.

Re-exporting with reuse

use makes imported elements available only in the current file. If another file imports the current file, it will not see elements brought in via use:

// common/index.dbml
use * from './users'
use * from './orders'
// main.dbml
// users and orders are NOT available here
use * from './common/index'

reuse goes one step further — it also makes them visible to any file that imports the current file.

// common/index.dbml
reuse * from './users'
reuse * from './orders'
// main.dbml
// users and orders are available here
use * from './common/index'

reuse is best for cases where you want to expose some schema elements to other consumers, without forcing the consumers to be aware of the internal folder structure of your project.

use vs reuse illustration

main.dbml can only see include-*.dbml files — those imported via reuse. Files imported via use stay private to the intermediate file.

Notes

use is not transitive — If a.dbml imports b.dbml and b.dbml imports c.dbml via use, elements from c.dbml would not be available in a.dbml. Use reuse if you need to pass elements through.

Circular imports — Because DBML is declarative, files can reference each other without any issues. For example, users.dbml can import from orders.dbml and vice versa.