From 8ecb809fac9f13db35b48b43951932f0fbc43e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20L=27homme?= Date: Thu, 19 Jan 2023 09:23:13 -0500 Subject: [PATCH 1/2] Add test showing !88 --- migrate_test.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/migrate_test.go b/migrate_test.go index 89073a35..9702cf7a 100644 --- a/migrate_test.go +++ b/migrate_test.go @@ -502,6 +502,60 @@ func (s *SqliteMigrateSuite) TestPlanMigrationWithHoles(c *C) { c.Assert(plannedMigrations[2].Queries[0], Equals, down) } +func (s *SqliteMigrateSuite) TestPlanMigrationWithHolesThenCatchupOnDown(c *C) { + up := "SELECT 0" + down := "SELECT 1" + migrations := &MemoryMigrationSource{ + Migrations: []*Migration{ + { + Id: "1", + Up: []string{up}, + Down: []string{down}, + }, + { + Id: "3", + Up: []string{up}, + Down: []string{down}, + }, + }, + } + + // apply #1 and #3 + n, err := Exec(s.Db, "sqlite3", migrations, Up) + c.Assert(err, IsNil) + c.Assert(n, Equals, 2) + + records, err := GetMigrationRecords(s.Db, "sqlite3") + c.Assert(err, IsNil) + c.Assert(records, HasLen, 2) + + // add #2 (a missing migration up) + migrations.Migrations = append(migrations.Migrations, &Migration{ + Id: "2", + Up: []string{up}, + Down: []string{down}, + }) + + // going down of 1 operation (3), will apply #2 also. + plannedMigrations, _, err := PlanMigration(s.Db, "sqlite3", migrations, Down, 1) + c.Assert(err, IsNil) + c.Assert(plannedMigrations, HasLen, 2) + c.Assert(plannedMigrations[0].Migration.Id, Equals, "2") + c.Assert(plannedMigrations[0].Queries[0], Equals, up) + c.Assert(plannedMigrations[1].Migration.Id, Equals, "3") + c.Assert(plannedMigrations[1].Queries[0], Equals, down) + + // exec down of 1 + n, err = ExecMax(s.Db, "sqlite3", migrations, Down, 1) + c.Assert(err, IsNil) + c.Assert(n, Equals, 2) + + // should be 2: #1 do not change, #2 is applied by catchup, #3 is down + records, err = GetMigrationRecords(s.Db, "sqlite3") + c.Assert(err, IsNil) + c.Assert(records, HasLen, 2) +} + func (s *SqliteMigrateSuite) TestLess(c *C) { c.Assert((Migration{Id: "1"}).Less(&Migration{Id: "2"}), Equals, true) // 1 less than 2 c.Assert((Migration{Id: "2"}).Less(&Migration{Id: "1"}), Equals, false) // 2 not less than 1 From ae3a7eb00a4280643f75a26c59c0c3903116ee58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20L=27homme?= Date: Thu, 19 Jan 2023 08:15:10 -0500 Subject: [PATCH 2/2] Fix missing info on catchup migrations !88 --- migrate.go | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/migrate.go b/migrate.go index a6ff7b25..e5261477 100644 --- a/migrate.go +++ b/migrate.go @@ -168,6 +168,19 @@ type PlannedMigration struct { Queries []string } +// isUpQuery returns true if the query is an "up" query. +func (m PlannedMigration) isUpQuery() bool { + if len(m.Up) != len(m.Queries) { + return false + } + for i, query := range m.Up { + if query != m.Queries[i] { + return false + } + } + return true +} + type byId []*Migration func (b byId) Len() int { return len(b) } @@ -505,8 +518,12 @@ func (ms MigrationSet) applyMigrations(dir MigrationDirection, migrations []*Pla } } - switch dir { - case Up: + switch { + // case when we are migrating down, but a migration up was not applied. + // See MigrationSet.planMigrationCommon and the ToCatchup call. + case dir == Down && migration.isUpQuery(): + fallthrough + case dir == Up: err = executor.Insert(&MigrationRecord{ Id: migration.Id, AppliedAt: time.Now(), @@ -518,7 +535,7 @@ func (ms MigrationSet) applyMigrations(dir MigrationDirection, migrations []*Pla return applied, newTxError(migration, err) } - case Down: + case dir == Down: _, err := executor.Delete(&MigrationRecord{ Id: migration.Id, })