Migration¶
Overview¶
Migration is a feature that allows you to evolve your database schema over time, REL provides DSL that allows you to write migration in Golang.
Defining Migration¶
Migration package usually located inside your-repo/db/migrations
package. It's a standalone package that should not be imported by the rest of your application. Each migration file is named as number_name.go
, and each migration file must define a pair of migration and rollback functions: MigrateName
and RollbackName
. Migrate and rollback function name is the camel cased file name without version.
Note
Sample project that demonstrate this setup can be found at go-rel/gin-example
// 20202806225100_create_todos.go
package migrations
import (
"context"
"github.com/go-rel/rel"
)
// MigrateCreateTodos definition
func MigrateCreateTodos(schema *rel.Schema) {
schema.CreateTable("todos", func(t *rel.Table) {
t.ID("id")
t.DateTime("created_at")
t.DateTime("updated_at")
t.String("title")
t.Bool("completed")
t.Int("order")
})
schema.CreateIndex("todos", "order", []string{"order"})
schema.Do(func(ctx context.Context, repo rel.Repository) error {
// add seeds
return repo.Insert(ctx, &Todo{Title: "Do homework"})
})
}
// RollbackCreateTodos definition
func RollbackCreateTodos(schema *rel.Schema) {
schema.DropTable("todos")
}
Running Migration¶
REL provides CLI that can be used to run your migration, it can be installed using homebrew
, go get
or downloaded from release page.
Install using homebrew:
brew tap go-rel/tap
brew install rel
Or, Install using go get:
go get github.com/go-rel/cmd/rel
Since Go 1.18 use go install:
go install github.com/go-rel/cmd/rel@latest
Verify installation:
rel -version
Migrate to the latest version:
rel migrate
Rollback one migration step:
rel rollback
Configuring Database Connection¶
By default, REL will try to use database connection info that available as environment variable.
Variable | Description |
---|---|
DATABASE_URL | Database connection string (Optional) |
DATABASE_ADAPTER | Adapter package (Required if DATABASE_URL specified) |
DATABASE_DRIVER | Driver package (Required if DATABASE_URL specified) |
MYSQL_HOST | MySQL host (Optional) |
MYSQL_PORT | MySQL port (Optional) |
MYSQL_DATABASE | MySQL database (Required, if MYSQL_HOST specified) |
MYSQL_USERNAME | MySQL host (Required, if MYSQL_HOST specified) |
MYSQL_PASSWORD | MySQL host (Optional) |
POSTGRES_HOST | PostgreSQL host (Optional) |
POSTGRES_PORT | PostgreSQL port (Optional) |
POSTGRES_DATABASE | PostgreSQL database (Required, if POSTGRES_HOST specified) |
POSTGRES_USERNAME | PostgreSQL username (Required, if POSTGRES_HOST specified) |
POSTGRES_PASSWORD | PostgreSQL password (Optional) |
SQLITE3_DATABASE | SQLite3 database (Optional) |
Database connection info can also be specified using command line options: dsn
, adapter
and driver
:
rel migrate -adapter=github.com/go-rel/rel/adapter/sqlite3 -driver=github.com/mattn/go-sqlite3 -dsn=:memory:
Migration API¶
If you need more flexibility, migration API can be used to manually execute migrations.
package main
import (
"context"
"github.com/go-rel/doc/examples/db/migrations"
"github.com/go-rel/migration"
"github.com/go-rel/mysql"
"github.com/go-rel/rel"
_ "github.com/go-sql-driver/mysql"
)
func main() {
var (
ctx = context.TODO()
repo = rel.New(mysql.MustOpen("root@(source:3306)/rel_test?charset=utf8&parseTime=True&loc=Local"))
m = migration.New(repo)
)
// Register migrations
m.Register(20202806225100, migrations.MigrateCreateTodos, migrations.RollbackCreateTodos)
// Run migrations
m.Migrate(ctx)
// OR:
// m.Rollback(ctx)
}