# How DrawDB Generates Diagrams from AI Prompts: A Complete Technical Breakdown

> Discover how DrawDB generates diagrams from AI prompts using a four-stage pipeline: AI request, JSON normalization, auto layout, and state integration. Learn the technical breakdown.

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

---

**DrawDB converts natural language or SQL prompts into interactive database diagrams through a four-stage pipeline: extension‑based AI request, JSON normalization, automatic table layout, and state integration.**

DrawDB's AI-powered import feature lets you describe a database schema in plain English—or paste raw SQL—and instantly receive a fully-rendered, editable diagram. This article examines the exact code path that transforms your prompt into structured diagram state, based on the `drawdb-io/drawdb` source code.

## The Four-Stage AI Import Pipeline

### Stage 1: Initiating the AI Request

The journey begins in [`src/components/EditorHeader/Modal/Modal.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/components/EditorHeader/Modal/Modal.jsx). When a user clicks **Import with AI**, the modal invokes `importSourceWithAi`:

```javascript
// Modal.jsx lines 92-104
const importSourceWithAi = async () => {
  setLoading(true);
  try {
    const diagram = await importSqlWithAi({
      sql: importSource.src,
      database: database === DB.GENERIC ? importDb : database,
      allowedTypes: allowedTypesFor(database),
    });
    // ...normalization and state application
  } finally {
    setLoading(false);
  }
};

```

This function delegates the actual AI call to `importSqlWithAi`, an **extension hook** provided by `ExtensionsContext`. The hook packages three critical pieces of information:
- `sql` — the raw prompt or SQL text
- `database` — the target database engine (PostgreSQL, MySQL, etc., or generic)
- `allowedTypes` — valid column types for that engine, drawn from `dbToTypes`

The extension sends this payload to an external AI service (e.g., OpenAI), which returns a **JSON diagram description** containing tables, fields, relationships, enums, and custom types.

### Stage 2: Normalizing the AI Response

Once the AI service responds, the raw JSON flows into `normalizeAiDiagram` in [`src/utils/importAiDiagram.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/importAiDiagram.js) (lines 58-118). This function hardens the AI output into a valid internal diagram structure:

```javascript
// importAiDiagram.js
export function normalizeAiDiagram(raw, database) {
  // 1. Validate presence of tables
  if (!raw.tables || raw.tables.length === 0) {
    throw new Error("AI response contains no tables");
  }

  const warnings = [];
  const typeMap = dbToTypes[database];

  // 2. Resolve column types against database-specific type map
  raw.tables.forEach(table => {
    table.fields = table.fields.map(field => ({
      ...field,
      type: resolveType(field.type, typeMap, warnings)
    }));
  });

  // 3. Filter invalid relationships
  const validRelationships = raw.relationships?.filter(r => {
    const valid = relationshipPointsToValidColumns(r, raw.tables);
    if (!valid) warnings.push(`Relationship ${r.name} references missing columns`);
    return valid;
  }) || [];

  // 4. Construct diagram object
  const diagram = {
    tables: raw.tables,
    relationships: validRelationships,
    enums: raw.enums || [],
    customTypes: raw.customTypes || [],
  };

  // 5. Validate final structure and compute layout
  jsonDiagramIsValid(diagram);
  arrangeTables(diagram);

  return { diagram, warnings };
}

```

Three key operations happen here:

- **Type resolution** via `resolveType`: Maps AI-generated type strings to valid database types, handling aliases from `TYPE_ALIASES`, user-defined enums, and falling back to `FALLBACK_TYPES` for unrecognized entries.

- **Relationship filtering**: Verifies that every relationship endpoint points to actual table columns, collecting warnings for any orphans.

- **Schema validation**: `jsonDiagramIsValid` ensures the diagram conforms to DrawDB's internal schema before layout computation.

### Stage 3: Automatic Table Layout

After normalization, `arrangeTables` (imported from [`src/utils/arrangeTables.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/arrangeTables.js)) calculates an initial visual arrangement. This prevents overlapping tables and provides a sensible starting point for the diagram. The layout algorithm considers table dimensions and applies a force-directed or grid-based positioning strategy—details vary by DrawDB version, but the goal is always **instant visual coherence without manual positioning**.

### Stage 4: State Integration

The normalized diagram returns to [`Modal.jsx`](https://github.com/drawdb-io/drawdb/blob/main/Modal.jsx), where `applyImportedDiagram` (lines 63-85) merges it into the application's React state:

```javascript
// Modal.jsx
const applyImportedDiagram = (diagram) => {
  setTables(diagram.tables);
  setRelationships(diagram.relationships);
  setEnums(diagram.enums || []);
  setCustomType(diagram.customTypes || []);
  setTypes(diagram.types || []);
  setNotedef(diagram.notes || []);
  setAreas(diagram.areas || []);
  setUndoStack([]);
  setRedoStack([]);
  saveDiagram();
};

```

This operation:
- Replaces all current diagram entities with AI-generated ones
- Clears undo/redo history (the import is treated as a fresh start)
- Persists the result via `saveDiagram()`

If `normalizeAiDiagram` returned warnings, the modal displays them via toast notification before closing.

## Key Data Structures and Configuration

### Type Resolution Pipeline

The `resolveType` function (in [`importAiDiagram.js`](https://github.com/drawdb-io/drawdb/blob/main/importAiDiagram.js)) implements a priority-based lookup:

1. **Direct match** in `dbToTypes[database]`
2. **Alias resolution** through `TYPE_ALIASES` (e.g., "string" → "VARCHAR")
3. **User-defined enum/type** matching
4. **Fallback types** for unrecognized entries

This ensures that even imprecise AI type descriptions produce valid, database-specific column definitions.

### Database-Specific Type Maps

[`src/data/datatypes.js`](https://github.com/drawdb-io/drawdb/blob/main/src/data/datatypes.js) exports `dbToTypes`, a comprehensive mapping for every supported engine:

```javascript
// datatypes.js (conceptual)
export const dbToTypes = {
  [DB.POSTGRESQL]: { "VARCHAR": {...}, "INTEGER": {...}, ... },
  [DB.MYSQL]: { "VARCHAR": {...}, "INT": {...}, ... },
  // ...other engines
};

```

The `allowedTypesFor(database)` helper extracts just the type names for the AI prompt context, constraining the model's output to valid options.

## Comparing AI Import to Other Import Methods

DrawDB offers multiple import paths. Here's how AI generation differs:

| Method | Input | Processing | Best For |
|--------|-------|------------|----------|
| **AI Import** | Natural language or SQL | External AI service + normalization | Rapid prototyping, complex schemas described verbally |
| **SQL Import** | Valid SQL DDL | Parser-based, no external service | Existing database scripts, precise control |
| **JSON Import** | DrawDB export format | Direct validation only | Backup restoration, cross-workspace transfer |

The AI path trades **determinism for convenience**—the normalization layer in [`importAiDiagram.js`](https://github.com/drawdb-io/drawdb/blob/main/importAiDiagram.js) exists specifically to recover from AI hallucinations or imprecise type names.

## Error Handling and Edge Cases

The pipeline includes several safeguards:

- **Empty table detection**: Throws immediately if AI returns no tables
- **Type fallback**: Never fails on unrecognized types; warns and substitutes
- **Relationship orphaning**: Silently drops broken relationships with warnings
- **Schema validation**: Final `jsonDiagramIsValid` check prevents corrupt state

These layers mean the AI import rarely fails completely—instead, it degrades gracefully with actionable warnings.

## Summary

- **Trigger**: `importSourceWithAi` in [`Modal.jsx`](https://github.com/drawdb-io/drawdb/blob/main/Modal.jsx) initiates the flow via `importSqlWithAi`
- **AI Request**: Extension hook sends prompt + database context to external service
- **Normalization**: `normalizeAiDiagram` validates, resolves types, filters relationships, and runs `arrangeTables`
- **Integration**: `applyImportedDiagram` atomically replaces diagram state and resets history
- **Resilience**: Multiple fallback layers ensure usable output even from imperfect AI responses

## Frequently Asked Questions

### What AI service does DrawDB use for diagram generation?

DrawDB delegates AI requests to external services through its extension system. The core repository provides the `importSqlWithAi` hook interface in `ExtensionsContext`, but the actual implementation—whether OpenAI, Anthropic, or another provider—is supplied by the deployed extension. This architecture keeps the open-source core provider-agnostic.

### Can I use AI import with any database type?

Yes. The `allowedTypesFor(database)` function dynamically constrains the AI's output to valid types for your selected engine. If you select **Generic** mode, the modal prompts you to choose a specific database first, ensuring type resolution succeeds in `normalizeAiDiagram`.

### What happens if the AI generates invalid SQL types?

The `resolveType` function in [`importAiDiagram.js`](https://github.com/drawdb-io/drawdb/blob/main/importAiDiagram.js) implements a three-tier fallback: exact match, alias lookup, then `FALLBACK_TYPES` substitution. You'll receive a warning toast describing any replacements, but the import completes with safe defaults rather than failing.

### How does DrawDB prevent overlapping tables in AI-generated diagrams?

After normalization, `arrangeTables` from [`src/utils/arrangeTables.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/arrangeTables.js) computes non-overlapping positions before state integration. The algorithm runs server-side in the normalization phase, so users see a coherent layout immediately without manual adjustment.