Why a Schema DSL?
Traditional migration workflows require manually writing SQL for each database driver. Heimdall’s DSL approach:- Define once, deploy anywhere: Write your schema in Rust, generate SQL for Postgres, SQLite, MySQL, or MongoDB
- Type-safe: Compile-time checks ensure your schema is valid
- Idempotent by default: All DDL uses
IF NOT EXISTS/DROP TRIGGER IF EXISTS—safe to run repeatedly - Version control friendly: Schema definition lives in
src/db/schema/definition.rsas source code
Schema Definition
The complete Heimdall schema is defined insrc/db/schema/definition.rs:
Available Column Types
| Builder Method | SQL Type | Description |
|---|---|---|
uuid_pk(name) | UUID PRIMARY KEY | Auto-generates UUIDs using gen_random_uuid() |
uuid(name) | UUID | Standard UUID column |
text(name) | TEXT | Variable-length text |
integer(name) / int(name) | INTEGER | Whole numbers |
boolean(name) | BOOLEAN | True/false |
timestamp(name) | TIMESTAMPTZ | Timezone-aware timestamp |
jsonb(name) | JSONB | JSON with binary storage (Postgres) |
Column Modifiers
Chain modifiers to customize columns:Foreign Keys
Define relationships with.references():
OnDelete behaviors:
OnDelete::Cascade— Delete dependent rowsOnDelete::SetNull— Set foreign key to NULLOnDelete::Restrict— Prevent deletion if dependents exist (default)
Composite Constraints
Helper Methods
Timestamps — addscreated_at and updated_at columns:
updated_at on every row modification.
Soft delete — adds deleted_at column for logical deletes:
Indexes
Add indexes at the schema level:Automatic Schema Application
On every startup, Heimdall:- Calls
heimdall_schema()to build the schema definition - Generates full DDL for the configured driver (Postgres, MySQL, SQLite, or MongoDB)
- Executes the DDL using idempotent statements:
CREATE TABLE IF NOT EXISTSCREATE INDEX IF NOT EXISTSDROP TRIGGER IF EXISTS+CREATE TRIGGER(forupdated_atautomation)
Generating Migration Files
For CI/CD pipelines, external tooling, or manual review, you can export migration SQL files:Output Structure
Migrations are written to:Incremental Migrations
Heimdall supports smart incremental migrations by snapshotting the schema and diffing on the next generation:How It Works
- First run: Generates full schema → saves snapshot in
.schema_snapshot.json - Subsequent runs:
- Loads snapshot
- Compares against current
heimdall_schema() - Generates only the changes:
ALTER TABLE ... ADD COLUMN ...CREATE INDEX IF NOT EXISTS ...DROP INDEX IF EXISTS ...
Example Incremental Migration
If you add a new column tousers:
schema_gen with --incremental generates:
Schema Versioning
The schema definition insrc/db/schema/definition.rs is the single source of truth. Version control your schema changes:
- Option A: Run
cargo run --bin heimdalland let automatic schema application handle it - Option B: Generate migration files in CI, review them, and apply manually:
Driver-Specific Notes
PostgreSQL
- Uses
gen_random_uuid()for UUID generation (requirespgcryptoextension) JSONBfor JSON columns- Triggers for
updated_atautomation
SQLite
- Uses
lower(hex(randomblob(16)))for UUID generation TEXTfor JSON (no native JSONB)- No trigger support for
updated_at—handle in application code
MySQL
- Uses
UUID()function for UUID generation JSONcolumn type (MySQL 5.7.8+)- Triggers supported
MongoDB
Generates JavaScript schema validation scripts instead of SQL DDL.Testing Your Schema
The schema builder includes unit tests:Best Practices
- Always use
timestamps()for audit trails - Prefer
soft_delete()over hard deletes for user-facing data - Index foreign keys explicitly for query performance:
- Use composite unique constraints for natural keys:
- Set
ON DELETEbehavior explicitly on every foreign key
Example: Adding a New Table
Related Files
src/db/schema/definition.rs— Schema definition (source of truth)src/db/schema/builder.rs— DSL builder implementationsrc/db/schema/generator.rs— DDL generators for each driversrc/db/schema/diff.rs— Schema diffing for incremental migrationssrc/db/schema/snapshot.rs— Snapshot serializationsrc/bin/schema_gen.rs— CLI tool for migration generation