Migration System Feature
Overview​
The Migration System provides automatic database schema migration generation and execution. It detects schema changes from model definitions, generates SQL migrations, and executes them safely with rollback support.
Location​
forge/db/migrate/ and forge/migrate/
Status​
✅ Complete - Production ready
Core Components​
1. Migration Generation (forge/db/migrate/generate/)​
Purpose: Generate migration files from schema changes
Components:
generator.go- Main migration generatordetector.go- Change detection between schema statesdependencies.go- Migration dependency resolutionsquash.go- Migration squashing (combining multiple migrations)
Key Features:
- AST-based schema parsing
- State comparison and diff generation
- SQL generation for multiple database dialects
- Migration file creation with up/down SQL
- Dependency tracking
2. State Management (forge/db/migrate/state/)​
Purpose: Track and manage database schema state
Components:
manager.go- State manager interfaceloader.go- Load state from migration filesinmemory.go- In-memory state implementationconverter.go- Convert between state formatssorting.go- Migration file sorting
State Structure:
type SchemaState struct {
Tables map[string]*TableState
}
type TableState struct {
Name string
Columns map[string]*ColumnState
Indexes map[string]*IndexState
ForeignKeys map[string]*ForeignKeyState
Constraints map[string]*ConstraintState
}
3. Change Detection (forge/db/migrate/generate/detector.go)​
Purpose: Detect differences between current and previous schema
Change Types:
CreateTable- Create new tableDropTable- Drop tableRenameTable- Rename tableAddColumn- Add column to tableDropColumn- Drop column from tableModifyColumn- Modify column definitionRenameColumn- Rename columnAddIndex- Add indexDropIndex- Drop indexModifyIndex- Modify indexAddForeignKey- Add foreign key constraintDropForeignKey- Drop foreign key constraintAddConstraint- Add custom constraintDropConstraint- Drop constraintRunSQL- Execute raw SQLRunGo- Execute Go code migration
4. SQL Generation (forge/db/migrate/sql/)​
Purpose: Generate database-agnostic SQL from changes
Components:
builder.go- Base SQL builderpostgres.go- PostgreSQL-specific SQLsqlite.go- SQLite-specific SQLcommon.go- Common SQL utilities
Features:
- Dialect-aware SQL generation
- Proper identifier escaping
- Transaction support
- Rollback SQL generation
5. Migration Execution (forge/db/migrate/execute/)​
Purpose: Execute migrations safely with rollback support
Components:
executor.go- Migration executor (wraps golang-migrate)apply.go- Apply migrationsrollback.go- Rollback migrationsstatus.go- Check migration statusdryrun.go- Dry-run migrationsrecover.go- Recover from failed migrationsvalidator.go- Validate migrationschecksum.go- Migration checksum verification
Features:
- Transaction-wrapped migrations
- Rollback support
- Migration status tracking
- Dirty state detection
- Checksum verification
- Dry-run mode
6. Migration Verification (forge/db/migrate/verify/)​
Purpose: Verify migrations and detect schema drift
Components:
drift.go- Detect schema driftsafety.go- Safety checks for migrationssyntax.go- SQL syntax validationlint.go- Migration lintingchecksum.go- Checksum verification
7. Migration Parsing (forge/db/migrate/parse/)​
Purpose: Parse existing migration files
Components:
parse.go- Main parserlexer.go- SQL lexerddl.go- DDL statement parsingtables.go- Table structure extractionclassifier.go- Statement classification
Features​
✅ Complete Features​
- Schema Detection - Automatic schema detection from model definitions
- Change Detection - Compare current and previous schema states
- SQL Generation - Generate database-agnostic SQL
- Migration Execution - Execute migrations with transactions
- Rollback Support - Rollback migrations safely
- State Management - Track schema state across migrations
- Dependency Resolution - Handle migration dependencies
- Checksum Verification - Verify migration integrity
- Drift Detection - Detect schema drift
- Safety Checks - Validate migrations before execution
- Dry-Run Mode - Test migrations without executing
- Recovery - Recover from failed migrations
Usage Examples​
Generate Migrations​
import (
"github.com/forgego/forge/db/migrate"
"github.com/forgego/forge/db/migrate/generate"
)
// Create generator
generator := generate.NewGenerator(
"./models", // Models directory
"./migrations", // Migrations directory
migrate.DriverPostgreSQL,
)
// Generate migrations
err := generator.GenerateMigrations("add_user_table")
if err != nil {
log.Fatal(err)
}
Execute Migrations​
import (
"github.com/forgego/forge/db"
"github.com/forgego/forge/db/migrate/execute"
)
// Create executor
executor, err := execute.NewExecutor(db, "./migrations")
if err != nil {
log.Fatal(err)
}
// Apply all pending migrations
err = executor.Migrate(ctx)
if err != nil {
log.Fatal(err)
}
// Rollback last migration
err = executor.Rollback(ctx)
if err != nil {
log.Fatal(err)
}
Check Migration Status​
status, err := executor.Status(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Current version: %d\n", status.Version)
fmt.Printf("Dirty: %v\n", status.Dirty)
fmt.Printf("Pending: %d\n", len(status.Pending))
Verify Migrations​
import "github.com/forgego/forge/db/migrate/verify"
// Check for schema drift
drift, err := verify.DetectDrift(db, "./migrations")
if err != nil {
log.Fatal(err)
}
if len(drift) > 0 {
fmt.Println("Schema drift detected:")
for _, d := range drift {
fmt.Printf(" - %s\n", d)
}
}
Integration Points​
Schema System​
- Migrations generated from schema definitions
- Schema changes detected automatically
- Field types mapped to database types
Code Generation​
- AST parser extracts model definitions
- Model definitions converted to migration state
- Generated code synchronized with migrations
Database Layer​
- Migrations executed through database connection
- Transaction support for safe migrations
- Connection pooling for migration execution
CLI Tools​
forge migrate- Generate and execute migrationsforge migrate status- Check migration statusforge migrate rollback- Rollback migrations
Migration File Format​
Migrations are stored as SQL files:
migrations/
000001_initial.up.sql
000001_initial.down.sql
000002_add_users.up.sql
000002_add_users.down.sql
Up Migration (*.up.sql):
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(150) NOT NULL UNIQUE,
email VARCHAR(254) NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users(email);
Down Migration (*.down.sql):
DROP INDEX IF EXISTS idx_users_email;
DROP TABLE IF EXISTS users;
Best Practices​
- Always Generate Migrations - Never write migrations manually
- Review Generated SQL - Check generated SQL before committing
- Test Migrations - Test migrations in development first
- Use Transactions - All migrations are transactional by default
- Version Control - Commit all migration files
- Rollback Support - Ensure down migrations are reversible
- Avoid Data Loss - Be careful with DROP operations
- Migration Ordering - Dependencies are handled automatically
- Checksums - Verify checksums before applying migrations
- Schema Drift - Regularly check for schema drift
Safety Features​
Transaction Wrapping​
All migrations are wrapped in transactions for safety.
Dirty State Detection​
Detects and prevents execution when database is in dirty state.
Checksum Verification​
Verifies migration file integrity before execution.
Rollback Safety​
Validates rollback operations before executing.
Drift Detection​
Detects differences between database and migration state.
Extension Points​
Custom Change Types​
- Define custom change types
- Custom SQL generation
- Custom validation
Custom Dialects​
- Add support for new databases
- Custom SQL generation
- Database-specific optimizations
Custom Validators​
- Add custom migration validators
- Safety checks
- Business rule validation
Future Enhancements​
- Data migrations (beyond schema)
- Migration squashing UI
- Migration testing framework
- Migration performance analysis
- Multi-database support
- Migration templates
- Migration rollback strategies