# How DrawDB Parses and Imports DBML Files: A Complete Technical Guide

> Discover how DrawDB parses and imports DBML files. Learn about the AST generation and internal object transformation process for seamless database diagram creation.

- Repository: [drawDB/drawdb](https://github.com/drawdb-io/drawdb)
- Tags: how-to-guide
- Published: 2026-08-14

---

**DrawDB parses DBML files using the `@dbmljs/parser` library to generate an AST, then transforms the parsed structure into internal diagram objects via the `fromDBML(src, database)` utility in [`src/utils/importFrom/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/importFrom/dbml.js).**

DrawDB is an open-source database design tool that treats DBML (Database Markup Language) as a first-class citizen for schema representation. The application converts plain-text DBML definitions into interactive diagrams through a dedicated import pipeline that maps AST nodes to internal models.

## Overview of the DBML Import Architecture

The DBML import functionality is encapsulated in a pure utility module that isolates parsing logic from the UI layer. The [`src/utils/importFrom/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/importFrom/dbml.js) file exports the `fromDBML` function, which coordinates transformation between external DBML syntax and DrawDB's internal diagram representation.

The parsing pipeline follows these stages:

1. **Tokenization** – Raw DBML text is parsed by the `@dbmljs/parser` library into a structured AST.
2. **Model instantiation** – AST nodes are converted to `Table`, `Column`, `Enum`, and `Relationship` objects.
3. **Reference resolution** – Foreign key targets and enum values are linked to their respective owners.
4. **State integration** – Parsed objects are merged into the current `database` object passed to the function.

## Deep Dive into the Parsing Logic

### Tokenization and AST Generation

The `fromDBML` function delegates initial parsing to the `@dbmljs/parser` library. When invoked with a raw DBML string and the current database state, the function calls the parser's `parse(src)` method to generate an AST describing tables, enums, relationships, and notes.

This AST serves as an intermediate representation that captures the hierarchical structure of the DBML schema without coupling to DrawDB's internal model.

### Transforming Tables and Columns

For each `table` node in the AST, the code creates a new `Table` instance and sets its name property. The function then iterates over the table's `columns` array to instantiate `Column` objects with the following attributes:

- **Data type** – Extracted from the column definition.
- **Constraints** – Primary key (`[pk]`), foreign key (`[ref]`), nullability, and default values.
- **Annotations** – Inline comments and notes attached to specific columns.

The column mapping preserves DBML constraint syntax while translating it into DrawDB's internal validation flags.

### Handling Enums and Relationships

Enum definitions undergo similar transformation. Each `enum` node becomes an `Enum` object, with individual entries converted to `EnumValue` instances. This preserves the enumerated type constraints for databases that support them.

Relationship parsing handles `ref` blocks by resolving source and target table-column identifiers. The parser determines cardinality from arrow direction (`<`, `>`, `-`, `<>`) and stores custom names or comments attached to the relationship definition.

### Resolving References and Annotations

The final parsing stage resolves symbolic references between objects. Foreign key targets are linked to their corresponding table and column objects, while enum values are attached to columns that reference them. Stray comments and table-level notes are preserved and attached to their respective model elements.

The function returns a plain JavaScript structure mirroring the internal diagram representation, ready for immediate integration with the current database state.

## Exporting DBML from DrawDB

While the import pipeline focuses on parsing, understanding the symmetrical `toDBML(diagram)` function in [`src/utils/exportAs/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportAs/dbml.js) provides context for the format's round-trip fidelity. This serializer walks the internal model and emits DBML syntax for tables, enums, and relationships, preserving order, comments, and cardinality annotations.

The export utility generates:

- `Table` blocks with column definitions and constraints.
- `Enum` declarations with value lists.
- `Ref` lines expressing cardinality through arrow notation.
- Inline comments derived from model annotations.

## UI Integration Points

The parsing utilities remain pure functions without direct UI dependencies. Two React components orchestrate the user-facing workflow:

**[`ImportDiagram.jsx`](https://github.com/drawdb-io/drawdb/blob/main/ImportDiagram.jsx)** ([`src/components/EditorHeader/Modal/ImportDiagram.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/EditorHeader/Modal/ImportDiagram.jsx)) handles file loading and invokes `fromDBML` when users import DBML files through the interface.

**[`DBMLEditor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/DBMLEditor.jsx)** ([`src/components/EditorSidePanel/DBMLEditor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/EditorSidePanel/DBMLEditor.jsx)) displays generated DBML and triggers `toDBML` for real-time export or side-panel preview.

## Practical Implementation Examples

### Importing a DBML String into the Diagram

```javascript
import { fromDBML } from '@/utils/importFrom/dbml';
import { useDiagram } from '@/hooks/useDiagram';

const rawDbml = `
Table users {
  id int [pk, increment]
  name varchar
  email varchar [unique, note: 'User contact address']
}

Table posts {
  id int [pk]
  user_id int [ref: > users.id]
  title varchar
}
`;

const { diagram, setDiagram } = useDiagram();

// Parse DBML into internal model
const parsed = fromDBML(rawDbml, diagram.database);

// Merge parsed objects into current diagram state
setDiagram(prev => ({
  ...prev,
  ...parsed,  // Contains tables, enums, relationships
}));

```

### Exporting the Current Diagram as DBML

```javascript
import { toDBML } from '@/utils/exportAs/dbml';
import { useDiagram } from '@/hooks/useDiagram';

const { diagram } = useDiagram();

// Serialize diagram to DBML format
const dbmlString = toDBML(diagram);

// Trigger file download
const blob = new Blob([dbmlString], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'schema.dbml';
a.click();

```

## Summary

- **Primary parser**: DrawDB relies on the `@dbmljs/parser` library to handle tokenization and AST generation from raw DBML text.
- **Import location**: The `fromDBML(src, database)` function in [`src/utils/importFrom/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/importFrom/dbml.js) orchestrates the conversion pipeline.
- **Object mapping**: AST nodes transform into `Table`, `Column`, `Enum`, and `Relationship` instances with resolved references.
- **UI separation**: Pure utility functions ensure parsing logic remains decoupled from React components like [`ImportDiagram.jsx`](https://github.com/drawdb-io/drawdb/blob/main/ImportDiagram.jsx) and [`DBMLEditor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/DBMLEditor.jsx).
- **Bidirectional support**: The complementary `toDBML(diagram)` export function ensures lossless round-tripping between formats.

## Frequently Asked Questions

### What parser library does DrawDB use for DBML files?

DrawDB uses the `@dbmljs/parser` library to parse DBML text. This library tokenizes the input and generates an AST that represents tables, columns, enums, relationships, and notes as structured nodes, which the `fromDBML` function then traverses to build internal objects.

### How does DrawDB handle foreign key relationships during import?

The parser resolves `ref` blocks by identifying source and target table-column identifiers from the AST. It determines cardinality by analyzing arrow direction (`<`, `>`, `-`, or `<>`) in the DBML syntax, then creates `Relationship` objects that link the appropriate columns in the internal model.

### Can DrawDB export diagrams back to DBML format?

Yes. The `toDBML(diagram)` function in [`src/utils/exportAs/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportAs/dbml.js) serializes the internal diagram model back to DBML syntax. It emits `Table` and `Enum` blocks, preserves constraint annotations like `[pk]` and `[ref: > table.id]`, and maintains relationship cardinality through proper arrow notation.

### Where is the DBML import logic located in the DrawDB source code?

The core import logic resides in [`src/utils/importFrom/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/importFrom/dbml.js). UI components that trigger this logic include [`src/components/EditorHeader/Modal/ImportDiagram.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/EditorHeader/Modal/ImportDiagram.jsx) for file imports and [`src/components/EditorSidePanel/DBMLEditor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/EditorSidePanel/DBMLEditor.jsx) for real-time DBML preview and export.