Skip to content

Commit ca2e507

Browse files
committed
Add SetLazyLoad option, which sets the boolean to enable migration file to be loaded only when needed.
1 parent 5d0f4bf commit ca2e507

File tree

2 files changed

+103
-8
lines changed

2 files changed

+103
-8
lines changed

migrate.go

Lines changed: 77 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ type MigrationSet struct {
3939
IgnoreUnknown bool
4040
// DisableCreateTable disable the creation of the migration table
4141
DisableCreateTable bool
42+
// LazyLoad enable migration file to be loaded only when needed.
43+
LazyLoad bool
4244
}
4345

4446
var migSet = MigrationSet{}
@@ -121,13 +123,28 @@ func SetIgnoreUnknown(v bool) {
121123
migSet.IgnoreUnknown = v
122124
}
123125

126+
// SetLazyLoad sets the boolean to enable migration file to be loaded only when needed.
127+
func SetLazyLoad(v bool) {
128+
migSet.LazyLoad = v
129+
}
130+
131+
type migrationFile struct {
132+
dir http.FileSystem
133+
root string
134+
baseName string
135+
}
136+
124137
type Migration struct {
125138
Id string
126139
Up []string
127140
Down []string
128141

129142
DisableTransactionUp bool
130143
DisableTransactionDown bool
144+
145+
delayLoad bool
146+
// file is information of migration file, which is used to load migration file later if delayLoad is true.
147+
file *migrationFile
131148
}
132149

133150
func (m Migration) Less(other *Migration) bool {
@@ -160,6 +177,34 @@ func (m Migration) VersionInt() int64 {
160177
return value
161178
}
162179

180+
// Load parses migration file if not yet
181+
func (m *Migration) Load() error {
182+
if !m.delayLoad {
183+
return nil
184+
}
185+
if m.file == nil {
186+
return fmt.Errorf("Error m.file must not be nil when call loadFile")
187+
}
188+
root := m.file.root
189+
name := m.file.baseName
190+
file, err := m.file.dir.Open(path.Join(root, name))
191+
if err != nil {
192+
return fmt.Errorf("Error while opening %s: %s", name, err)
193+
}
194+
defer func() { _ = file.Close() }()
195+
196+
parsed, err := sqlparse.ParseMigration(file)
197+
if err != nil {
198+
return fmt.Errorf("Error parsing migration (%s): %s", m.Id, err)
199+
}
200+
m.Up = parsed.UpStatements
201+
m.Down = parsed.DownStatements
202+
m.DisableTransactionUp = parsed.DisableTransactionUp
203+
m.DisableTransactionDown = parsed.DisableTransactionDown
204+
m.delayLoad = false
205+
return nil
206+
}
207+
163208
type PlannedMigration struct {
164209
*Migration
165210

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

267312
for _, info := range files {
268313
if strings.HasSuffix(info.Name(), ".sql") {
269-
migration, err := migrationFromFile(dir, root, info)
270-
if err != nil {
271-
return nil, err
314+
if migSet.LazyLoad {
315+
migration := &Migration{
316+
Id: info.Name(),
317+
delayLoad: true,
318+
file: &migrationFile{
319+
dir: dir,
320+
root: root,
321+
baseName: info.Name(),
322+
},
323+
}
324+
migrations = append(migrations, migration)
325+
} else {
326+
migration, err := migrationFromFile(dir, root, info)
327+
if err != nil {
328+
return nil, err
329+
}
330+
migrations = append(migrations, migration)
272331
}
273-
274-
migrations = append(migrations, migration)
275332
}
276333
}
277334

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

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

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

686-
func ToCatchup(migrations, existingMigrations []*Migration, lastRun *Migration) []*PlannedMigration {
751+
func ToCatchup(migrations, existingMigrations []*Migration, lastRun *Migration) ([]*PlannedMigration, error) {
687752
missing := make([]*PlannedMigration, 0)
688753
for _, migration := range migrations {
689754
found := false
@@ -694,14 +759,18 @@ func ToCatchup(migrations, existingMigrations []*Migration, lastRun *Migration)
694759
}
695760
}
696761
if !found && migration.Less(lastRun) {
762+
err := migration.Load()
763+
if err != nil {
764+
return nil, err
765+
}
697766
missing = append(missing, &PlannedMigration{
698767
Migration: migration,
699768
Queries: migration.Up,
700769
DisableTransaction: migration.DisableTransactionUp,
701770
})
702771
}
703772
}
704-
return missing
773+
return missing, nil
705774
}
706775

707776
func GetMigrationRecords(db *sql.DB, dialect string) ([]*MigrationRecord, error) {

migrate_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,29 @@ func (s *SqliteMigrateSuite) TestGetMigrationDbMapWithDisableCreateTable(c *C) {
665665
_, err := migSet.getMigrationDbMap(s.Db, "postgres")
666666
c.Assert(err, IsNil)
667667
}
668+
669+
func (s *SqliteMigrateSuite) TestFileMigrateWithLazyLoad(c *C) {
670+
migrations := &FileMigrationSource{
671+
Dir: "test-migrations",
672+
}
673+
674+
SetLazyLoad(true)
675+
migrationsNotLoaded, err := migrations.FindMigrations()
676+
c.Assert(err, IsNil)
677+
for _, migration := range migrationsNotLoaded {
678+
c.Assert(migration.DisableTransactionUp, Equals, false)
679+
c.Assert(migration.DisableTransactionDown, Equals, false)
680+
c.Assert(len(migration.Up), Equals, 0)
681+
c.Assert(len(migration.Down), Equals, 0)
682+
}
683+
// Executes two migrations
684+
n, err := Exec(s.Db, "sqlite3", migrations, Up)
685+
c.Assert(err, IsNil)
686+
c.Assert(n, Equals, 2)
687+
688+
// Has data
689+
id, err := s.DbMap.SelectInt("SELECT id FROM people")
690+
c.Assert(err, IsNil)
691+
c.Assert(id, Equals, int64(1))
692+
SetLazyLoad(false)
693+
}

0 commit comments

Comments
 (0)