mirror of
https://github.com/therootcompany/golib.git
synced 2026-04-25 05:08:00 +00:00
Index skill (use-sqlmigrate) plus focused skills for CLI usage, Go library integration, and per-database conventions (PostgreSQL, MySQL/MariaDB, SQLite, SQL Server).
3.8 KiB
3.8 KiB
name, description, depends
| name | description | depends | ||
|---|---|---|---|---|
| use-sql-migrate-golang | Embed SQL migrations in Go applications using sqlmigrate library. Use when writing Go code that runs migrations on startup, implements auto-migrate, or uses the Migrator interface. Covers pgmigrate, mymigrate, litemigrate, msmigrate. |
|
Modules
Each backend is a separate Go module. Import only what you need:
| Module | Import path |
|---|---|
| Core | github.com/therootcompany/golib/database/sqlmigrate |
| PostgreSQL | github.com/therootcompany/golib/database/sqlmigrate/pgmigrate |
| MySQL/MariaDB | github.com/therootcompany/golib/database/sqlmigrate/mymigrate |
| SQLite | github.com/therootcompany/golib/database/sqlmigrate/litemigrate |
| SQL Server | github.com/therootcompany/golib/database/sqlmigrate/msmigrate |
Core API
// Collect reads .up.sql/.down.sql pairs from an fs.FS
scripts, err := sqlmigrate.Collect(migrationsFS, "sql/migrations")
// Apply all pending migrations
applied, err := sqlmigrate.Latest(ctx, runner, scripts)
// Apply n pending migrations (-1 = all)
applied, err := sqlmigrate.Up(ctx, runner, scripts, n)
// Roll back n migrations (-1 = all, default pattern: 1)
rolled, err := sqlmigrate.Down(ctx, runner, scripts, n)
// Roll back all migrations
rolled, err := sqlmigrate.Drop(ctx, runner, scripts)
// Check status
status, err := sqlmigrate.GetStatus(ctx, runner, scripts)
// status.Applied, status.Pending
Key types
type Migration struct {
ID string // 8-char hex from INSERT statement
Name string // e.g. "2026-04-05-001000_create-todos"
}
type Script struct {
Migration
Up string // .up.sql content
Down string // .down.sql content
}
type Migrator interface {
ExecUp(ctx context.Context, m Migration, sql string) error
ExecDown(ctx context.Context, m Migration, sql string) error
Applied(ctx context.Context) ([]Migration, error)
}
Embedding migrations
MUST: Use embed.FS to bundle migration files into the binary:
//go:embed sql/migrations/*.sql
var migrationsFS embed.FS
Backend setup pattern
MUST: Backends take a single connection, not a pool.
database/sql backends (MySQL, SQLite, SQL Server)
db, err := sql.Open("mysql", dsn)
// ...
// acquire a dedicated connection for migrations
conn, err := db.Conn(ctx)
// ...
defer func() { _ = conn.Close() }()
runner := mymigrate.New(conn) // or litemigrate.New(conn), msmigrate.New(conn)
pgx backend (PostgreSQL)
// single connection, not pool
conn, err := pgx.Connect(ctx, pgURL)
// ...
defer func() { _ = conn.Close(ctx) }()
runner := pgmigrate.New(conn)
Auto-migrate on startup
Common pattern — run all pending migrations before serving:
func main() {
// ... open db, get conn ...
scripts := mustCollectMigrations()
runner := litemigrate.New(conn)
// apply all pending (idempotent)
if _, err := sqlmigrate.Latest(ctx, runner, scripts); err != nil {
log.Fatalf("auto-migrate: %v", err)
}
// close migration conn, use db/pool for app queries
_ = conn.Close()
// ... start serving ...
}
Example app structure
my-app/
main.go # flag parsing, DB setup, auto-migrate, dispatch
demo.go # app-specific CRUD (uses *sql.DB for queries)
go.mod
sql/
migrations/
0001-01-01-001000_init-migrations.up.sql
0001-01-01-001000_init-migrations.down.sql
2026-04-05-001000_create-todos.up.sql
2026-04-05-001000_create-todos.down.sql
Migrate subcommand pattern
Expose migrate up/down/status/reset as a subcommand:
case "migrate":
err = runMigrate(ctx, runner, migrations, subArgs)
case "add":
autoMigrate(ctx, runner, migrations)
err = runAdd(ctx, db, subArgs)
See example apps in cmd/sql-migrate/examples/ for full implementations.