migrate

package module
v0.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2022 License: MIT Imports: 6 Imported by: 34

README

Migrate

GoDoc Go

A simple database migration tool using an sql.DB connection and fs.FS for the migration source. It has no non-test dependencies.

Made in 🇩🇰 by maragu, maker of online Go courses.

Features

  • Simple: The common usage is a one-liner.
  • Safe: Each migration is run in a transaction, and automatically rolled back on errors.
  • Flexible: Setup a custom migrations table and use callbacks before and after each migration.

Usage

go get -u github.com/maragudk/migrate
package main

import (
	"context"
	"database/sql"
	"os"

	_ "github.com/jackc/pgx/v4/stdlib"
	"github.com/maragudk/migrate"
)

// migrations is a directory with sql files that look something like this:
// migrations/1-accounts.up.sql
// migrations/1-accounts.down.sql
// migrations/2-users.up.sql
// migrations/2-users.down.sql
var migrations = os.DirFS("migrations")

func main() {
	db, err := sql.Open("pgx", "postgresql://postgres:123@localhost:5432/postgres?sslmode=disable")
	if err != nil {
		panic(err)
	}

	if err := migrate.Up(context.Background(), db, migrations); err != nil {
		panic(err)
	}

	if err := migrate.Down(context.Background(), db, migrations); err != nil {
		panic(err)
	}

	if err := migrate.To(context.Background(), db, migrations, "1-accounts"); err != nil {
		panic(err)
	}
}

Documentation

Overview

Package migrate provides simple migration functions Up, Down, and To, as well as a Migrator. Up, Down, and To are one-liner convenience functions that use default Options. If you need custom Options, use New.

Example
package main

import (
	"context"
	"database/sql"
	"os"

	_ "github.com/go-sql-driver/mysql"
	_ "github.com/jackc/pgx/v4/stdlib"
	"github.com/maragudk/migrate"

	_ "github.com/mattn/go-sqlite3"
)

var migrations = os.DirFS("testdata/example")

func main() {
	db, err := sql.Open("sqlite3", "db.sqlite")
	if err != nil {
		panic(err)
	}

	if err := migrate.Up(context.Background(), db, migrations); err != nil {
		panic(err)
	}

	if err := migrate.Down(context.Background(), db, migrations); err != nil {
		panic(err)
	}

	if err := migrate.To(context.Background(), db, migrations, "1"); err != nil {
		panic(err)
	}
}
Output:

Example (Advanced)
package main

import (
	"context"
	"database/sql"
	"os"

	_ "github.com/go-sql-driver/mysql"
	_ "github.com/jackc/pgx/v4/stdlib"
	"github.com/maragudk/migrate"

	_ "github.com/mattn/go-sqlite3"
)

var migrations = os.DirFS("testdata/example")

func main() {
	db, err := sql.Open("sqlite3", "db.sqlite")
	if err != nil {
		panic(err)
	}

	before := func(ctx context.Context, tx *sql.Tx, version string) error {
		// Do whatever you need to before each migration
		return nil
	}

	after := func(ctx context.Context, tx *sql.Tx, version string) error {
		// Do whatever you need to after each migration
		return nil
	}

	m := migrate.New(migrate.Options{
		After:  after,
		Before: before,
		DB:     db,
		FS:     migrations,
		Table:  "migrations2",
	})

	if err := m.MigrateUp(context.Background()); err != nil {
		panic(err)
	}

	if err := m.MigrateDown(context.Background()); err != nil {
		panic(err)
	}

	if err := m.MigrateTo(context.Background(), "1"); err != nil {
		panic(err)
	}
}
Output:

Example (Embed)
package main

import (
	"context"
	"database/sql"
	"embed"
	"io/fs"

	_ "github.com/go-sql-driver/mysql"
	_ "github.com/jackc/pgx/v4/stdlib"
	"github.com/maragudk/migrate"

	_ "github.com/mattn/go-sqlite3"
)

//go:embed testdata/example
var embeddedMigrations embed.FS

func main() {
	db, err := sql.Open("sqlite3", "db.sqlite")
	if err != nil {
		panic(err)
	}

	// Because migrate always reads from the root of the provided file system,
	// use fs.Sub to return the subtree rooted at the provided dir.
	fsys, err := fs.Sub(embeddedMigrations, "testdata/example")
	if err != nil {
		panic(err)
	}

	if err := migrate.Up(context.Background(), db, fsys); err != nil {
		panic(err)
	}

	if err := migrate.Down(context.Background(), db, fsys); err != nil {
		panic(err)
	}

	if err := migrate.To(context.Background(), db, fsys, "1"); err != nil {
		panic(err)
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Down added in v0.3.1

func Down(ctx context.Context, db *sql.DB, fsys fs.FS) error

Down from the current version.

func To added in v0.3.1

func To(ctx context.Context, db *sql.DB, fsys fs.FS, version string) error

To the given version.

func Up added in v0.3.1

func Up(ctx context.Context, db *sql.DB, fsys fs.FS) error

Up from the current version.

Types

type Migrator

type Migrator struct {
	// contains filtered or unexported fields
}

func New

func New(opts Options) *Migrator

New Migrator with Options. If Options.Table is not set, defaults to "migrations". The table name must match ^[\w.]+$ . New panics on illegal options.

func (*Migrator) MigrateDown

func (m *Migrator) MigrateDown(ctx context.Context) (err error)

MigrateDown from the current version.

func (*Migrator) MigrateTo added in v0.3.1

func (m *Migrator) MigrateTo(ctx context.Context, version string) (err error)

func (*Migrator) MigrateUp

func (m *Migrator) MigrateUp(ctx context.Context) (err error)

MigrateUp from the current version.

type Options added in v0.4.0

type Options struct {
	After  callback
	Before callback
	DB     *sql.DB
	FS     fs.FS
	Table  string
}

Options for New. DB and FS are always required.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL