migrate refactor: simplify MigrationMap struct by allowing each Migration to track its own Version

pull/2/head
Liam Staskawicz 2013-01-06 22:12:17 -08:00
parent 0287dcd9b2
commit edaa9e3049
2 changed files with 37 additions and 47 deletions

View File

@ -49,8 +49,8 @@ func statusRun(cmd *Command, args ...string) {
fmt.Printf("goose: status for environment '%v'\n", conf.Env) fmt.Printf("goose: status for environment '%v'\n", conf.Env)
fmt.Println(" Applied At Migration") fmt.Println(" Applied At Migration")
fmt.Println(" =======================================") fmt.Println(" =======================================")
for _, v := range mm.Versions { for _, m := range mm.Migrations {
printMigrationStatus(db, v, path.Base(mm.Migrations[v].Source)) printMigrationStatus(db, m.Version, path.Base(m.Source))
} }
} }

View File

@ -22,22 +22,22 @@ type MigrationRecord struct {
} }
type Migration struct { type Migration struct {
Version int64
Next int64 // next version, or -1 if none Next int64 // next version, or -1 if none
Previous int64 // previous version, -1 if none Previous int64 // previous version, -1 if none
Source string // .go or .sql script Source string // .go or .sql script
} }
type MigrationVersions []int64 type MigrationSlice []Migration
// helpers so we can use pkg sort // helpers so we can use pkg sort
func (s MigrationVersions) Len() int { return len(s) } func (s MigrationSlice) Len() int { return len(s) }
func (s MigrationVersions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s MigrationSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s MigrationVersions) Less(i, j int) bool { return s[i] < s[j] } func (s MigrationSlice) Less(i, j int) bool { return s[i].Version < s[j].Version }
type MigrationMap struct { type MigrationMap struct {
Versions MigrationVersions // sorted slice of version keys Migrations MigrationSlice // migrations, sorted according to Direction
Migrations map[int64]Migration // sources (.sql or .go) keyed by version Direction bool // sort direction: true -> Up, false -> Down
Direction bool // sort direction: true -> Up, false -> Down
} }
func runMigrations(conf *DBConf, migrationsDir string, target int64) { func runMigrations(conf *DBConf, migrationsDir string, target int64) {
@ -58,7 +58,7 @@ func runMigrations(conf *DBConf, migrationsDir string, target int64) {
log.Fatal(err) log.Fatal(err)
} }
if len(mm.Versions) == 0 { if len(mm.Migrations) == 0 {
fmt.Printf("goose: no migrations to run. current version: %d\n", current) fmt.Printf("goose: no migrations to run. current version: %d\n", current)
return return
} }
@ -68,24 +68,22 @@ func runMigrations(conf *DBConf, migrationsDir string, target int64) {
fmt.Printf("goose: migrating db environment '%v', current version: %d, target: %d\n", fmt.Printf("goose: migrating db environment '%v', current version: %d, target: %d\n",
conf.Env, current, target) conf.Env, current, target)
for _, v := range mm.Versions { for _, m := range mm.Migrations {
var e error var e error
filepath := mm.Migrations[v].Source switch path.Ext(m.Source) {
switch path.Ext(filepath) {
case ".go": case ".go":
e = runGoMigration(conf, filepath, v, mm.Direction) e = runGoMigration(conf, m.Source, m.Version, mm.Direction)
case ".sql": case ".sql":
e = runSQLMigration(db, filepath, v, mm.Direction) e = runSQLMigration(db, m.Source, m.Version, mm.Direction)
} }
if e != nil { if e != nil {
log.Fatalf("FAIL %v, quitting migration", e) log.Fatalf("FAIL %v, quitting migration", e)
} }
fmt.Println("OK ", path.Base(filepath)) fmt.Println("OK ", path.Base(m.Source))
} }
} }
@ -93,9 +91,7 @@ func runMigrations(conf *DBConf, migrationsDir string, target int64) {
// migrations folder, and key them by version // migrations folder, and key them by version
func collectMigrations(dirpath string, current, target int64) (mm *MigrationMap, err error) { func collectMigrations(dirpath string, current, target int64) (mm *MigrationMap, err error) {
mm = &MigrationMap{ mm = &MigrationMap{}
Migrations: make(map[int64]Migration),
}
// extract the numeric component of each migration, // extract the numeric component of each migration,
// filter out any uninteresting files, // filter out any uninteresting files,
@ -104,9 +100,11 @@ func collectMigrations(dirpath string, current, target int64) (mm *MigrationMap,
if v, e := numericComponent(name); e == nil { if v, e := numericComponent(name); e == nil {
if _, ok := mm.Migrations[v]; ok { for _, m := range mm.Migrations {
log.Fatalf("more than one file specifies the migration for version %d (%s and %s)", if v == m.Version {
v, mm.Versions[v], path.Join(dirpath, name)) log.Fatalf("more than one file specifies the migration for version %d (%s and %s)",
v, m.Source, path.Join(dirpath, name))
}
} }
if versionFilter(v, current, target) { if versionFilter(v, current, target) {
@ -138,43 +136,35 @@ func versionFilter(v, current, target int64) bool {
return false return false
} }
func (m *MigrationMap) Append(v int64, source string) { func (mm *MigrationMap) Append(v int64, source string) {
m.Versions = append(m.Versions, v) mm.Migrations = append(mm.Migrations, Migration{
m.Migrations[v] = Migration{ Version: v,
Next: -1, Next: -1,
Previous: -1, Previous: -1,
Source: source, Source: source,
} })
} }
func (m *MigrationMap) Sort(direction bool) { func (mm *MigrationMap) Sort(direction bool) {
sort.Sort(m.Versions) sort.Sort(mm.Migrations)
// set direction, and reverse order if need be // set direction, and reverse order if need be
m.Direction = direction mm.Direction = direction
if m.Direction == false { if mm.Direction == false {
for i, j := 0, len(m.Versions)-1; i < j; i, j = i+1, j-1 { for i, j := 0, len(mm.Migrations)-1; i < j; i, j = i+1, j-1 {
m.Versions[i], m.Versions[j] = m.Versions[j], m.Versions[i] mm.Migrations[i], mm.Migrations[j] = mm.Migrations[j], mm.Migrations[i]
} }
} }
// now that we're sorted in the appropriate direction, // now that we're sorted in the appropriate direction,
// populate next and previous for each migration // populate next and previous for each migration
// for i, m := range mm.Migrations {
// work around http://code.google.com/p/go/issues/detail?id=3117 prev := int64(-1)
previousV := int64(-1) if i > 0 {
for _, v := range m.Versions { prev = mm.Migrations[i-1].Version
cur := m.Migrations[v] mm.Migrations[i-1].Next = m.Version
cur.Previous = previousV
m.Migrations[v] = cur
// if a migration exists at prev, its next is now v
if prev, ok := m.Migrations[previousV]; ok {
prev.Next = v
m.Migrations[previousV] = prev
} }
m.Previous = prev
previousV = v
} }
} }