# How DrawDB Validates Relationships and Handles Cascade Deletes

> Discover how DrawDB validates relationships with JSON Schema and manages cascade deletes using ON DELETE CASCADE clauses. Learn about its robust database schema management.

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

---

**DrawDB validates relationships using JSON Schema validators in [`src/utils/validateSchema.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/validateSchema.js) and handles cascade deletes by parsing the `cascade` keyword into `Constraint.CASCADE` objects that SQL exporters convert into `ON DELETE CASCADE` clauses.**

DrawDB is an open-source database diagramming tool that stores diagrams as JSON objects following the DBML (Database Markup Language) specification. When users define relationships between tables, the application enforces structural integrity through a multi-stage validation pipeline before generating SQL. Understanding how DrawDB validates relationships and handles cascade deletes reveals the safeguards that prevent malformed schemas from reaching production databases.

## JSON Schema Validation for Diagram Integrity

DrawDB employs two distinct validation layers in [`src/utils/validateSchema.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/validateSchema.js) to verify diagram correctness. Both functions instantiate `new Validator()` from the **jsonschema** package to check the diagram object against predefined schemas.

### Generic DBML Schema Validation

The `jsonDiagramIsValid(obj)` function validates the diagram against the standard DBML JSON schema (`jsonSchema`). This ensures the overall structure conforms to the DBML specification before DrawDB-specific processing begins.

### DrawDB-Specific Constraints

The `ddbDiagramIsValid(obj)` function applies the stricter `ddbSchema`, which adds extra constraints required by the DrawDB UI. This validation runs before saving or exporting to catch UI-specific errors that generic DBML validation might miss.

```javascript
// Validate the whole diagram before saving
import { ddbDiagramIsValid } from '@/utils/validateSchema';

if (!ddbDiagramIsValid(diagram)) {
  alert('Diagram contains errors – cannot save.');
}

```

## Parsing Relationships and Cascade Constraints

When the DBML parser processes relationship definitions in [`src/utils/dbml/parse.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/dbml/parse.js), it transforms syntax into internal constraint objects. If a relationship includes the optional `cascade` keyword, the parser sets the constraint type to `Constraint.CASCADE`.

For example, the DBML syntax `TableA.id <|-- TableB.parentId [cascade]` triggers the following logic:

```javascript
// DBML parser extracts a cascade relationship
function parseRelationship(rel) {
  const constraint = {
    type: rel.cascade ? Constraint.CASCADE : Constraint.FOREIGN_KEY,
    // … other fields (source, target, columns)
  };
  return constraint;
}

```

This constraint object travels through the application state until SQL generation, carrying the cascade delete semantics specified by the user.

## SQL Generation with ON DELETE CASCADE

During export, SQL generators in [`src/utils/exportSQL/postgres.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportSQL/postgres.js) and [`src/utils/exportSQL/sqlite.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportSQL/sqlite.js) iterate over table constraints. When encountering `Constraint.CASCADE`, they append the `ON DELETE CASCADE` clause to the foreign key definition.

The PostgreSQL exporter implements this logic to ensure referential integrity actions are preserved in the generated DDL:

```javascript
// PostgreSQL exporter adds ON DELETE CASCADE
function renderConstraint(constraint) {
  if (constraint.type === Constraint.CASCADE) {
    return `FOREIGN KEY (${constraint.column}) REFERENCES ${constraint.refTable}(${constraint.refColumn}) ON DELETE CASCADE`;
  }
  // regular foreign‑key handling …
}

```

SQLite follows an identical pattern in [`src/utils/exportSQL/sqlite.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportSQL/sqlite.js), ensuring consistent cascade behavior across database engines.

## Summary

- **Validation Entry Points:** `jsonDiagramIsValid()` and `ddbDiagramIsValid()` in [`src/utils/validateSchema.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/validateSchema.js) use the **jsonschema** library to validate diagram structure before persistence.
- **Cascade Detection:** The DBML parser in [`src/utils/dbml/parse.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/dbml/parse.js) converts the `[cascade]` keyword into `Constraint.CASCADE` type constraints.
- **SQL Output:** Exporters in [`src/utils/exportSQL/postgres.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportSQL/postgres.js) and [`sqlite.js`](https://github.com/drawdb-io/drawdb/blob/main/sqlite.js) translate `Constraint.CASCADE` into standard `ON DELETE CASCADE` SQL clauses.
- **Integrity Guarantee:** Because validation runs before parsing and export, DrawDB ensures only well-formed relationships reach the generated SQL, preventing runtime database errors.

## Frequently Asked Questions

### How does DrawDB prevent invalid relationships from being exported?

DrawDB runs JSON Schema validation via `ddbDiagramIsValid()` before any export operation. This function checks the diagram against the `ddbSchema`, which enforces DrawDB-specific constraints. If validation fails, the UI blocks the export action, ensuring only structurally sound relationships proceed to SQL generation.

### What database engines support DrawDB's cascade delete feature?

The SQL exporters for PostgreSQL ([`src/utils/exportSQL/postgres.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportSQL/postgres.js)) and SQLite ([`src/utils/exportSQL/sqlite.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportSQL/sqlite.js)) both implement `ON DELETE CASCADE` generation. The constraint system is engine-agnostic at the parsing level, with each SQL dialect generator handling the specific syntax required for cascade operations.

### Can I use cascade updates in addition to cascade deletes?

The current implementation focuses on `ON DELETE CASCADE` through the `Constraint.CASCADE` type. The DBML parser recognizes the `cascade` keyword primarily for delete operations. Update cascades would require extending the constraint types in [`src/utils/dbml/parse.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/dbml/parse.js) and updating the SQL generators to handle `ON UPDATE CASCADE` clauses.

### Where does DrawDB store the cascade constraint information?

Cascade constraints exist as part of the diagram's JSON structure after parsing. The [`src/utils/dbml/parse.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/dbml/parse.js) parser stores them as constraint objects with `type: Constraint.CASCADE`, which persist in the application state until the SQL exporter serializes them into `FOREIGN KEY` definitions with `ON DELETE CASCADE` modifiers.