sql-migrate icon indicating copy to clipboard operation
sql-migrate copied to clipboard

Migration doesn't apply

Open ok2ju opened this issue 7 years ago • 2 comments

Hi, I'm trying to figure out why my migration doesn't apply. I use bleeding edge version of gorp and postgres driver. To embed the migration files I use bindata. So first of all I run following command:

$ go-bindata -pkg repository -o repository/migrations.go migrations/...
package repository

import (
	"database/sql"

	"github.com/go-gorp/gorp"
	_ "github.com/lib/pq"
	migrate "github.com/rubenv/sql-migrate"
)

func InitStorage(storage string, dsn string) (*gorp.DbMap, error) {
	dbmap := createStorage(storage, dsn)
	migrations := &migrate.AssetMigrationSource{
		Asset:    Asset,
		AssetDir: AssetDir,
		Dir:      "migrations",
	}

	n, err := migrate.Exec(dbmap.Db, "postgres", migrations, migrate.Up)
	if err != nil {
		return nil, err
	}
	fmt.Printf("Applied %d migrations!\n", n)

	return dbmap, nil
}

func createStorage(storage string, dsn string) *gorp.DbMap {
	dialect, driver := dialectAndDriver(storage)
	dbmap := &gorp.DbMap{Db: connect(driver, dsn), Dialect: dialect}
	return dbmap
}

func connect(driver string, dsn string) *sql.DB {
	if dsn == "" {
		panic("DSN is no set.")
	}

	db, err := sql.Open(driver, dsn)
	if err != nil {
		panic("Error connecting to db: " + err.Error())
	}
	return db
}

func dialectAndDriver(storage string) (gorp.Dialect, string) {
	switch storage {
	case "postgres":
		return gorp.PostgresDialect{}, "postgres"
	case "sqlite":
		return gorp.SqliteDialect{}, "sqlite3"
	default:
		return gorp.PostgresDialect{}, "postgres"
	}
}

My migration file looks like: migrations/1_init.sql

-- +migrate UP

CREATE TABLE IF NOT EXISTS "organization" (
  "id" VARCHAR(250) PRIMARY KEY,
  "name" VARCHAR(20) NOT NULL,
  "email" VARCHAR(25) NOT NULL,
  "description" VARCHAR(150),
  "location" VARCHAR(50)
);

-- +migrate Down
DROP TABLE IF EXISTS "organization";

But after running my application, I receive following console output:

Applied 0 migrations!

And my DB is empty, table organization was not created. What am I doing wrong?

ok2ju avatar Apr 02 '18 10:04 ok2ju

@ok2ju try to use packr for you trouble instead of &migrate.AssetMigrationSource. For example:

	migrations := &migrate.PackrMigrationSource{
		Box: packr.NewBox(migrationFolder),
	}

	findedMigrations, err := migrations.FindMigrations()
	if err != nil {
		logger.Error(err.Error())
		return err
	}

	for _, migr := range findedMigrations {
		n, err := migrate.Exec(
			db,
			"postgres",
			migrate.MemoryMigrationSource{Migrations: []*migrate.Migration{migr}},
			migrate.Up,
		)
		if err != nil {
			logger.Error(err.Error())
			return err
		}
		if n != 0 {
			logger.Info(fmt.Sprintf("%s are migrated!", migr.Id))
		} else {
			logger.Info(fmt.Sprintf("%s are not migrated!", migr.Id))
		}
	}

nextel avatar Apr 13 '18 10:04 nextel

I am using sql-migrate + packr for mysql. However

  • can't call migrate.Exec multiple times with for loop. later migrate.Exec always returns n == 0 after first migration. So I use sql-migrate in this way.
func Migrate(db *sql.DB, dialect string) {
	logger := getDbLogger()

	migrationSrc := &migrate.PackrMigrationSource{
		Box: packr.NewBox(SqlSchemaDir),
	}

	migrations, err := migrationSrc.FindMigrations()
	if err != nil {
		logger.Fatalw("Failed to find sql migrations")
	}

	appliedMigrationCount, err := migrate.Exec(
		db,
		dialect,
		migrate.MemoryMigrationSource{Migrations: migrations},
		migrate.Up,
	)

	if err != nil {
		failedMigr := migrations[appliedMigrationCount]

		logger.Warnw("Found sql migration error. Doing rollback...", "down", failedMigr.Down)
		_, downErr := migrate.Exec(
			db,
			dialect,
			migrate.MemoryMigrationSource{Migrations: []*migrate.Migration{failedMigr}},
			migrate.Down,
		)

		if downErr != nil {
			logger.Errorw("Failed to do rollback sql migration", "error", downErr)
		}

		logger.Fatalw("Failed to do sql migration", "error", err)
	}

	totalMigrationCount := len(migrations)
	if appliedMigrationCount != totalMigrationCount {
		logger.Infow("Some migrations are skipped", "total", totalMigrationCount, "applied", appliedMigrationCount)
	}

	for i := 0; i < totalMigrationCount; i++ {
		skipped := true

		if totalMigrationCount-appliedMigrationCount <= i {
			skipped = false
		}

		logger.Infow("Migration File", "filename", migrations[i].Id, "skip", skipped)
	}

	logger.Infow("Finished migration")
}

1ambda avatar Jun 03 '18 10:06 1ambda