migrations library

Database migrations and schema management for Ormed.

This library provides a complete schema migration system with:

  • Fluent API for defining table structures
  • Reversible migrations with up() and down() methods
  • Driver-agnostic schema operations
  • Migration tracking and execution

Creating Migrations

Extend the Migration class and implement up() and down() methods:

import 'package:ormed/migrations.dart';

class CreateUsersTable extends Migration {
  const CreateUsersTable();

  @override
  void up(SchemaBuilder schema) {
    schema.create('users', (table) {
      table.increments('id');              // Auto-incrementing primary key
      table.string('email').unique();      // VARCHAR with unique constraint
      table.string('name').nullable();     // Nullable string
      table.boolean('active').defaultValue(true);
      table.timestamps();                  // created_at, updated_at
    });
  }

  @override
  void down(SchemaBuilder schema) {
    schema.drop('users', ifExists: true);
  }
}

Column Types

The TableBlueprint provides methods for all common column types:

schema.create('posts', (table) {
  // Primary keys
  table.id();                     // bigIncrements('id')
  table.increments('id');         // Auto-incrementing integer PK
  table.bigIncrements('id');      // Auto-incrementing bigint PK
  table.uuid('id');               // UUID primary key

  // Strings
  table.string('title');          // VARCHAR(255)
  table.string('code', length: 50); // VARCHAR(50)
  table.text('body');             // TEXT
  table.longText('content');      // LONGTEXT

  // Numbers
  table.integer('count');
  table.bigInteger('views');
  table.decimal('price', precision: 10, scale: 2);
  table.float('rating');
  table.double('latitude');

  // Dates & Times
  table.dateTime('published_at');
  table.dateTimeTz('scheduled_at');  // Timezone-aware
  table.timestamp('logged_at');
  table.timestampTz('synced_at');    // Timezone-aware
  table.date('birth_date');
  table.time('start_time');

  // Special types
  table.boolean('is_active');
  table.json('metadata');
  table.jsonb('settings');         // PostgreSQL JSONB
  table.binary('data');
  table.enum_('status', ['draft', 'published', 'archived']);
});

Column Modifiers

Chain modifiers to customize columns:

schema.create('products', (table) {
  table.string('sku')
      .unique()                    // Add unique constraint
      .comment('Stock keeping unit');

  table.string('name')
      .nullable()                  // Allow NULL values
      .collation('utf8mb4_unicode_ci');

  table.decimal('price')
      .defaultValue(0.00)            // Static default value
      .unsigned();                 // No negative values

  table.timestamp('created_at')
      .useCurrentTimestamp()       // DEFAULT CURRENT_TIMESTAMP
      .useCurrentOnUpdate();       // ON UPDATE CURRENT_TIMESTAMP
});

Timestamps & Soft Deletes

Convenience methods for common patterns:

schema.create('posts', (table) {
  table.id();
  table.string('title');

  // Add created_at and updated_at columns
  table.timestamps();              // Non-timezone aware
  table.timestampsTz();            // Timezone aware (UTC)
  table.nullableTimestamps();      // Nullable, no defaults
  table.nullableTimestampsTz();    // Nullable, timezone aware

  // Add soft delete column (deleted_at)
  table.softDeletes();             // Non-timezone aware
  table.softDeletesTz();           // Timezone aware (UTC)
});

Indexes & Foreign Keys

schema.create('posts', (table) {
  table.id();
  table.integer('author_id');
  table.string('slug');
  table.string('category');

  // Simple index
  table.index(['slug']);

  // Composite index
  table.index(['category', 'created_at']);

  // Unique constraint
  table.unique(['slug']);

  // Full-text search index
  table.fullText(['title', 'body']);

  // Foreign key
  table.foreign(['author_id'])
      .references('users', ['id'])
      .onDelete(ReferenceAction.cascade)
      .onUpdate(ReferenceAction.cascade);
});

Foreign Key Shortcuts

schema.create('posts', (table) {
  table.id();

  // Creates integer column + foreign key constraint
  table.foreignId('user_id')
      .constrained('users')        // References users.id
      .onDelete(ReferenceAction.cascade);

  // UUID foreign key
  table.foreignUuid('category_id')
      .constrained('categories');
});

Altering Tables

Use schema.table() to modify existing tables:

class AddAvatarToUsers extends Migration {
  const AddAvatarToUsers();

  @override
  void up(SchemaBuilder schema) {
    schema.table('users', (table) {
      table.string('avatar_url').nullable();
      table.index(['avatar_url']);
    });
  }

  @override
  void down(SchemaBuilder schema) {
    schema.table('users', (table) {
      table.dropColumn('avatar_url');
      table.dropIndex(['avatar_url']);
    });
  }
}

Renaming & Dropping

// Rename table
schema.rename('old_name', 'new_name');

// Drop table
schema.drop('table_name');
schema.drop('table_name', ifExists: true);

// Drop if exists
schema.dropIfExists('table_name');

Migration Registry

Register migrations using MigrationEntry for proper ordering:

final entries = [
  MigrationEntry(
    id: MigrationId.parse('m_20251115014501_create_users_table'),
    migration: const CreateUsersTable(),
  ),
  MigrationEntry(
    id: MigrationId.parse('m_20251115015021_create_posts_table'),
    migration: const CreatePostsTable(),
  ),
];

// Build descriptors sorted by timestamp
final descriptors = MigrationEntry.buildDescriptors(entries);

Running Migrations

Use MigrationRunner to execute migrations:

final runner = MigrationRunner(
  schemaDriver: schemaDriver,
  migrations: descriptors,
  ledger: SqlMigrationLedger(driver: schemaDriver),
);

// Run all pending migrations
await runner.applyAll();

// Rollback last batch
await runner.rollback();

// Get migration status
final status = await runner.status();

Driver-Specific Overrides

Customize schema for different databases:

schema.create('events', (table) {
  table.json('metadata')
      .driverType('postgres', const ColumnType.jsonb());

  table.string('locale')
      .driverOverride('postgres', collation: '"und-x-icu"');

  table.timestamp('synced_at', timezoneAware: true)
      .driverDefault('postgres', expression: "timezone('UTC', now())");
});

Key Classes

Classes

$OrmMigrationRecord
Generated tracked model class for OrmMigrationRecord.
AppliedMigrationRecord
Snapshot of a migration persisted inside the ledger table.
ColumnBuilder
ColumnCommand
Snapshot of a column mutation.
ColumnDefault
Representation of a default value. Literal values and SQL expressions are both supported.
ColumnDefinition
Declarative column metadata captured by the DSL.
ColumnDriverOverride
Driver-specific column hints that override the default definition.
ColumnRename
Records the original and new names for a column rename.
ColumnType
Declarative column type metadata.
DatabaseSeeder
Base class for database seeders that work with OrmConnection
DropTableOptions
ForeignKeyBuilder
ForeignKeyCommand
Snapshot of a foreign key mutation.
ForeignKeyDefinition
Declarative foreign key metadata.
ForeignKeyEntry
IndexCommand
Snapshot of an index mutation.
IndexDefinition
Declarative index metadata.
Migration
Base contract migrations extend.
MigrationAction
Describes a single migration action that occurred.
MigrationDescriptor
Snapshot of a compiled migration ready to be logged inside the ledger.
MigrationEntry
Ties a MigrationId to a Migration instance.
MigrationId
Value object representing a migration identifier derived from its file name.
MigrationLedger
Storage abstraction for recording applied migrations.
MigrationReport
High-level summary returned after applying or rolling back migrations.
MigrationRunner
MigrationSqlExporter
Exports SQL text files derived from schema plan previews.
MigrationStatus
Status information for a migration when listing history.
ModelColumnSnapshot
Snapshot of a single column derived from a model field.
ModelGraphSnapshot
Captures the tables derived from the current ModelDefinition registry.
ModelTableSnapshot
Snapshot of a single model's table shape.
OrmMigrationRecord
OrmMigrationRecordInsertDto
Insert DTO for OrmMigrationRecord.
OrmMigrationRecordModelFactory
OrmMigrationRecordPartial
Partial projection for OrmMigrationRecord.
OrmMigrationRecords
OrmMigrationRecordUpdateDto
Update DTO for OrmMigrationRecord.
RenameTableOptions
SchemaBuilder
Fluent builder that collects schema commands for a migration direction.
SchemaColumn
Metadata describing a table column.
SchemaDialect
Dialects convert individual schema mutations into executable SQL.
SchemaDriver
Contract implemented by database drivers that can execute schema plans and introspect live database metadata.
SchemaForeignKey
Metadata describing a foreign key constraint.
SchemaIndex
Metadata describing an index.
SchemaInspector
High-level helper that mirrors Laravel's schema inspector.
SchemaMutation
A mutation emitted by the schema builder.
SchemaNamespace
Additional metadata about namespaces/schemas available on a connection.
SchemaPlan
Immutable collection of schema mutations.
SchemaPlanCompiler
Translates SchemaPlan objects into SQL statements using a dialect.
SchemaPreview
Preview of the SQL statements a schema plan would execute. A preview of SQL statements that would be executed for a schema plan.
SchemaSnapshot
Captures a read-only snapshot of schema metadata for offline inspection.
SchemaStatement
Represents a single schema statement and optional structured payload.
SchemaTable
Metadata describing a database table (excluding views).
SchemaTableIdentifier
Identifier that pairs a schema with a table name for comparisons.
SchemaView
Metadata describing a database view.
Seeder
Base class for database seeders
SeederRegistration
Seeder registration for managing multiple seeders.
SeederRegistry
Registry and runner for database seeders
SnapshotSchemaDriver
Lightweight driver backed entirely by a SchemaSnapshot.
SqlFileMigration
A Migration implementation backed by SQL files (up.sql and down.sql).
SqliteFullTextOptions
Options for SQLite full text search indexes.
SqliteSpatialIndexOptions
Options controlling SQLite spatial indexes.
SqlMigrationLedger
Generic SQL ledger that persists migrations inside a driver-managed table.
TableBlueprint
Mutable blueprint that records the operations to perform against a table.

Enums

ColumnCommandKind
Low-level column command kinds surfaced through TableBlueprint.
ColumnMutation
Describes whether a column command adds or alters a column.
ColumnTypeName
Logical column type names recognized by the DSL.
ForeignKeyCommandKind
Foreign-key command kinds supported by the fluent DSL.
IndexCommandKind
Index command kinds supported by the fluent DSL.
IndexType
Logical index types that influence naming and SQL generation.
MigrationDirection
Directions supported by a migration lifecycle.
MigrationOperation
Supported operations tracked inside a MigrationAction.
MorphKeyType
Morph key variants supported by helper methods like TableBlueprint.morphs.
ReferenceAction
Reference actions that control cascading behavior for foreign keys.
SchemaMutationOperation
High-level operations supported by the schema planner.
TableOperationKind
Determines whether a blueprint is creating a new table or mutating an existing one.

Typedefs

MigrationPlanResolver = Future<SchemaPlan> Function(MigrationDescriptor descriptor, MigrationDirection direction)
Coordinates applying and rolling back migrations using a SchemaDriver and ledger store.