How DrawDB Imports SQL Schemas from Different Database Engines: A Deep Dive into the Open-Source Pipeline

DrawDB uses a modular SQL-to-AST parser combined with database-specific transformers to convert DDL from MySQL, PostgreSQL, SQLite, and other engines into its internal diagram model.

The drawdb-io/drawdb repository implements a flexible import pipeline that transforms raw SQL schema definitions into interactive visual diagrams. This article explains how the codebase handles schema parsing across multiple database systems while maintaining type fidelity and producing readable auto-arranged layouts.


Overview of the SQL Import Pipeline

DrawDB's import system follows a six-stage pipeline. Each stage isolates a specific concern, making the architecture extensible for new database engines.

Stage Purpose Key File
Parse SQL to AST Convert raw DDL into a language-agnostic syntax tree sql-ddl-parser (npm dependency)
Route to Converter Select database-specific transformer src/utils/importSQL/index.js
Transform to Internal Model Walk AST and build diagram objects src/utils/importSQL/<engine>.js
Normalize Data Types Map native types to generic DrawDB types src/data/datatypes.js
Auto-Layout Tables Calculate initial canvas positions src/utils/arrangeTables.js
Render Diagram Update React state and paint SVG src/context/DiagramContext.jsx

The pipeline accepts either file drops or pasted DDL text, processing both through identical code paths.


Stage 1: SQL Parsing with sql-ddl-parser

DrawDB delegates initial parsing to the sql-ddl-parser library. This open-source package handles lexical analysis and produces a normalized AST (abstract syntax tree) regardless of source database dialect.

The parser accepts CREATE TABLE statements with constraints, indexes, and foreign keys. It abstracts away syntactic differences—so AUTO_INCREMENT (MySQL), SERIAL (PostgreSQL), and IDENTITY (MSSQL) all become comparable AST nodes before database-specific interpretation.


Stage 2: Database-Specific AST Transformation

The central dispatcher importSQL in src/utils/importSQL/index.js receives the AST and routes it to the appropriate converter. Each supported database has a dedicated module:

Each from<Engine> function implements the same interface: it traverses the AST, extracts structural elements, and returns DrawDB-native objects.

MySQL-Specific Handling

// src/utils/importSQL/mysql.js
// Simplified excerpt showing AUTO_INCREMENT detection

function fromMySQL(ast, diagram) {
  ast.forEach(stmt => {
    if (stmt.type === "create") {
      const table = {
        name: stmt.table.name,
        columns: stmt.columns.map(col => ({
          name: col.name,
          type: dbToTypes(col.datatype, DB.MYSQL),
          nullable: col.nullable !== false,
          primary: col.primary_key || false,
          autoIncrement: col.auto_increment || false
        }))
      };
      diagram.tables.push(table);
    }
  });
}

Key MySQL constructs handled: ENUM types, AUTO_INCREMENT, UNSIGNED integers, and engine clauses.

PostgreSQL-Specific Handling

The PostgreSQL converter in src/utils/importSQL/postgres.js handles:

  • SERIAL and BIGSERIAL pseudo-types (converted to auto-incrementing integers)
  • Array types (INTEGER[], TEXT[])
  • JSONB and JSON column types
  • GENERATED ALWAYS AS computed columns

SQLite-Specific Handling

fromSQLite in src/utils/importSQL/sqlite.js accommodates SQLite's minimal DDL:

  • Implicit INTEGER PRIMARY KEY as ROWID alias
  • WITHOUT ROWID tables
  • Limited foreign key syntax without named constraints
  • Type affinity rules (e.g., VARCHAR(50) affinity-matches to TEXT)

Stage 3: Type Normalization with dbToTypes

Every converter calls dbToTypes from src/data/datatypes.js to translate native column types into DrawDB's generic type system.

Native Type Database DrawDB Generic Type
VARCHAR2(100) Oracle STRING
NVARCHAR MSSQL STRING
SERIAL PostgreSQL INTEGER (autoIncrement=true)
NUMBER(10,2) Oracle DECIMAL
BOOLEAN PostgreSQL BOOLEAN
TINYINT(1) MySQL BOOLEAN

This normalization ensures that diagrams remain portable and that export to different target databases produces valid DDL.


Stage 4: Building the Internal Diagram Model

Converters instantiate three core object types defined in src/data/db.js:

  • Table — Container with name, comment, and positioning metadata
  • Column — Typed field with constraints, default values, and display options
  • Relationship — Foreign key links with cardinality (1:1, 1:N, N:M)

The populated db store becomes the single source of truth for React's state management.


Stage 5: Auto-Arranging the Canvas Layout

After model construction, arrangeTables in src/utils/arrangeTables.js computes initial positions.

The algorithm:

  1. Groups tables by connected components (isolated subgraphs)
  2. Applies force-directed placement to minimize edge crossings
  3. Respects minimum spacing constraints for readability
  4. Centers the viewport on the resulting bounding box

Users can manually reposition tables after import; the layout is non-destructive.


Stage 6: Rendering via React Contexts

The DiagramContext in src/context/DiagramContext.jsx subscribes to the db store and triggers re-renders. Components in src/components/Canvas/ paint:

  • SVG rectangles for tables with header and field sections
  • Bezier curves for relationship lines
  • Cardinality indicators (crow's foot notation)

Programmatic Usage Example

Import a MySQL schema without the UI:

import { importSQL } from "./src/utils/importSQL";
import { DB } from "./src/data/constants";
import { sqlParser } from "sql-ddl-parser";

const ddl = `
CREATE TABLE departments (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL
);

CREATE TABLE employees (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(200) NOT NULL,
  dept_id INT,
  FOREIGN KEY (dept_id) REFERENCES departments(id)
);
`;

const ast = sqlParser(ddl);
const diagram = importSQL(ast, DB.MYSQL, DB.GENERIC);

// diagram.tables.length === 2
// diagram.relationships contains the FK link

Adding Support for New Database Engines

The modular architecture enables straightforward extension:

  1. Create src/utils/importSQL/newengine.js
  2. Export a fromNewEngine(ast, diagram) function
  3. Register the route in src/utils/importSQL/index.js
  4. Add type mappings to src/data/datatypes.js

The existing pipeline handles normalization, layout, and rendering automatically.


Summary

  • DrawDB imports SQL schemas using the sql-ddl-parser library to produce ASTs, then routes to database-specific converters.
  • Six dedicated modules (mysql.js, postgres.js, sqlite.js, mssql.js, mariadb.js, oraclesql.js) handle dialect-specific semantics.
  • Type normalization via dbToTypes ensures cross-database portability.
  • Auto-layout via arrangeTables.js produces readable initial diagrams.
  • Extensible architecture requires only a new converter file to add database support.

Frequently Asked Questions

What databases does DrawDB support for SQL schema import?

DrawDB supports MySQL, PostgreSQL, SQLite, Microsoft SQL Server, MariaDB, and Oracle SQL. Each has a dedicated transformer module in src/utils/importSQL/ that handles dialect-specific syntax like SERIAL, IDENTITY, or VARCHAR2.

Can DrawDB import schemas from SQL dump files?

Yes. The parser accepts any text containing valid DDL CREATE statements. Users can paste dump contents directly or drag-and-drop .sql files. The UI extracts the text and passes it through the same importSQL pipeline.

How does DrawDB handle database-specific data types?

Each converter calls dbToTypes() from src/data/datatypes.js, which maps native types (e.g., PostgreSQL JSONB, Oracle NUMBER) to DrawDB's generic type system. This normalization allows diagrams to be exported to different target databases later.

Is the imported diagram layout editable?

Yes. The arrangeTables function computes only an initial layout. Users can drag tables, resize them, and manually route relationship lines. The auto-layout is non-destructive and can be re-triggered from the UI if desired.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →