github.com/mrqzzz/migrate@v5.1.7+incompatible/migrate.go (about)

     1  // Package migrate reads migrations from sources and runs them against databases.
     2  // Sources are defined by the `source.Driver` and databases by the `database.Driver`
     3  // interface. The driver interfaces are kept "dump", all migration logic is kept
     4  // in this package.
     5  package migrate
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"os"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/golang-migrate/migrate/v4/database"
    15  	"github.com/golang-migrate/migrate/v4/source"
    16  )
    17  
    18  // DefaultPrefetchMigrations sets the number of migrations to pre-read
    19  // from the source. This is helpful if the source is remote, but has little
    20  // effect for a local source (i.e. file system).
    21  // Please note that this setting has a major impact on the memory usage,
    22  // since each pre-read migration is buffered in memory. See DefaultBufferSize.
    23  var DefaultPrefetchMigrations = uint(10)
    24  
    25  // DefaultLockTimeout sets the max time a database driver has to acquire a lock.
    26  var DefaultLockTimeout = 15 * time.Second
    27  
    28  var (
    29  	ErrNoChange       = errors.New("no change")
    30  	ErrNilVersion     = errors.New("no migration")
    31  	ErrInvalidVersion = errors.New("version must be >= -1")
    32  	ErrLocked         = errors.New("database locked")
    33  	ErrLockTimeout    = errors.New("timeout: can't acquire database lock")
    34  )
    35  
    36  // ErrShortLimit is an error returned when not enough migrations
    37  // can be returned by a source for a given limit.
    38  type ErrShortLimit struct {
    39  	Short uint
    40  }
    41  
    42  // Error implements the error interface.
    43  func (e ErrShortLimit) Error() string {
    44  	return fmt.Sprintf("limit %v short", e.Short)
    45  }
    46  
    47  type ErrDirty struct {
    48  	Version int
    49  }
    50  
    51  func (e ErrDirty) Error() string {
    52  	return fmt.Sprintf("Dirty database version %v. Fix and force version.", e.Version)
    53  }
    54  
    55  type Migrate struct {
    56  	sourceName   string
    57  	sourceDrv    source.Driver
    58  	databaseName string
    59  	databaseDrv  database.Driver
    60  
    61  	// Log accepts a Logger interface
    62  	Log Logger
    63  
    64  	// GracefulStop accepts `true` and will stop executing migrations
    65  	// as soon as possible at a safe break point, so that the database
    66  	// is not corrupted.
    67  	GracefulStop   chan bool
    68  	isGracefulStop bool
    69  
    70  	isLockedMu *sync.Mutex
    71  	isLocked   bool
    72  
    73  	// PrefetchMigrations defaults to DefaultPrefetchMigrations,
    74  	// but can be set per Migrate instance.
    75  	PrefetchMigrations uint
    76  
    77  	// LockTimeout defaults to DefaultLockTimeout,
    78  	// but can be set per Migrate instance.
    79  	LockTimeout time.Duration
    80  }
    81  
    82  // New returns a new Migrate instance from a source URL and a database URL.
    83  // The URL scheme is defined by each driver.
    84  func New(sourceUrl, databaseUrl string) (*Migrate, error) {
    85  	m := newCommon()
    86  
    87  	sourceName, err := sourceSchemeFromUrl(sourceUrl)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	m.sourceName = sourceName
    92  
    93  	databaseName, err := databaseSchemeFromUrl(databaseUrl)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  	m.databaseName = databaseName
    98  
    99  	sourceDrv, err := source.Open(sourceUrl)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	m.sourceDrv = sourceDrv
   104  
   105  	databaseDrv, err := database.Open(databaseUrl)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	m.databaseDrv = databaseDrv
   110  
   111  	return m, nil
   112  }
   113  
   114  // NewWithDatabaseInstance returns a new Migrate instance from a source URL
   115  // and an existing database instance. The source URL scheme is defined by each driver.
   116  // Use any string that can serve as an identifier during logging as databaseName.
   117  // You are responsible for closing the underlying database client if necessary.
   118  func NewWithDatabaseInstance(sourceUrl string, databaseName string, databaseInstance database.Driver) (*Migrate, error) {
   119  	m := newCommon()
   120  
   121  	sourceName, err := schemeFromUrl(sourceUrl)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  	m.sourceName = sourceName
   126  
   127  	m.databaseName = databaseName
   128  
   129  	sourceDrv, err := source.Open(sourceUrl)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  	m.sourceDrv = sourceDrv
   134  
   135  	m.databaseDrv = databaseInstance
   136  
   137  	return m, nil
   138  }
   139  
   140  // NewWithSourceInstance returns a new Migrate instance from an existing source instance
   141  // and a database URL. The database URL scheme is defined by each driver.
   142  // Use any string that can serve as an identifier during logging as sourceName.
   143  // You are responsible for closing the underlying source client if necessary.
   144  func NewWithSourceInstance(sourceName string, sourceInstance source.Driver, databaseUrl string) (*Migrate, error) {
   145  	m := newCommon()
   146  
   147  	databaseName, err := schemeFromUrl(databaseUrl)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  	m.databaseName = databaseName
   152  
   153  	m.sourceName = sourceName
   154  
   155  	databaseDrv, err := database.Open(databaseUrl)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	m.databaseDrv = databaseDrv
   160  
   161  	m.sourceDrv = sourceInstance
   162  
   163  	return m, nil
   164  }
   165  
   166  // NewWithInstance returns a new Migrate instance from an existing source and
   167  // database instance. Use any string that can serve as an identifier during logging
   168  // as sourceName and databaseName. You are responsible for closing down
   169  // the underlying source and database client if necessary.
   170  func NewWithInstance(sourceName string, sourceInstance source.Driver, databaseName string, databaseInstance database.Driver) (*Migrate, error) {
   171  	m := newCommon()
   172  
   173  	m.sourceName = sourceName
   174  	m.databaseName = databaseName
   175  
   176  	m.sourceDrv = sourceInstance
   177  	m.databaseDrv = databaseInstance
   178  
   179  	return m, nil
   180  }
   181  
   182  func newCommon() *Migrate {
   183  	return &Migrate{
   184  		GracefulStop:       make(chan bool, 1),
   185  		PrefetchMigrations: DefaultPrefetchMigrations,
   186  		LockTimeout:        DefaultLockTimeout,
   187  		isLockedMu:         &sync.Mutex{},
   188  	}
   189  }
   190  
   191  // Close closes the source and the database.
   192  func (m *Migrate) Close() (source error, database error) {
   193  	databaseSrvClose := make(chan error)
   194  	sourceSrvClose := make(chan error)
   195  
   196  	m.logVerbosePrintf("Closing source and database\n")
   197  
   198  	go func() {
   199  		databaseSrvClose <- m.databaseDrv.Close()
   200  	}()
   201  
   202  	go func() {
   203  		sourceSrvClose <- m.sourceDrv.Close()
   204  	}()
   205  
   206  	return <-sourceSrvClose, <-databaseSrvClose
   207  }
   208  
   209  // Migrate looks at the currently active migration version,
   210  // then migrates either up or down to the specified version.
   211  func (m *Migrate) Migrate(version uint) error {
   212  	if err := m.lock(); err != nil {
   213  		return err
   214  	}
   215  
   216  	curVersion, dirty, err := m.databaseDrv.Version()
   217  	if err != nil {
   218  		return m.unlockErr(err)
   219  	}
   220  
   221  	if dirty {
   222  		return m.unlockErr(ErrDirty{curVersion})
   223  	}
   224  
   225  	ret := make(chan interface{}, m.PrefetchMigrations)
   226  	go m.read(curVersion, int(version), ret)
   227  
   228  	return m.unlockErr(m.runMigrations(ret))
   229  }
   230  
   231  // Steps looks at the currently active migration version.
   232  // It will migrate up if n > 0, and down if n < 0.
   233  func (m *Migrate) Steps(n int) error {
   234  	if n == 0 {
   235  		return ErrNoChange
   236  	}
   237  
   238  	if err := m.lock(); err != nil {
   239  		return err
   240  	}
   241  
   242  	curVersion, dirty, err := m.databaseDrv.Version()
   243  	if err != nil {
   244  		return m.unlockErr(err)
   245  	}
   246  
   247  	if dirty {
   248  		return m.unlockErr(ErrDirty{curVersion})
   249  	}
   250  
   251  	ret := make(chan interface{}, m.PrefetchMigrations)
   252  
   253  	if n > 0 {
   254  		go m.readUp(curVersion, n, ret)
   255  	} else {
   256  		go m.readDown(curVersion, -n, ret)
   257  	}
   258  
   259  	return m.unlockErr(m.runMigrations(ret))
   260  }
   261  
   262  // Up looks at the currently active migration version
   263  // and will migrate all the way up (applying all up migrations).
   264  func (m *Migrate) Up() error {
   265  	if err := m.lock(); err != nil {
   266  		return err
   267  	}
   268  
   269  	curVersion, dirty, err := m.databaseDrv.Version()
   270  	if err != nil {
   271  		return m.unlockErr(err)
   272  	}
   273  
   274  	if dirty {
   275  		return m.unlockErr(ErrDirty{curVersion})
   276  	}
   277  
   278  	ret := make(chan interface{}, m.PrefetchMigrations)
   279  
   280  	go m.readUp(curVersion, -1, ret)
   281  	return m.unlockErr(m.runMigrations(ret))
   282  }
   283  
   284  // Down looks at the currently active migration version
   285  // and will migrate all the way down (applying all down migrations).
   286  func (m *Migrate) Down() error {
   287  	if err := m.lock(); err != nil {
   288  		return err
   289  	}
   290  
   291  	curVersion, dirty, err := m.databaseDrv.Version()
   292  	if err != nil {
   293  		return m.unlockErr(err)
   294  	}
   295  
   296  	if dirty {
   297  		return m.unlockErr(ErrDirty{curVersion})
   298  	}
   299  
   300  	ret := make(chan interface{}, m.PrefetchMigrations)
   301  	go m.readDown(curVersion, -1, ret)
   302  	return m.unlockErr(m.runMigrations(ret))
   303  }
   304  
   305  // Drop deletes everything in the database.
   306  func (m *Migrate) Drop() error {
   307  	if err := m.lock(); err != nil {
   308  		return err
   309  	}
   310  	if err := m.databaseDrv.Drop(); err != nil {
   311  		return m.unlockErr(err)
   312  	}
   313  	return m.unlock()
   314  }
   315  
   316  // Run runs any migration provided by you against the database.
   317  // It does not check any currently active version in database.
   318  // Usually you don't need this function at all. Use Migrate,
   319  // Steps, Up or Down instead.
   320  func (m *Migrate) Run(migration ...*Migration) error {
   321  	if len(migration) == 0 {
   322  		return ErrNoChange
   323  	}
   324  
   325  	if err := m.lock(); err != nil {
   326  		return err
   327  	}
   328  
   329  	curVersion, dirty, err := m.databaseDrv.Version()
   330  	if err != nil {
   331  		return m.unlockErr(err)
   332  	}
   333  
   334  	if dirty {
   335  		return m.unlockErr(ErrDirty{curVersion})
   336  	}
   337  
   338  	ret := make(chan interface{}, m.PrefetchMigrations)
   339  
   340  	go func() {
   341  		defer close(ret)
   342  		for _, migr := range migration {
   343  			if m.PrefetchMigrations > 0 && migr.Body != nil {
   344  				m.logVerbosePrintf("Start buffering %v\n", migr.LogString())
   345  			} else {
   346  				m.logVerbosePrintf("Scheduled %v\n", migr.LogString())
   347  			}
   348  
   349  			ret <- migr
   350  			go migr.Buffer()
   351  		}
   352  	}()
   353  
   354  	return m.unlockErr(m.runMigrations(ret))
   355  }
   356  
   357  // Force sets a migration version.
   358  // It does not check any currently active version in database.
   359  // It resets the dirty state to false.
   360  func (m *Migrate) Force(version int) error {
   361  	if version < -1 {
   362  		return ErrInvalidVersion
   363  	}
   364  
   365  	if err := m.lock(); err != nil {
   366  		return err
   367  	}
   368  
   369  	if err := m.databaseDrv.SetVersion(version, false); err != nil {
   370  		return m.unlockErr(err)
   371  	}
   372  
   373  	return m.unlock()
   374  }
   375  
   376  // Version returns the currently active migration version.
   377  // If no migration has been applied, yet, it will return ErrNilVersion.
   378  func (m *Migrate) Version() (version uint, dirty bool, err error) {
   379  	v, d, err := m.databaseDrv.Version()
   380  	if err != nil {
   381  		return 0, false, err
   382  	}
   383  
   384  	if v == database.NilVersion {
   385  		return 0, false, ErrNilVersion
   386  	}
   387  
   388  	return suint(v), d, nil
   389  }
   390  
   391  // read reads either up or down migrations from source `from` to `to`.
   392  // Each migration is then written to the ret channel.
   393  // If an error occurs during reading, that error is written to the ret channel, too.
   394  // Once read is done reading it will close the ret channel.
   395  func (m *Migrate) read(from int, to int, ret chan<- interface{}) {
   396  	defer close(ret)
   397  
   398  	// check if from version exists
   399  	if from >= 0 {
   400  		if err := m.versionExists(suint(from)); err != nil {
   401  			ret <- err
   402  			return
   403  		}
   404  	}
   405  
   406  	// check if to version exists
   407  	if to >= 0 {
   408  		if err := m.versionExists(suint(to)); err != nil {
   409  			ret <- err
   410  			return
   411  		}
   412  	}
   413  
   414  	// no change?
   415  	if from == to {
   416  		ret <- ErrNoChange
   417  		return
   418  	}
   419  
   420  	if from < to {
   421  		// it's going up
   422  		// apply first migration if from is nil version
   423  		if from == -1 {
   424  			firstVersion, err := m.sourceDrv.First()
   425  			if err != nil {
   426  				ret <- err
   427  				return
   428  			}
   429  
   430  			migr, err := m.newMigration(firstVersion, int(firstVersion))
   431  			if err != nil {
   432  				ret <- err
   433  				return
   434  			}
   435  
   436  			ret <- migr
   437  			go migr.Buffer()
   438  			from = int(firstVersion)
   439  		}
   440  
   441  		// run until we reach target ...
   442  		for from < to {
   443  			if m.stop() {
   444  				return
   445  			}
   446  
   447  			next, err := m.sourceDrv.Next(suint(from))
   448  			if err != nil {
   449  				ret <- err
   450  				return
   451  			}
   452  
   453  			migr, err := m.newMigration(next, int(next))
   454  			if err != nil {
   455  				ret <- err
   456  				return
   457  			}
   458  
   459  			ret <- migr
   460  			go migr.Buffer()
   461  			from = int(next)
   462  		}
   463  
   464  	} else {
   465  		// it's going down
   466  		// run until we reach target ...
   467  		for from > to && from >= 0 {
   468  			if m.stop() {
   469  				return
   470  			}
   471  
   472  			prev, err := m.sourceDrv.Prev(suint(from))
   473  			if os.IsNotExist(err) && to == -1 {
   474  				// apply nil migration
   475  				migr, err := m.newMigration(suint(from), -1)
   476  				if err != nil {
   477  					ret <- err
   478  					return
   479  				}
   480  				ret <- migr
   481  				go migr.Buffer()
   482  				return
   483  
   484  			} else if err != nil {
   485  				ret <- err
   486  				return
   487  			}
   488  
   489  			migr, err := m.newMigration(suint(from), int(prev))
   490  			if err != nil {
   491  				ret <- err
   492  				return
   493  			}
   494  
   495  			ret <- migr
   496  			go migr.Buffer()
   497  			from = int(prev)
   498  		}
   499  	}
   500  }
   501  
   502  // readUp reads up migrations from `from` limitted by `limit`.
   503  // limit can be -1, implying no limit and reading until there are no more migrations.
   504  // Each migration is then written to the ret channel.
   505  // If an error occurs during reading, that error is written to the ret channel, too.
   506  // Once readUp is done reading it will close the ret channel.
   507  func (m *Migrate) readUp(from int, limit int, ret chan<- interface{}) {
   508  	defer close(ret)
   509  
   510  	// check if from version exists
   511  	if from >= 0 {
   512  		if err := m.versionExists(suint(from)); err != nil {
   513  			ret <- err
   514  			return
   515  		}
   516  	}
   517  
   518  	if limit == 0 {
   519  		ret <- ErrNoChange
   520  		return
   521  	}
   522  
   523  	count := 0
   524  	for count < limit || limit == -1 {
   525  		if m.stop() {
   526  			return
   527  		}
   528  
   529  		// apply first migration if from is nil version
   530  		if from == -1 {
   531  			firstVersion, err := m.sourceDrv.First()
   532  			if err != nil {
   533  				ret <- err
   534  				return
   535  			}
   536  
   537  			migr, err := m.newMigration(firstVersion, int(firstVersion))
   538  			if err != nil {
   539  				ret <- err
   540  				return
   541  			}
   542  
   543  			ret <- migr
   544  			go migr.Buffer()
   545  			from = int(firstVersion)
   546  			count++
   547  			continue
   548  		}
   549  
   550  		// apply next migration
   551  		next, err := m.sourceDrv.Next(suint(from))
   552  		if os.IsNotExist(err) {
   553  			// no limit, but no migrations applied?
   554  			if limit == -1 && count == 0 {
   555  				ret <- ErrNoChange
   556  				return
   557  			}
   558  
   559  			// no limit, reached end
   560  			if limit == -1 {
   561  				return
   562  			}
   563  
   564  			// reached end, and didn't apply any migrations
   565  			if limit > 0 && count == 0 {
   566  				ret <- os.ErrNotExist
   567  				return
   568  			}
   569  
   570  			// applied less migrations than limit?
   571  			if count < limit {
   572  				ret <- ErrShortLimit{suint(limit - count)}
   573  				return
   574  			}
   575  		}
   576  		if err != nil {
   577  			ret <- err
   578  			return
   579  		}
   580  
   581  		migr, err := m.newMigration(next, int(next))
   582  		if err != nil {
   583  			ret <- err
   584  			return
   585  		}
   586  
   587  		ret <- migr
   588  		go migr.Buffer()
   589  		from = int(next)
   590  		count++
   591  	}
   592  }
   593  
   594  // readDown reads down migrations from `from` limitted by `limit`.
   595  // limit can be -1, implying no limit and reading until there are no more migrations.
   596  // Each migration is then written to the ret channel.
   597  // If an error occurs during reading, that error is written to the ret channel, too.
   598  // Once readDown is done reading it will close the ret channel.
   599  func (m *Migrate) readDown(from int, limit int, ret chan<- interface{}) {
   600  	defer close(ret)
   601  
   602  	// check if from version exists
   603  	if from >= 0 {
   604  		if err := m.versionExists(suint(from)); err != nil {
   605  			ret <- err
   606  			return
   607  		}
   608  	}
   609  
   610  	if limit == 0 {
   611  		ret <- ErrNoChange
   612  		return
   613  	}
   614  
   615  	// no change if already at nil version
   616  	if from == -1 && limit == -1 {
   617  		ret <- ErrNoChange
   618  		return
   619  	}
   620  
   621  	// can't go over limit if already at nil version
   622  	if from == -1 && limit > 0 {
   623  		ret <- os.ErrNotExist
   624  		return
   625  	}
   626  
   627  	count := 0
   628  	for count < limit || limit == -1 {
   629  		if m.stop() {
   630  			return
   631  		}
   632  
   633  		prev, err := m.sourceDrv.Prev(suint(from))
   634  		if os.IsNotExist(err) {
   635  			// no limit or haven't reached limit, apply "first" migration
   636  			if limit == -1 || limit-count > 0 {
   637  				firstVersion, err := m.sourceDrv.First()
   638  				if err != nil {
   639  					ret <- err
   640  					return
   641  				}
   642  
   643  				migr, err := m.newMigration(firstVersion, -1)
   644  				if err != nil {
   645  					ret <- err
   646  					return
   647  				}
   648  				ret <- migr
   649  				go migr.Buffer()
   650  				count++
   651  			}
   652  
   653  			if count < limit {
   654  				ret <- ErrShortLimit{suint(limit - count)}
   655  			}
   656  			return
   657  		}
   658  		if err != nil {
   659  			ret <- err
   660  			return
   661  		}
   662  
   663  		migr, err := m.newMigration(suint(from), int(prev))
   664  		if err != nil {
   665  			ret <- err
   666  			return
   667  		}
   668  
   669  		ret <- migr
   670  		go migr.Buffer()
   671  		from = int(prev)
   672  		count++
   673  	}
   674  }
   675  
   676  // runMigrations reads *Migration and error from a channel. Any other type
   677  // sent on this channel will result in a panic. Each migration is then
   678  // proxied to the database driver and run against the database.
   679  // Before running a newly received migration it will check if it's supposed
   680  // to stop execution because it might have received a stop signal on the
   681  // GracefulStop channel.
   682  func (m *Migrate) runMigrations(ret <-chan interface{}) error {
   683  	for r := range ret {
   684  
   685  		if m.stop() {
   686  			return nil
   687  		}
   688  
   689  		switch r.(type) {
   690  		case error:
   691  			return r.(error)
   692  
   693  		case *Migration:
   694  			migr := r.(*Migration)
   695  
   696  			// set version with dirty state
   697  			if err := m.databaseDrv.SetVersion(migr.TargetVersion, true); err != nil {
   698  				return err
   699  			}
   700  
   701  			if migr.Body != nil {
   702  				m.logVerbosePrintf("Read and execute %v\n", migr.LogString())
   703  				if err := m.databaseDrv.Run(migr.BufferedBody); err != nil {
   704  					return err
   705  				}
   706  			}
   707  
   708  			// set clean state
   709  			if err := m.databaseDrv.SetVersion(migr.TargetVersion, false); err != nil {
   710  				return err
   711  			}
   712  
   713  			endTime := time.Now()
   714  			readTime := migr.FinishedReading.Sub(migr.StartedBuffering)
   715  			runTime := endTime.Sub(migr.FinishedReading)
   716  
   717  			// log either verbose or normal
   718  			if m.Log != nil {
   719  				if m.Log.Verbose() {
   720  					m.logPrintf("Finished %v (read %v, ran %v)\n", migr.LogString(), readTime, runTime)
   721  				} else {
   722  					m.logPrintf("%v (%v)\n", migr.LogString(), readTime+runTime)
   723  				}
   724  			}
   725  
   726  		default:
   727  			return fmt.Errorf("unknown type: %T with value: %+v", r, r)
   728  		}
   729  	}
   730  	return nil
   731  }
   732  
   733  // versionExists checks the source if either the up or down migration for
   734  // the specified migration version exists.
   735  func (m *Migrate) versionExists(version uint) error {
   736  	// try up migration first
   737  	up, _, err := m.sourceDrv.ReadUp(version)
   738  	if err == nil {
   739  		defer up.Close()
   740  	}
   741  	if os.IsExist(err) {
   742  		return nil
   743  	} else if !os.IsNotExist(err) {
   744  		return err
   745  	}
   746  
   747  	// then try down migration
   748  	down, _, err := m.sourceDrv.ReadDown(version)
   749  	if err == nil {
   750  		defer down.Close()
   751  	}
   752  	if os.IsExist(err) {
   753  		return nil
   754  	} else if !os.IsNotExist(err) {
   755  		return err
   756  	}
   757  
   758  	return os.ErrNotExist
   759  }
   760  
   761  // stop returns true if no more migrations should be run against the database
   762  // because a stop signal was received on the GracefulStop channel.
   763  // Calls are cheap and this function is not blocking.
   764  func (m *Migrate) stop() bool {
   765  	if m.isGracefulStop {
   766  		return true
   767  	}
   768  
   769  	select {
   770  	case <-m.GracefulStop:
   771  		m.isGracefulStop = true
   772  		return true
   773  
   774  	default:
   775  		return false
   776  	}
   777  }
   778  
   779  // newMigration is a helper func that returns a *Migration for the
   780  // specified version and targetVersion.
   781  func (m *Migrate) newMigration(version uint, targetVersion int) (*Migration, error) {
   782  	var migr *Migration
   783  
   784  	if targetVersion >= int(version) {
   785  		r, identifier, err := m.sourceDrv.ReadUp(version)
   786  		if os.IsNotExist(err) {
   787  			// create "empty" migration
   788  			migr, err = NewMigration(nil, "", version, targetVersion)
   789  			if err != nil {
   790  				return nil, err
   791  			}
   792  
   793  		} else if err != nil {
   794  			return nil, err
   795  
   796  		} else {
   797  			// create migration from up source
   798  			migr, err = NewMigration(r, identifier, version, targetVersion)
   799  			if err != nil {
   800  				return nil, err
   801  			}
   802  		}
   803  
   804  	} else {
   805  		r, identifier, err := m.sourceDrv.ReadDown(version)
   806  		if os.IsNotExist(err) {
   807  			// create "empty" migration
   808  			migr, err = NewMigration(nil, "", version, targetVersion)
   809  			if err != nil {
   810  				return nil, err
   811  			}
   812  
   813  		} else if err != nil {
   814  			return nil, err
   815  
   816  		} else {
   817  			// create migration from down source
   818  			migr, err = NewMigration(r, identifier, version, targetVersion)
   819  			if err != nil {
   820  				return nil, err
   821  			}
   822  		}
   823  	}
   824  
   825  	if m.PrefetchMigrations > 0 && migr.Body != nil {
   826  		m.logVerbosePrintf("Start buffering %v\n", migr.LogString())
   827  	} else {
   828  		m.logVerbosePrintf("Scheduled %v\n", migr.LogString())
   829  	}
   830  
   831  	return migr, nil
   832  }
   833  
   834  // lock is a thread safe helper function to lock the database.
   835  // It should be called as late as possible when running migrations.
   836  func (m *Migrate) lock() error {
   837  	m.isLockedMu.Lock()
   838  	defer m.isLockedMu.Unlock()
   839  
   840  	if m.isLocked {
   841  		return ErrLocked
   842  	}
   843  
   844  	// create done channel, used in the timeout goroutine
   845  	done := make(chan bool, 1)
   846  	defer func() {
   847  		done <- true
   848  	}()
   849  
   850  	// use errchan to signal error back to this context
   851  	errchan := make(chan error, 2)
   852  
   853  	// start timeout goroutine
   854  	timeout := time.After(m.LockTimeout)
   855  	go func() {
   856  		for {
   857  			select {
   858  			case <-done:
   859  				return
   860  			case <-timeout:
   861  				errchan <- ErrLockTimeout
   862  				return
   863  			}
   864  		}
   865  	}()
   866  
   867  	// now try to acquire the lock
   868  	go func() {
   869  		if err := m.databaseDrv.Lock(); err != nil {
   870  			errchan <- err
   871  		} else {
   872  			errchan <- nil
   873  		}
   874  		return
   875  	}()
   876  
   877  	// wait until we either recieve ErrLockTimeout or error from Lock operation
   878  	err := <-errchan
   879  	if err == nil {
   880  		m.isLocked = true
   881  	}
   882  	return err
   883  }
   884  
   885  // unlock is a thread safe helper function to unlock the database.
   886  // It should be called as early as possible when no more migrations are
   887  // expected to be executed.
   888  func (m *Migrate) unlock() error {
   889  	m.isLockedMu.Lock()
   890  	defer m.isLockedMu.Unlock()
   891  
   892  	if err := m.databaseDrv.Unlock(); err != nil {
   893  		// BUG: Can potentially create a deadlock. Add a timeout.
   894  		return err
   895  	}
   896  
   897  	m.isLocked = false
   898  	return nil
   899  }
   900  
   901  // unlockErr calls unlock and returns a combined error
   902  // if a prevErr is not nil.
   903  func (m *Migrate) unlockErr(prevErr error) error {
   904  	if err := m.unlock(); err != nil {
   905  		return NewMultiError(prevErr, err)
   906  	}
   907  	return prevErr
   908  }
   909  
   910  // logPrintf writes to m.Log if not nil
   911  func (m *Migrate) logPrintf(format string, v ...interface{}) {
   912  	if m.Log != nil {
   913  		m.Log.Printf(format, v...)
   914  	}
   915  }
   916  
   917  // logVerbosePrintf writes to m.Log if not nil. Use for verbose logging output.
   918  func (m *Migrate) logVerbosePrintf(format string, v ...interface{}) {
   919  	if m.Log != nil && m.Log.Verbose() {
   920  		m.Log.Printf(format, v...)
   921  	}
   922  }