Skip to content

Commit

Permalink
Add SetLazyLoad option, which sets the boolean to enable migration fi…
Browse files Browse the repository at this point in the history
…le to be loaded only when needed.
  • Loading branch information
KeiichiHirobe committed Feb 4, 2022
1 parent 5d0f4bf commit ca2e507
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 8 deletions.
85 changes: 77 additions & 8 deletions migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type MigrationSet struct {
IgnoreUnknown bool
// DisableCreateTable disable the creation of the migration table
DisableCreateTable bool
// LazyLoad enable migration file to be loaded only when needed.
LazyLoad bool
}

var migSet = MigrationSet{}
Expand Down Expand Up @@ -121,13 +123,28 @@ func SetIgnoreUnknown(v bool) {
migSet.IgnoreUnknown = v
}

// SetLazyLoad sets the boolean to enable migration file to be loaded only when needed.
func SetLazyLoad(v bool) {
migSet.LazyLoad = v
}

type migrationFile struct {
dir http.FileSystem
root string
baseName string
}

type Migration struct {
Id string
Up []string
Down []string

DisableTransactionUp bool
DisableTransactionDown bool

delayLoad bool
// file is information of migration file, which is used to load migration file later if delayLoad is true.
file *migrationFile
}

func (m Migration) Less(other *Migration) bool {
Expand Down Expand Up @@ -160,6 +177,34 @@ func (m Migration) VersionInt() int64 {
return value
}

// Load parses migration file if not yet
func (m *Migration) Load() error {
if !m.delayLoad {
return nil
}
if m.file == nil {
return fmt.Errorf("Error m.file must not be nil when call loadFile")
}
root := m.file.root
name := m.file.baseName
file, err := m.file.dir.Open(path.Join(root, name))
if err != nil {
return fmt.Errorf("Error while opening %s: %s", name, err)
}
defer func() { _ = file.Close() }()

parsed, err := sqlparse.ParseMigration(file)
if err != nil {
return fmt.Errorf("Error parsing migration (%s): %s", m.Id, err)
}
m.Up = parsed.UpStatements
m.Down = parsed.DownStatements
m.DisableTransactionUp = parsed.DisableTransactionUp
m.DisableTransactionDown = parsed.DisableTransactionDown
m.delayLoad = false
return nil
}

type PlannedMigration struct {
*Migration

Expand Down Expand Up @@ -266,12 +311,24 @@ func findMigrations(dir http.FileSystem, root string) ([]*Migration, error) {

for _, info := range files {
if strings.HasSuffix(info.Name(), ".sql") {
migration, err := migrationFromFile(dir, root, info)
if err != nil {
return nil, err
if migSet.LazyLoad {
migration := &Migration{
Id: info.Name(),
delayLoad: true,
file: &migrationFile{
dir: dir,
root: root,
baseName: info.Name(),
},
}
migrations = append(migrations, migration)
} else {
migration, err := migrationFromFile(dir, root, info)
if err != nil {
return nil, err
}
migrations = append(migrations, migration)
}

migrations = append(migrations, migration)
}
}

Expand Down Expand Up @@ -575,7 +632,11 @@ func (ms MigrationSet) PlanMigration(db *sql.DB, dialect string, m MigrationSour
// Add missing migrations up to the last run migration.
// This can happen for example when merges happened.
if len(existingMigrations) > 0 {
result = append(result, ToCatchup(migrations, existingMigrations, record)...)
catchUp, err := ToCatchup(migrations, existingMigrations, record)
if err != nil {
return nil, nil, err
}
result = append(result, catchUp...)
}

// Figure out which migrations to apply
Expand All @@ -585,6 +646,10 @@ func (ms MigrationSet) PlanMigration(db *sql.DB, dialect string, m MigrationSour
toApplyCount = max
}
for _, v := range toApply[0:toApplyCount] {
err = v.Load()
if err != nil {
return nil, nil, err
}

if dir == Up {
result = append(result, &PlannedMigration{
Expand Down Expand Up @@ -683,7 +748,7 @@ func ToApply(migrations []*Migration, current string, direction MigrationDirecti
panic("Not possible")
}

func ToCatchup(migrations, existingMigrations []*Migration, lastRun *Migration) []*PlannedMigration {
func ToCatchup(migrations, existingMigrations []*Migration, lastRun *Migration) ([]*PlannedMigration, error) {
missing := make([]*PlannedMigration, 0)
for _, migration := range migrations {
found := false
Expand All @@ -694,14 +759,18 @@ func ToCatchup(migrations, existingMigrations []*Migration, lastRun *Migration)
}
}
if !found && migration.Less(lastRun) {
err := migration.Load()
if err != nil {
return nil, err
}
missing = append(missing, &PlannedMigration{
Migration: migration,
Queries: migration.Up,
DisableTransaction: migration.DisableTransactionUp,
})
}
}
return missing
return missing, nil
}

func GetMigrationRecords(db *sql.DB, dialect string) ([]*MigrationRecord, error) {
Expand Down
26 changes: 26 additions & 0 deletions migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -665,3 +665,29 @@ func (s *SqliteMigrateSuite) TestGetMigrationDbMapWithDisableCreateTable(c *C) {
_, err := migSet.getMigrationDbMap(s.Db, "postgres")
c.Assert(err, IsNil)
}

func (s *SqliteMigrateSuite) TestFileMigrateWithLazyLoad(c *C) {
migrations := &FileMigrationSource{
Dir: "test-migrations",
}

SetLazyLoad(true)
migrationsNotLoaded, err := migrations.FindMigrations()
c.Assert(err, IsNil)
for _, migration := range migrationsNotLoaded {
c.Assert(migration.DisableTransactionUp, Equals, false)
c.Assert(migration.DisableTransactionDown, Equals, false)
c.Assert(len(migration.Up), Equals, 0)
c.Assert(len(migration.Down), Equals, 0)
}
// Executes two migrations
n, err := Exec(s.Db, "sqlite3", migrations, Up)
c.Assert(err, IsNil)
c.Assert(n, Equals, 2)

// Has data
id, err := s.DbMap.SelectInt("SELECT id FROM people")
c.Assert(err, IsNil)
c.Assert(id, Equals, int64(1))
SetLazyLoad(false)
}

0 comments on commit ca2e507

Please sign in to comment.