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:
fromMySQL—src/utils/importSQL/mysql.jsfromPostgres—src/utils/importSQL/postgres.jsfromSQLite—src/utils/importSQL/sqlite.jsfromMSSQL—src/utils/importSQL/mssql.jsfromMariaDB—src/utils/importSQL/mariadb.jsfromOracleSQL—src/utils/importSQL/oraclesql.js
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:
SERIALandBIGSERIALpseudo-types (converted to auto-incrementing integers)- Array types (
INTEGER[],TEXT[]) JSONBandJSONcolumn typesGENERATED ALWAYS AScomputed columns
SQLite-Specific Handling
fromSQLite in src/utils/importSQL/sqlite.js accommodates SQLite's minimal DDL:
- Implicit
INTEGER PRIMARY KEYasROWIDalias WITHOUT ROWIDtables- Limited foreign key syntax without named constraints
- Type affinity rules (e.g.,
VARCHAR(50)affinity-matches toTEXT)
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 metadataColumn— Typed field with constraints, default values, and display optionsRelationship— 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:
- Groups tables by connected components (isolated subgraphs)
- Applies force-directed placement to minimize edge crossings
- Respects minimum spacing constraints for readability
- 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:
- Create
src/utils/importSQL/newengine.js - Export a
fromNewEngine(ast, diagram)function - Register the route in
src/utils/importSQL/index.js - 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-parserlibrary 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
dbToTypesensures cross-database portability. - Auto-layout via
arrangeTables.jsproduces 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →