migrate

package module
v0.1.7 Latest Latest
Warning

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

Go to latest
Published: Jan 13, 2026 License: Unlicense Imports: 12 Imported by: 1

README

migrate - Generic, Database-Agnostic Schema Migration Package

Go Reference Go Report Card

migrate is a lightweight, zero-dependency package for managing database migrations in Go. It works with any database that has a database/sql driver. See Go SQL Drivers for a list of supported drivers.

Read more on pkg.go.dev

Documentation

Overview

Package migrate provides a generic and database-agnostic schema migration tool.

It works with any SQL (or SQL-like) database that has a database/sql driver. See https://go.dev/wiki/SQLDrivers for a list of supported drivers.

Migrations are versioned, transactional (when supported), and verified using checksums to detect changes in already applied scripts. PostgreSQL and SQLite are supported out of the box, with the ability to extend support for additional dialects.

Example (ApplyEmbedFSMigrations)

Apply migrations embedded in the binary using embed.FS.

package main

import (
	"database/sql"
	"embed"
	"fmt"

	_ "modernc.org/sqlite"

	"github.com/ladzaretti/migrate"
)

var (
	//go:embed testdata/sqlite/migrations
	embedFS embed.FS

	embeddedMigrations = migrate.EmbeddedMigrations{
		FS:   embedFS,
		Path: "testdata/sqlite/migrations",
	}
)

// Apply migrations embedded in the binary using embed.FS.
func main() {
	db, err := sql.Open("sqlite", ":memory:")
	if err != nil {
		fmt.Printf("open: %v", err)
		return
	}
	defer func() { //nolint:wsl // false positive
		_ = db.Close()
	}()

	m := migrate.New(db, migrate.SQLiteDialect{})

	n, err := m.Apply(embeddedMigrations)
	if err != nil {
		fmt.Printf("migration apply: %v", err)
		return
	}

	fmt.Printf("applied migrations: %d", n)
}
Output:
applied migrations: 2
Example (ApplyStringBasedMigrations)

Apply migrations directly from strings without using external files.

package main

import (
	"database/sql"
	"fmt"

	_ "modernc.org/sqlite"

	"github.com/ladzaretti/migrate"
)

var scripts = []string{
	"CREATE TABLE foo (id INTEGER PRIMARY KEY);",
	"CREATE TABLE bar (id INTEGER PRIMARY KEY);",
}

// Apply migrations directly from strings without using external files.
func main() {
	db, err := sql.Open("sqlite", ":memory:")
	if err != nil {
		fmt.Printf("open: %v", err)
		return
	}
	defer func() { //nolint:wsl // false positive
		_ = db.Close()
	}()

	m := migrate.New(db, migrate.SQLiteDialect{})

	n, err := m.Apply(migrate.StringMigrations(scripts))
	if err != nil {
		fmt.Printf("migration apply: %v", err)
		return
	}

	fmt.Printf("applied migrations: %d", n)
}
Output:
applied migrations: 2

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Checksum

type Checksum func(s string) string

Checksum computes a hash value for the given string. It is used to validate and compare migration scripts.

type EmbeddedMigrations

type EmbeddedMigrations struct {
	FS   embed.FS
	Path string
}

EmbeddedMigrations wraps the embed.FS and the path to the migration scripts directory.

func (EmbeddedMigrations) List

func (e EmbeddedMigrations) List() ([]string, error)

List returns a list of migration script queries from the embedded file system.

It reads migration scripts from the directory specified in the [EmbeddedMigrations.Path] field within the embedded file system [EmbeddedMigrations.FS] and returns them as a slice of strings.

This function does not recursively read subdirectories.

Queries are ordered lexicographically rather than naturally. For example, the files "1.sql", "2.sql", and "03.sql" will be read in the order: "03.sql", "1.sql", "2.sql".

To ensure correct ordering, use zero-padding for numbers, e.g., "001.sql", "002.sql", "003.sql".

type Filter

type Filter func(migrationIndex int) bool

Filter is used to filter migrations by their index in the execution order. Return true to apply the migration.

type Lister added in v0.1.2

type Lister interface {
	List() ([]string, error)
}

Lister is an interface that defines a method for listing the contents of the underlying data source.

type Migrator

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

func New

func New(db types.DBTX, dialect types.Dialect, opts ...Opt) *Migrator

New creates a new Migrator with the provided database, dialect, and options.

By default, both transactions and checksum validation are enabled. The checksum validation uses a SHA-1 function that ignores formatting (e.g., whitespaces). These defaults can be customized using the Opt functions.

func (*Migrator) Apply

func (m *Migrator) Apply(from Lister) (int, error)

Apply applies the given migrations in the order they are provided. Only unapplied migrations are applied. That is, if the current schema version is n and n + k scripts are provided, only the additional k will be applied.

To re-apply all migrations, use the WithReapplyAll Opt function.

The initial schema state is considered version 0.

For each schema version, a cumulative checksum is calculated, considering all previously applied migrations. If an already applied migration has changed, validation will fail, and no further migrations will be applied.

It returns the number of migrations applied and any error encountered.

With transactions enabled (default), any error triggers a rollback; otherwise, migrations are applied sequentially until an error occurs or all are applied.

To reset the schema and force re-application of migrations, along with re-generating checksum values, use the following:

opts := []migrate.Opts{
	migrate.WithChecksumValidation(false),
	migrate.WithReapplyAll(true),
}
m := migrate.New(db, s.dialect, opts...)
m.Apply(migrations)

func (*Migrator) ApplyContext

func (m *Migrator) ApplyContext(ctx context.Context, from Lister) (int, error)

func (*Migrator) CurrentSchemaVersion

func (m *Migrator) CurrentSchemaVersion(ctx context.Context) (types.SchemaVersion, error)

type Opt

type Opt func(*Migrator)

func WithChecksum

func WithChecksum(fn Checksum) Opt

WithChecksum sets a custom Checksum function or uses the default if nil.

func WithChecksumValidation

func WithChecksumValidation(enabled bool) Opt

func WithFilter

func WithFilter(fn Filter) Opt

WithFilter is used to set a filtering function to exclude certain scripts from being applied.

Example:

// Skip the 4th migration
skipForth := func(n int) bool { return n != 4 }

m := migrate.New(db, s.dialect, migrate.WithFilter(skipForth))
n, err := m.Apply(migrations)

func WithReapplyAll

func WithReapplyAll(enabled bool) Opt

WithReapplyAll controls whether to reapply existing migrations.

func WithTransaction

func WithTransaction(enabled bool) Opt

type PostgreSQLDialect

type PostgreSQLDialect struct{}

PostgreSQLDialect provides the needed queries for managing schema versioning for an PostgreSQL database.

func (PostgreSQLDialect) CreateVersionTableQuery

func (PostgreSQLDialect) CreateVersionTableQuery() string

func (PostgreSQLDialect) CurrentVersionQuery

func (PostgreSQLDialect) CurrentVersionQuery() string

func (PostgreSQLDialect) SaveVersionQuery

func (PostgreSQLDialect) SaveVersionQuery() string

type SQLiteDialect

type SQLiteDialect struct{}

SQLiteDialect provides the needed queries for managing schema versioning for an SQLite database.

func (SQLiteDialect) CreateVersionTableQuery

func (SQLiteDialect) CreateVersionTableQuery() string

func (SQLiteDialect) CurrentVersionQuery

func (SQLiteDialect) CurrentVersionQuery() string

func (SQLiteDialect) SaveVersionQuery

func (SQLiteDialect) SaveVersionQuery() string

type StringMigrations

type StringMigrations []string

StringMigrations is a slice of plain string migration script queries to be applied.

func (StringMigrations) List

func (s StringMigrations) List() ([]string, error)

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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