Add schema.update method for intelligent schema migration
This PR adds a new update method to schema(...) objects that intelligently compares the current schema definition with the database state and applies necessary changes to make them match.
Problem
Previously, there was no way to automatically update database schemas when model definitions changed. Users had to manually manage schema migrations or recreate tables entirely:
schema(Account, Transaction).create; # Works first time
# After changing model definitions, no easy way to update the database
Solution
Added a new update method to Red::Schema that provides intelligent schema migration:
schema(Account, Transaction).update; # Compares schema with DB and applies changes
schema(Account, Transaction).update; # Idempotent - safe to run multiple times
The method can also be chained like other schema methods:
schema(Account, Transaction).create.update; # Method chaining supported
Implementation
The implementation leverages Red's existing schema comparison infrastructure:
-
Added
Red::Schema.updatemethod that compares model definitions with database state usingdiff-from-db -
Uses existing
diff-to-astinfrastructure to convert differences into executable AST nodes - Executes changes in proper order to handle dependencies and constraints
- Runs in a transaction to ensure atomicity of schema changes
- Preserves existing data during schema updates
The solution reuses Red's robust schema reading and migration mechanisms, ensuring consistency with existing patterns.
Key Features
- Intelligent Comparison: Automatically detects differences between model definitions and database schema
- Idempotent: Safe to run multiple times - only applies necessary changes
- Data Preservation: Existing data is preserved during schema updates
- Transaction Safety: All changes are wrapped in a transaction
- Method Chaining: Returns schema object to allow method chaining
- Comprehensive: Handles missing tables, column changes, constraints, and relationships
Testing
Added comprehensive tests covering:
- Basic update functionality with single and multiple tables
- Missing table creation during updates
- Idempotent behavior (multiple updates are safe)
- Data preservation during schema changes
- Method chaining capabilities
- Complex schemas with foreign key relationships
All existing tests continue to pass, ensuring no breaking changes.
Usage Example
use Red;
use Red::Schema;
# Define your models
model User {
has Int $.id is serial;
has Str $.name is column;
}
# Create schema
my $schema = schema(User);
$schema.create;
# Later, after modifying your model definitions...
# Just call update to apply changes automatically
$schema.update;
Fixes #482.
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.