func Queries(queries []string) func(*sql.Tx) error {
	return func(tx *sql.Tx) error {
		for _, query := range queries {
			if _, err := tx.Exec(query); err != nil {
				return err
			}
		}
		return nil
	}
}
Queries returns a func(tx *sql.Tx) error function that performs the given sql
queries in multiple Exec calls.
package migrate
import (
	"database/sql"
	"fmt"
	"hash/crc32"
	"sort"
	"sync"
)
type MigrationDirection int
const (
	Up MigrationDirection = iota
	Down
)
type TransactionMode int
const (
	IndividualTransactions TransactionMode = iota
	SingleTransaction
)
type MigrationError struct {
	Migration
	Err error
}
func (e *MigrationError) Error() string {
	return fmt.Sprintf("migration %d failed: %v", e.ID, e.Err)
}
const DefaultTable = "schema_migrations"
type Migration struct {
	ID int
	Up func(tx *sql.Tx) error
	Down func(tx *sql.Tx) error
}
type ByID []Migration
func (m ByID) Len() int           { return len(m) }
func (m ByID) Less(i, j int) bool { return m[i].ID < m[j].ID }
func (m ByID) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
type Migrator struct {
	Table string
	sync.Locker
	TransactionMode TransactionMode
	db *sql.DB
}
type postgresLocker struct {
	key uint32
	db  *sql.DB
}
func newPostgresLocker(db *sql.DB) sync.Locker {
	key := crc32.ChecksumIEEE([]byte("migrations"))
	return &postgresLocker{
		key: key,
		db:  db,
	}
}
func (l *postgresLocker) Lock() {
	l.do("lock")
}
func (l *postgresLocker) Unlock() {
	l.do("unlock")
}
func (l *postgresLocker) do(m string) {
	_, err := l.db.Exec(fmt.Sprintf("SELECT pg_advisory_%s(%d)", m, l.key))
	if err != nil {
		panic(fmt.Sprintf("migrate: %v", err))
	}
}
func NewMigrator(db *sql.DB) *Migrator {
	return &Migrator{
		db:     db,
		Locker: new(sync.Mutex),
	}
}
func NewPostgresMigrator(db *sql.DB) *Migrator {
	m := NewMigrator(db)
	m.Locker = newPostgresLocker(db)
	return m
}
func (m *Migrator) Exec(dir MigrationDirection, migrations ...Migration) error {
	m.Lock()
	defer m.Unlock()
	_, err := m.db.Exec(fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (version integer primary key not null)", m.table()))
	if err != nil {
		return err
	}
	var tx *sql.Tx
	if m.TransactionMode == SingleTransaction {
		tx, err = m.db.Begin()
		if err != nil {
			return err
		}
	}
	for _, migration := range sortMigrations(dir, migrations) {
		if m.TransactionMode == IndividualTransactions {
			tx, err = m.db.Begin()
			if err != nil {
				return err
			}
		}
		if err := m.runMigration(tx, dir, migration); err != nil {
			tx.Rollback()
			return err
		}
		if m.TransactionMode == IndividualTransactions {
			if err := tx.Commit(); err != nil {
				return err
			}
		}
	}
	if m.TransactionMode == SingleTransaction {
		if err := tx.Commit(); err != nil {
			return err
		}
	}
	return nil
}
func (m *Migrator) runMigration(tx *sql.Tx, dir MigrationDirection, migration Migration) error {
	shouldMigrate, err := m.shouldMigrate(tx, migration.ID, dir)
	if err != nil {
		return err
	}
	if !shouldMigrate {
		return nil
	}
	var migrate func(tx *sql.Tx) error
	switch dir {
	case Up:
		migrate = migration.Up
	default:
		migrate = migration.Down
	}
	if err := migrate(tx); err != nil {
		return &MigrationError{Migration: migration, Err: err}
	}
	var query string
	switch dir {
	case Up:
		query = fmt.Sprintf("INSERT INTO %s (version) VALUES (%d)", m.table(), migration.ID)
	default:
		query = fmt.Sprintf("DELETE FROM %s WHERE version = %d", m.table(), migration.ID)
	}
	_, err = tx.Exec(query)
	return err
}
func (m *Migrator) shouldMigrate(tx *sql.Tx, id int, dir MigrationDirection) (bool, error) {
	var _id int
	err := tx.QueryRow(fmt.Sprintf("SELECT version FROM %s WHERE version = %d", m.table(), id)).Scan(&_id)
	if err != nil && err != sql.ErrNoRows {
		return false, err
	}
	switch dir {
	case Up:
		return err == sql.ErrNoRows, nil
	default:
		return err != sql.ErrNoRows, nil
	}
}
func (m *Migrator) table() string {
	if m.Table == "" {
		return DefaultTable
	}
	return m.Table
}
func Exec(db *sql.DB, dir MigrationDirection, migrations ...Migration) error {
	return NewMigrator(db).Exec(dir, migrations...)
}