migrate

package module
v0.1.5 Latest Latest
Warning

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

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 7 Imported by: 0

README

go-sql-migrate

Retired. This module is no longer maintained and will not get fixes. For PostgreSQL, use go-pgx-kit. There is no Go replacement here for its MySQL and SQLite support.

A lightweight, reflection-based SQL schema migration library for Go. Supports PostgreSQL, MySQL, and SQLite.

Installation

go get codeberg.org/obadness/go-sql-migrate

Dependencies

This module uses sqlx for database interaction. A *sqlx.DB instance is required to use Migrate and GenerateSchemaDiffs.

go get github.com/jmoiron/sqlx

You will also need a driver for your database:

# PostgreSQL
go get github.com/jackc/pgx/v5/stdlib

# MySQL
go get github.com/go-sql-driver/mysql

# SQLite
go get github.com/mattn/go-sqlite3

Register the driver with sqlx before passing the *sqlx.DB to this module:

// PostgreSQL example
import (
    "github.com/jmoiron/sqlx"
    _ "github.com/jackc/pgx/v5/stdlib"
)

db, err := sqlx.Open("pgx", "postgres://user:pass@localhost:5432/mydb")
if err != nil {
    log.Fatal(err)
}

Usage

Define a schema

Implement the Schema interface by adding a TableName() method to your struct, then annotate fields with struct tags:

type User struct {
    ID        uuid.UUID `db:"id"        sql:"UUID"         primary:"true"`
    Email     string    `db:"email"     unique:"true"`
    Name      string    `db:"name"`
    Active    bool      `db:"active"    default:"true"`
    CreatedAt time.Time `db:"created_at"`
}

func (u User) TableName() string { return "users" }
Run a migration
import migrate "codeberg.org/obadness/go-sql-migrate"

schemas := []migrate.Schema{
    User{},
}

err := migrate.Migrate(ctx, db, migrate.ActionCreate, migrate.PostgreSQL, schemas)
if err != nil {
    log.Fatal(err)
}

Pass multiple schemas in one call:

schemas := []migrate.Schema{
    User{},
    Post{},
    Comment{},
}

err := migrate.Migrate(ctx, db, migrate.ActionCreate, migrate.PostgreSQL, schemas)
if err != nil {
    log.Fatal(err)
}

Actions

Action Constant Description
Create migrate.ActionCreate Runs CREATE TABLE IF NOT EXISTS
Drop migrate.ActionDrop Runs DROP TABLE IF EXISTS
Alter migrate.ActionAlter Adds missing columns and updates changed column types

Use the constants directly or construct an Action from a string using NewAction — useful when the action comes from a CLI flag, environment variable, or config file:

// From a constant
action := migrate.ActionCreate

// From a string (e.g. CLI flag or env var)
action := migrate.NewAction(os.Getenv("MIGRATE_ACTION"))

err := migrate.Migrate(ctx, db, action, migrate.PostgreSQL, schemas)
if err != nil {
    log.Fatal(err)
}

An unrecognised value returns an empty Action which fails validation inside Migrate with a clear error — no silent no-ops.

Dialects

Dialect Constant
PostgreSQL migrate.PostgreSQL
MySQL migrate.MySQL
SQLite migrate.SQLite

Struct tags

Tag Description Example
db Column name. Omit or set to - to skip the field db:"email"
sql Override the SQL type sql:"VARCHAR(100)"
primary Mark as primary key primary:"true"
unique Add UNIQUE constraint unique:"true"
nullable Allow NULL values nullable:"true"
default Set a DEFAULT value default:"true"
fk Add a FOREIGN KEY reference fk:"other_table(id)"

Go to SQL type mapping

Go type PostgreSQL MySQL SQLite
string VARCHAR(255) VARCHAR(255) TEXT
int, int32 INTEGER INTEGER INTEGER
int64 INTEGER BIGINT INTEGER
float32, float64 NUMERIC NUMERIC NUMERIC
bool BOOLEAN TINYINT(1) BOOLEAN
time.Time TIMESTAMPTZ DATETIME DATETIME
uuid.UUID UUID CHAR(36) TEXT
json.RawMessage JSONB JSON TEXT

Override any mapping with the sql tag.

Alter behaviour

ActionAlter compares your struct definition against the live table and generates statements for:

  • Columns present in the struct but missing from the table → ADD COLUMN
  • Columns where the Go-mapped type differs from the actual column type → ALTER COLUMN ... TYPE

Columns present in the table but absent from the struct are left untouched.

Note: ALTER COLUMN ... TYPE can fail if existing data is incompatible with the new type. Review generated statements before running against production data.

Generating SQL without executing

Use the underlying functions directly to inspect generated SQL before running it:

// Create
sql, err := migrate.GenerateCreateTableSQL(User{}, migrate.PostgreSQL)

// Alter / diff
stmts, err := migrate.GenerateSchemaDiffs(db, User{}, migrate.PostgreSQL)
for _, s := range stmts {
    fmt.Println(s)
}

// Drop
sql := migrate.DropTableSQL(User{})

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DropConstraintSQL

func DropConstraintSQL(tableName, constraintName string, dialect SQLDialect) string

func DropIndexSQL

func DropIndexSQL(tableName, column string, dialect SQLDialect) string

func DropTableSQL

func DropTableSQL(schema Schema) string

func GenerateCreateTableSQL

func GenerateCreateTableSQL(schema Schema, dialect SQLDialect) (string, error)

func GenerateSchemaDiffs

func GenerateSchemaDiffs(db *sqlx.DB, schema any, dialect SQLDialect) ([]string, error)

func GetTableColumns

func GetTableColumns(db *sqlx.DB, tableName string, dialect SQLDialect) (map[string]string, error)

func Map

func Map(t reflect.Type, dialect SQLDialect) string

func Migrate

func Migrate(ctx context.Context, db *sqlx.DB, action Action, dialect SQLDialect, schemas []Schema) error

Types

type Action

type Action string
const (
	ActionCreate Action = "create"
	ActionDrop   Action = "drop"
	ActionAlter  Action = "alter"
)

func NewAction

func NewAction(value string) Action

func (Action) Validate

func (a Action) Validate() error

type ColumnInfo

type ColumnInfo struct {
	Name string `db:"name"`
	Type string `db:"type"`
	// SQLite-only fields — nil for Postgres/MySQL
	Cid       *int            `db:"cid"`
	NotNull   *int            `db:"notnull"`
	DfltValue *sql.NullString `db:"dflt_value"`
	Pk        *int            `db:"pk"`
}

type SQLDialect

type SQLDialect string
const (
	PostgreSQL SQLDialect = "postgres"
	MySQL      SQLDialect = "mysql"
	SQLite     SQLDialect = "sqlite"
)

func (SQLDialect) Validate

func (d SQLDialect) Validate() error

type Schema

type Schema interface {
	TableName() string
}

Jump to

Keyboard shortcuts

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