mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
9.5 KiB
357 lines
9.5 KiB
package migrate |
|
|
|
import ( |
|
"database/sql" |
|
"os" |
|
|
|
_ "github.com/mattn/go-sqlite3" |
|
. "gopkg.in/check.v1" |
|
"gopkg.in/gorp.v1" |
|
) |
|
|
|
var filename = "/tmp/sql-migrate-sqlite.db" |
|
var sqliteMigrations = []*Migration{ |
|
&Migration{ |
|
Id: "123", |
|
Up: []string{"CREATE TABLE people (id int)"}, |
|
Down: []string{"DROP TABLE people"}, |
|
}, |
|
&Migration{ |
|
Id: "124", |
|
Up: []string{"ALTER TABLE people ADD COLUMN first_name text"}, |
|
Down: []string{"SELECT 0"}, // Not really supported |
|
}, |
|
} |
|
|
|
type SqliteMigrateSuite struct { |
|
Db *sql.DB |
|
DbMap *gorp.DbMap |
|
} |
|
|
|
var _ = Suite(&SqliteMigrateSuite{}) |
|
|
|
func (s *SqliteMigrateSuite) SetUpTest(c *C) { |
|
db, err := sql.Open("sqlite3", filename) |
|
c.Assert(err, IsNil) |
|
|
|
s.Db = db |
|
s.DbMap = &gorp.DbMap{Db: db, Dialect: &gorp.SqliteDialect{}} |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TearDownTest(c *C) { |
|
err := os.Remove(filename) |
|
c.Assert(err, IsNil) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestRunMigration(c *C) { |
|
migrations := &MemoryMigrationSource{ |
|
Migrations: sqliteMigrations[:1], |
|
} |
|
|
|
// Executes one migration |
|
n, err := Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 1) |
|
|
|
// Can use table now |
|
_, err = s.DbMap.Exec("SELECT * FROM people") |
|
c.Assert(err, IsNil) |
|
|
|
// Shouldn't apply migration again |
|
n, err = Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 0) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestMigrateMultiple(c *C) { |
|
migrations := &MemoryMigrationSource{ |
|
Migrations: sqliteMigrations[:2], |
|
} |
|
|
|
// Executes two migrations |
|
n, err := Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 2) |
|
|
|
// Can use column now |
|
_, err = s.DbMap.Exec("SELECT first_name FROM people") |
|
c.Assert(err, IsNil) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestMigrateIncremental(c *C) { |
|
migrations := &MemoryMigrationSource{ |
|
Migrations: sqliteMigrations[:1], |
|
} |
|
|
|
// Executes one migration |
|
n, err := Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 1) |
|
|
|
// Execute a new migration |
|
migrations = &MemoryMigrationSource{ |
|
Migrations: sqliteMigrations[:2], |
|
} |
|
n, err = Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 1) |
|
|
|
// Can use column now |
|
_, err = s.DbMap.Exec("SELECT first_name FROM people") |
|
c.Assert(err, IsNil) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestFileMigrate(c *C) { |
|
migrations := &FileMigrationSource{ |
|
Dir: "test-migrations", |
|
} |
|
|
|
// 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)) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestAssetMigrate(c *C) { |
|
migrations := &AssetMigrationSource{ |
|
Asset: Asset, |
|
AssetDir: AssetDir, |
|
Dir: "test-migrations", |
|
} |
|
|
|
// 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)) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestMigrateMax(c *C) { |
|
migrations := &FileMigrationSource{ |
|
Dir: "test-migrations", |
|
} |
|
|
|
// Executes one migration |
|
n, err := ExecMax(s.Db, "sqlite3", migrations, Up, 1) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 1) |
|
|
|
id, err := s.DbMap.SelectInt("SELECT COUNT(*) FROM people") |
|
c.Assert(err, IsNil) |
|
c.Assert(id, Equals, int64(0)) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestMigrateDown(c *C) { |
|
migrations := &FileMigrationSource{ |
|
Dir: "test-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)) |
|
|
|
// Undo the last one |
|
n, err = ExecMax(s.Db, "sqlite3", migrations, Down, 1) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 1) |
|
|
|
// No more data |
|
id, err = s.DbMap.SelectInt("SELECT COUNT(*) FROM people") |
|
c.Assert(err, IsNil) |
|
c.Assert(id, Equals, int64(0)) |
|
|
|
// Remove the table. |
|
n, err = ExecMax(s.Db, "sqlite3", migrations, Down, 1) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 1) |
|
|
|
// Cannot query it anymore |
|
_, err = s.DbMap.SelectInt("SELECT COUNT(*) FROM people") |
|
c.Assert(err, Not(IsNil)) |
|
|
|
// Nothing left to do. |
|
n, err = ExecMax(s.Db, "sqlite3", migrations, Down, 1) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 0) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestMigrateDownFull(c *C) { |
|
migrations := &FileMigrationSource{ |
|
Dir: "test-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)) |
|
|
|
// Undo the last one |
|
n, err = Exec(s.Db, "sqlite3", migrations, Down) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 2) |
|
|
|
// Cannot query it anymore |
|
_, err = s.DbMap.SelectInt("SELECT COUNT(*) FROM people") |
|
c.Assert(err, Not(IsNil)) |
|
|
|
// Nothing left to do. |
|
n, err = Exec(s.Db, "sqlite3", migrations, Down) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 0) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestMigrateTransaction(c *C) { |
|
migrations := &MemoryMigrationSource{ |
|
Migrations: []*Migration{ |
|
sqliteMigrations[0], |
|
sqliteMigrations[1], |
|
&Migration{ |
|
Id: "125", |
|
Up: []string{"INSERT INTO people (id, first_name) VALUES (1, 'Test')", "SELECT fail"}, |
|
Down: []string{}, // Not important here |
|
}, |
|
}, |
|
} |
|
|
|
// Should fail, transaction should roll back the INSERT. |
|
n, err := Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, Not(IsNil)) |
|
c.Assert(n, Equals, 2) |
|
|
|
// INSERT should be rolled back |
|
count, err := s.DbMap.SelectInt("SELECT COUNT(*) FROM people") |
|
c.Assert(err, IsNil) |
|
c.Assert(count, Equals, int64(0)) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestPlanMigration(c *C) { |
|
migrations := &MemoryMigrationSource{ |
|
Migrations: []*Migration{ |
|
&Migration{ |
|
Id: "1_create_table.sql", |
|
Up: []string{"CREATE TABLE people (id int)"}, |
|
Down: []string{"DROP TABLE people"}, |
|
}, |
|
&Migration{ |
|
Id: "2_alter_table.sql", |
|
Up: []string{"ALTER TABLE people ADD COLUMN first_name text"}, |
|
Down: []string{"SELECT 0"}, // Not really supported |
|
}, |
|
&Migration{ |
|
Id: "10_add_last_name.sql", |
|
Up: []string{"ALTER TABLE people ADD COLUMN last_name text"}, |
|
Down: []string{"ALTER TABLE people DROP COLUMN last_name"}, |
|
}, |
|
}, |
|
} |
|
n, err := Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 3) |
|
|
|
migrations.Migrations = append(migrations.Migrations, &Migration{ |
|
Id: "11_add_middle_name.sql", |
|
Up: []string{"ALTER TABLE people ADD COLUMN middle_name text"}, |
|
Down: []string{"ALTER TABLE people DROP COLUMN middle_name"}, |
|
}) |
|
|
|
plannedMigrations, _, err := PlanMigration(s.Db, "sqlite3", migrations, Up, 0) |
|
c.Assert(err, IsNil) |
|
c.Assert(plannedMigrations, HasLen, 1) |
|
c.Assert(plannedMigrations[0].Migration, Equals, migrations.Migrations[3]) |
|
|
|
plannedMigrations, _, err = PlanMigration(s.Db, "sqlite3", migrations, Down, 0) |
|
c.Assert(err, IsNil) |
|
c.Assert(plannedMigrations, HasLen, 3) |
|
c.Assert(plannedMigrations[0].Migration, Equals, migrations.Migrations[2]) |
|
c.Assert(plannedMigrations[1].Migration, Equals, migrations.Migrations[1]) |
|
c.Assert(plannedMigrations[2].Migration, Equals, migrations.Migrations[0]) |
|
} |
|
|
|
func (s *SqliteMigrateSuite) TestPlanMigrationWithHoles(c *C) { |
|
up := "SELECT 0" |
|
down := "SELECT 1" |
|
migrations := &MemoryMigrationSource{ |
|
Migrations: []*Migration{ |
|
&Migration{ |
|
Id: "1", |
|
Up: []string{up}, |
|
Down: []string{down}, |
|
}, |
|
&Migration{ |
|
Id: "3", |
|
Up: []string{up}, |
|
Down: []string{down}, |
|
}, |
|
}, |
|
} |
|
n, err := Exec(s.Db, "sqlite3", migrations, Up) |
|
c.Assert(err, IsNil) |
|
c.Assert(n, Equals, 2) |
|
|
|
migrations.Migrations = append(migrations.Migrations, &Migration{ |
|
Id: "2", |
|
Up: []string{up}, |
|
Down: []string{down}, |
|
}) |
|
|
|
migrations.Migrations = append(migrations.Migrations, &Migration{ |
|
Id: "4", |
|
Up: []string{up}, |
|
Down: []string{down}, |
|
}) |
|
|
|
migrations.Migrations = append(migrations.Migrations, &Migration{ |
|
Id: "5", |
|
Up: []string{up}, |
|
Down: []string{down}, |
|
}) |
|
|
|
// apply all the missing migrations |
|
plannedMigrations, _, err := PlanMigration(s.Db, "sqlite3", migrations, Up, 0) |
|
c.Assert(err, IsNil) |
|
c.Assert(plannedMigrations, HasLen, 3) |
|
c.Assert(plannedMigrations[0].Migration.Id, Equals, "2") |
|
c.Assert(plannedMigrations[0].Queries[0], Equals, up) |
|
c.Assert(plannedMigrations[1].Migration.Id, Equals, "4") |
|
c.Assert(plannedMigrations[1].Queries[0], Equals, up) |
|
c.Assert(plannedMigrations[2].Migration.Id, Equals, "5") |
|
c.Assert(plannedMigrations[2].Queries[0], Equals, up) |
|
|
|
// first catch up to current target state 123, then migrate down 1 step to 12 |
|
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) |
|
|
|
// first catch up to current target state 123, then migrate down 2 steps to 1 |
|
plannedMigrations, _, err = PlanMigration(s.Db, "sqlite3", migrations, Down, 2) |
|
c.Assert(err, IsNil) |
|
c.Assert(plannedMigrations, HasLen, 3) |
|
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) |
|
c.Assert(plannedMigrations[2].Migration.Id, Equals, "2") |
|
c.Assert(plannedMigrations[2].Queries[0], Equals, down) |
|
}
|
|
|