diff --git a/migration_sql.go b/migration_sql.go index d27554e..4db0514 100644 --- a/migration_sql.go +++ b/migration_sql.go @@ -3,6 +3,7 @@ package goose import ( "database/sql" "regexp" + "time" "github.com/pkg/errors" ) @@ -28,7 +29,7 @@ func runSQLMigration(db *sql.DB, statements []string, useTx bool, v int64, direc for _, query := range statements { verboseInfo("Executing statement: %s\n", clearStatement(query)) - if _, err = tx.Exec(query); err != nil { + if err = execQuery(tx.Exec, query); err != nil { verboseInfo("Rollback transaction") tx.Rollback() return errors.Wrapf(err, "failed to execute SQL query %q", clearStatement(query)) @@ -37,13 +38,13 @@ func runSQLMigration(db *sql.DB, statements []string, useTx bool, v int64, direc if !noVersioning { if direction { - if _, err := tx.Exec(GetDialect().insertVersionSQL(), v, direction); err != nil { + if err := execQuery(tx.Exec, GetDialect().insertVersionSQL(), v, direction); err != nil { verboseInfo("Rollback transaction") tx.Rollback() return errors.Wrap(err, "failed to insert new goose version") } } else { - if _, err := tx.Exec(GetDialect().deleteVersionSQL(), v); err != nil { + if err := execQuery(tx.Exec, GetDialect().deleteVersionSQL(), v); err != nil { verboseInfo("Rollback transaction") tx.Rollback() return errors.Wrap(err, "failed to delete goose version") @@ -62,17 +63,17 @@ func runSQLMigration(db *sql.DB, statements []string, useTx bool, v int64, direc // NO TRANSACTION. for _, query := range statements { verboseInfo("Executing statement: %s", clearStatement(query)) - if _, err := db.Exec(query); err != nil { + if err := execQuery(db.Exec, query); err != nil { return errors.Wrapf(err, "failed to execute SQL query %q", clearStatement(query)) } } if !noVersioning { if direction { - if _, err := db.Exec(GetDialect().insertVersionSQL(), v, direction); err != nil { + if err := execQuery(db.Exec, GetDialect().insertVersionSQL(), v, direction); err != nil { return errors.Wrap(err, "failed to insert new goose version") } } else { - if _, err := db.Exec(GetDialect().deleteVersionSQL(), v); err != nil { + if err := execQuery(db.Exec, GetDialect().deleteVersionSQL(), v); err != nil { return errors.Wrap(err, "failed to delete goose version") } } @@ -81,6 +82,31 @@ func runSQLMigration(db *sql.DB, statements []string, useTx bool, v int64, direc return nil } +func execQuery(fn func(string, ...interface{}) (sql.Result, error), query string, args ...interface{}) error { + if !verbose { + _, err := fn(query, args...) + return err + } + + ch := make(chan error) + + go func() { + _, err := fn(query, args...) + ch <- err + }() + + t := time.Now() + + for { + select { + case err := <-ch: + return err + case <-time.Tick(time.Minute): + verboseInfo("Executing statement still in progress for %v", time.Since(t).Round(time.Second)) + } + } +} + const ( grayColor = "\033[90m" resetColor = "\033[00m"