Laravel-inspired database migrations for Go
Get running in 60 seconds
Chain methods elegantly with a Laravel-inspired syntax that feels natural and readable.
PostgreSQL, MySQL, and SQLite support using standard database/sql package.
Full rollback functionality with batch tracking for safe schema changes.
Simple configuration with .env files - no complex connection strings needed.
Full foreign key support with cascading actions and relationship management.
Leverage Go's type system for compile-time safety and excellent IDE support.
No setup required! Automatically creates migration runner on first use.
Automatically formats migration names with create_ prefix and _table suffix.
Automatically handles MySQL reserved keywords like limit, order, and type.
Populate your database with test data using structs or maps with automatic snake_case conversion.
Modify existing column types and properties with the Change() modifier for evolving schemas.
Clean, expressive syntax for defining your schema
package migrations
import "github.com/ichtrojan/olympian"
func init() {
olympian.RegisterMigration(olympian.Migration{
Name: "create_users_table",
Up: func() error {
return olympian.Table("users").Create(func() {
olympian.Uuid("id").Primary()
olympian.String("email").Unique()
olympian.String("password")
olympian.Boolean("verified").Default(false)
olympian.Timestamps()
})
},
Down: func() error {
return olympian.Table("users").Drop()
},
})
}
olympian.Table("posts").Create(func() {
olympian.Uuid("id").Primary()
olympian.String("user_id")
olympian.String("title")
olympian.Text("content")
olympian.Foreign("user_id").
References("id").
On("users").
OnDelete("cascade")
olympian.Timestamps()
})
Define foreign keys directly on the column definition:
olympian.Uuid("user_id").
References("id").
On("users").
OnDelete("cascade")
Ensure uniqueness across multiple columns:
olympian.Table("subscriptions").Create(func() {
olympian.Uuid("id").Primary()
olympian.Uuid("user_id")
olympian.Uuid("plan_id")
// User can only subscribe to each plan once
olympian.Unique("user_id", "plan_id")
// With custom constraint name
olympian.Unique("user_id", "plan_id").Name("unique_user_plan")
})
olympian.Table("users").Modify(func() {
olympian.Text("bio").Nullable()
olympian.String("avatar").Nullable()
olympian.Integer("age").After("name")
})
Use the Change() modifier to alter existing column types or properties.
olympian.Table("invoices").Modify(func() {
// Change from Enum to String
olympian.String("currency").Default("GBP").Change()
// Make a column nullable
olympian.Text("notes").Nullable().Change()
// Change column type
olympian.BigInteger("amount").Change()
})
Note: MySQL uses MODIFY COLUMN, PostgreSQL uses ALTER COLUMN. SQLite does not support column modifications.
For complex queries or database-specific operations, access the underlying connection:
db, dialect := olympian.GetDB()
// Run any raw SQL
_, err := db.Exec("CREATE EXTENSION IF NOT EXISTS postgis")
// Use in migrations
{
Name: "add_postgis_extension",
Up: func() error {
db, _ := olympian.GetDB()
_, err := db.Exec("CREATE EXTENSION IF NOT EXISTS postgis")
return err
},
Down: func() error {
db, _ := olympian.GetDB()
_, err := db.Exec("DROP EXTENSION IF EXISTS postgis")
return err
},
}
Powerful command-line interface for managing migrations
Run all pending migrations
Create a new migration file with smart naming (automatically adds create_ and _table)
Rollback the last batch of migrations
Show migration status
Rich set of column types for any schema
UUID primary keys
VARCHAR(255)
Long text content
Small integers (TINYINT)
Integer numbers
Large integers (BIGINT)
Auto-increment INT PK
Auto-increment BIGINT PK
True/false values
Date and time
JSON/JSONB data
Precise decimals
olympian.String("email").Nullable()
olympian.Uuid("id").Primary()
olympian.String("username").Unique()
olympian.Boolean("active").Default(true)
olympian.Integer("age").After("name")
olympian.Integer("id").AutoIncrement()
olympian.String("status").Change() // Modify existing column
olympian.String("email").Index() // Add index (auto-named)
olympian.String("slug").IndexWithName("idx") // Add index with custom name
Populate your database with test or initial data
Field names are automatically converted to snake_case. time.Time is converted to timestamp format. Pass a slice for multiple records.
type User struct {
ID string
Name string
UserAge int // becomes user_age
CreatedAt time.Time // converted to timestamp
}
olympian.Seed("users", []User{
{ID: "1", Name: "John", UserAge: 25, CreatedAt: time.Now()},
{ID: "2", Name: "Jane", UserAge: 30, CreatedAt: time.Now()},
})
olympian.Seed("users",
map[string]interface{}{
"id": "uuid-1",
"name": "John Doe",
"email": "john@example.com",
},
)
package seeders
import "github.com/ichtrojan/olympian"
func init() {
olympian.RegisterSeeder(olympian.Seeder{
Name: "user",
Run: func() error {
return olympian.Seed("users",
map[string]interface{}{
"id": "uuid-here",
"name": "John Doe",
},
)
},
})
}
Olympian brings the elegance of Laravel's migration system to Go. If you've ever wished for a more expressive way to manage database schemas in Go, Olympian is your answer.