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