Migrations
The migrations plugin can automatically generate and apply migrations to keep your database schema up to date when changes to the model definitions occur.
- cmd/
- sqlbunny/ <- Runs sqlbunny, with your own configuration
- main.go
- migrate/ <- Runs your migrations
- main.go
- app/ <- Runs your application
- main.go
- migrations/ <- Package containing migrations.
- store.go
- migration_00001.go
- models/ <- autogenerated models package
- book.go
- bunny_*.go
Setting up
First, make sure that the migrations plugin is enabled:
Run(
&migration.Plugin{},
...
)
To create the migrations
package, run:
go run ./cmd/sqlbunny/main.go migration gen
The first run will create the package, and the migration store in migrations/store.go
.
Then, add the newly created migration store to the plugin config. This is necessary so the plugin can read the existing migrations, to diff the existing schema with the new one.
Run(
&migration.Plugin{
Store: &migrations.Store,
},
...
)
Generating migrations
To generate a migration, run:
go run ./cmd/sqlbunny/main.go migration gen
Migrations are generated according to the following algorithm:
- Existing migrations are applied to a "virtual" schema. This schema represents the current state of the database.
- The model definitions from the config are compiled into another "virtual" schema. This schema represents the desired final state of the database.
- The two schemas are examined for differences
- The differences are taken into a migration that converts the current schema to the desired schema.
- The migration is written to a Go file.
Generated migration files should be checked into version control (Git, SVN, etc.). They're effectively the history of your models, and keeping it intact ensures any developer or production database is able to be migrated up to the latest changes.
Running migrations
To run the migrations, call Store.Run(ctx)
on your migrations package.
You can do this from your main application, or you can build a third separate binary. Having a separate binary may be useful for development, so you can run migrations even when your main application code is in a state that doesn't compile.
Put this in cmd/migrate/main.go
:
package main
import (
"context"
"database/sql"
"github.com/sqlbunny/sqlbunny/runtime/bunny"
"github.com/sqlbunny/sqlbunny_demo/migrations"
)
func main() {
db, err := sql.Open("postgres", "host=localhost port=5432 dbname=postgres user=postgres password=postgres sslmode=disable")
if err != nil {
panic(err)
}
ctx := context.Background()
ctx = bunny.ContextWithDB(ctx, db)
err = migrations.Store.Run(ctx)
if err != nil {
panic(err)
}
}
The migration store tracks which migrations have been run in the migrations
table. This table is created on the fly, and it's not managed by migrations itself (ie, it's not a model).
When running, it will read which migrations have been applied from the migrations
table, and then apply the missing ones (if any) in order.
Manual migrations
TODO