mirror of https://github.com/pressly/goose.git
breaking change: version id is now int64 to accommodate larger date-based version id schemes
parent
9140de5045
commit
517e1701e2
|
@ -28,8 +28,8 @@ func statusRun(cmd *Command, args ...string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect all migrations
|
// collect all migrations
|
||||||
min := 0
|
min := int64(0)
|
||||||
max := (1 << 31) - 1
|
max := int64((1 << 63) - 1)
|
||||||
mm, e := collectMigrations(conf.MigrationsDir, min, max)
|
mm, e := collectMigrations(conf.MigrationsDir, min, max)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
log.Fatal(e)
|
log.Fatal(e)
|
||||||
|
@ -54,7 +54,7 @@ func statusRun(cmd *Command, args ...string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printMigrationStatus(db *sql.DB, version int, script string) {
|
func printMigrationStatus(db *sql.DB, version int64, script string) {
|
||||||
var row MigrationRecord
|
var row MigrationRecord
|
||||||
q := fmt.Sprintf("SELECT tstamp, is_applied FROM goose_db_version WHERE version_id=%d ORDER BY tstamp DESC LIMIT 1", version)
|
q := fmt.Sprintf("SELECT tstamp, is_applied FROM goose_db_version WHERE version_id=%d ORDER BY tstamp DESC LIMIT 1", version)
|
||||||
e := db.QueryRow(q).Scan(&row.TStamp, &row.IsApplied)
|
e := db.QueryRow(q).Scan(&row.TStamp, &row.IsApplied)
|
||||||
|
|
2
down.go
2
down.go
|
@ -38,7 +38,7 @@ func downRun(cmd *Command, args ...string) {
|
||||||
runMigrations(conf, conf.MigrationsDir, previous)
|
runMigrations(conf, conf.MigrationsDir, previous)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPreviousVersion(dirpath string, version int) (previous, earliest int) {
|
func getPreviousVersion(dirpath string, version int64) (previous, earliest int64) {
|
||||||
|
|
||||||
previous = -1
|
previous = -1
|
||||||
earliest = (1 << 31) - 1
|
earliest = (1 << 31) - 1
|
||||||
|
|
45
migrate.go
45
migrate.go
|
@ -16,24 +16,31 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MigrationRecord struct {
|
type MigrationRecord struct {
|
||||||
VersionId int
|
VersionId int64
|
||||||
TStamp time.Time
|
TStamp time.Time
|
||||||
IsApplied bool // was this a result of up() or down()
|
IsApplied bool // was this a result of up() or down()
|
||||||
}
|
}
|
||||||
|
|
||||||
type Migration struct {
|
type Migration struct {
|
||||||
Next int // next version, or -1 if none
|
Next int64 // next version, or -1 if none
|
||||||
Previous int // 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
|
||||||
|
|
||||||
|
// helpers so we can use pkg sort
|
||||||
|
func (s MigrationVersions) Len() int { return len(s) }
|
||||||
|
func (s MigrationVersions) 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] }
|
||||||
|
|
||||||
type MigrationMap struct {
|
type MigrationMap struct {
|
||||||
Versions []int // sorted slice of version keys
|
Versions MigrationVersions // sorted slice of version keys
|
||||||
Migrations map[int]Migration // sources (.sql or .go) keyed by version
|
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 int) {
|
func runMigrations(conf *DBConf, migrationsDir string, target int64) {
|
||||||
|
|
||||||
db, err := sql.Open(conf.Driver, conf.OpenStr)
|
db, err := sql.Open(conf.Driver, conf.OpenStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -85,10 +92,10 @@ func runMigrations(conf *DBConf, migrationsDir string, target int) {
|
||||||
|
|
||||||
// collect all the valid looking migration scripts in the
|
// collect all the valid looking migration scripts in the
|
||||||
// migrations folder, and key them by version
|
// migrations folder, and key them by version
|
||||||
func collectMigrations(dirpath string, current, target int) (mm *MigrationMap, err error) {
|
func collectMigrations(dirpath string, current, target int64) (mm *MigrationMap, err error) {
|
||||||
|
|
||||||
mm = &MigrationMap{
|
mm = &MigrationMap{
|
||||||
Migrations: make(map[int]Migration),
|
Migrations: make(map[int64]Migration),
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the numeric component of each migration,
|
// extract the numeric component of each migration,
|
||||||
|
@ -114,7 +121,7 @@ func collectMigrations(dirpath string, current, target int) (mm *MigrationMap, e
|
||||||
return mm, nil
|
return mm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func versionFilter(v, current, target int) bool {
|
func versionFilter(v, current, target int64) bool {
|
||||||
|
|
||||||
// special case - default target value
|
// special case - default target value
|
||||||
if target < 0 {
|
if target < 0 {
|
||||||
|
@ -132,7 +139,7 @@ func versionFilter(v, current, target int) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MigrationMap) Append(v int, source string) {
|
func (m *MigrationMap) Append(v int64, source string) {
|
||||||
m.Versions = append(m.Versions, v)
|
m.Versions = append(m.Versions, v)
|
||||||
m.Migrations[v] = Migration{
|
m.Migrations[v] = Migration{
|
||||||
Next: -1,
|
Next: -1,
|
||||||
|
@ -142,7 +149,7 @@ func (m *MigrationMap) Append(v int, source string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MigrationMap) Sort(direction bool) {
|
func (m *MigrationMap) Sort(direction bool) {
|
||||||
sort.Ints(m.Versions)
|
sort.Sort(m.Versions)
|
||||||
|
|
||||||
// set direction, and reverse order if need be
|
// set direction, and reverse order if need be
|
||||||
m.Direction = direction
|
m.Direction = direction
|
||||||
|
@ -156,7 +163,7 @@ func (m *MigrationMap) Sort(direction bool) {
|
||||||
// populate next and previous for each migration
|
// populate next and previous for each migration
|
||||||
//
|
//
|
||||||
// work around http://code.google.com/p/go/issues/detail?id=3117
|
// work around http://code.google.com/p/go/issues/detail?id=3117
|
||||||
previousV := -1
|
previousV := int64(-1)
|
||||||
for _, v := range m.Versions {
|
for _, v := range m.Versions {
|
||||||
cur := m.Migrations[v]
|
cur := m.Migrations[v]
|
||||||
cur.Previous = previousV
|
cur.Previous = previousV
|
||||||
|
@ -176,7 +183,7 @@ func (m *MigrationMap) Sort(direction bool) {
|
||||||
// XXX_descriptivename.ext
|
// XXX_descriptivename.ext
|
||||||
// where XXX specifies the version number
|
// where XXX specifies the version number
|
||||||
// and ext specifies the type of migration
|
// and ext specifies the type of migration
|
||||||
func numericComponent(name string) (int, error) {
|
func numericComponent(name string) (int64, error) {
|
||||||
|
|
||||||
base := path.Base(name)
|
base := path.Base(name)
|
||||||
|
|
||||||
|
@ -189,7 +196,7 @@ func numericComponent(name string) (int, error) {
|
||||||
return 0, errors.New("no separator found")
|
return 0, errors.New("no separator found")
|
||||||
}
|
}
|
||||||
|
|
||||||
n, e := strconv.Atoi(base[:idx])
|
n, e := strconv.ParseInt(base[:idx], 10, 64)
|
||||||
if e == nil && n == 0 {
|
if e == nil && n == 0 {
|
||||||
return 0, errors.New("0 is not a valid migration ID")
|
return 0, errors.New("0 is not a valid migration ID")
|
||||||
}
|
}
|
||||||
|
@ -199,7 +206,7 @@ func numericComponent(name string) (int, error) {
|
||||||
|
|
||||||
// retrieve the current version for this DB.
|
// retrieve the current version for this DB.
|
||||||
// Create and initialize the DB version table if it doesn't exist.
|
// Create and initialize the DB version table if it doesn't exist.
|
||||||
func ensureDBVersion(db *sql.DB) (int, error) {
|
func ensureDBVersion(db *sql.DB) (int64, error) {
|
||||||
|
|
||||||
rows, err := db.Query("SELECT version_id, is_applied from goose_db_version ORDER BY tstamp DESC;")
|
rows, err := db.Query("SELECT version_id, is_applied from goose_db_version ORDER BY tstamp DESC;")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -212,7 +219,7 @@ func ensureDBVersion(db *sql.DB) (int, error) {
|
||||||
// whether it has been applied or rolled back.
|
// whether it has been applied or rolled back.
|
||||||
// The first version we find that has been applied is the current version.
|
// The first version we find that has been applied is the current version.
|
||||||
|
|
||||||
toSkip := make([]int, 0)
|
toSkip := make([]int64, 0)
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var row MigrationRecord
|
var row MigrationRecord
|
||||||
|
@ -252,7 +259,7 @@ func createVersionTable(db *sql.DB) error {
|
||||||
|
|
||||||
// create the table and insert an initial value of 0
|
// create the table and insert an initial value of 0
|
||||||
create := `CREATE TABLE goose_db_version (
|
create := `CREATE TABLE goose_db_version (
|
||||||
version_id int NOT NULL,
|
version_id bigint NOT NULL,
|
||||||
is_applied boolean NOT NULL,
|
is_applied boolean NOT NULL,
|
||||||
tstamp timestamp NULL default now(),
|
tstamp timestamp NULL default now(),
|
||||||
PRIMARY KEY(tstamp)
|
PRIMARY KEY(tstamp)
|
||||||
|
@ -271,7 +278,7 @@ func createVersionTable(db *sql.DB) error {
|
||||||
|
|
||||||
// wrapper for ensureDBVersion for callers that don't already have
|
// wrapper for ensureDBVersion for callers that don't already have
|
||||||
// their own DB instance
|
// their own DB instance
|
||||||
func getDBVersion(conf *DBConf) int {
|
func getDBVersion(conf *DBConf) int64 {
|
||||||
|
|
||||||
db, err := sql.Open(conf.Driver, conf.OpenStr)
|
db, err := sql.Open(conf.Driver, conf.OpenStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -21,7 +21,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TemplateData struct {
|
type TemplateData struct {
|
||||||
Version int
|
Version int64
|
||||||
DBDriver string
|
DBDriver string
|
||||||
DBOpen string
|
DBOpen string
|
||||||
Direction string
|
Direction string
|
||||||
|
@ -41,7 +41,7 @@ func directionStr(direction bool) string {
|
||||||
// original .go migration, and execute it via `go run` along
|
// original .go migration, and execute it via `go run` along
|
||||||
// with a main() of our own creation.
|
// with a main() of our own creation.
|
||||||
//
|
//
|
||||||
func runGoMigration(conf *DBConf, path string, version int, direction bool) (int, error) {
|
func runGoMigration(conf *DBConf, path string, version int64, direction bool) (int, error) {
|
||||||
|
|
||||||
// everything gets written to a temp dir, and zapped afterwards
|
// everything gets written to a temp dir, and zapped afterwards
|
||||||
d, e := ioutil.TempDir("", "goose")
|
d, e := ioutil.TempDir("", "goose")
|
||||||
|
@ -83,7 +83,7 @@ func runGoMigration(conf *DBConf, path string, version int, direction bool) (int
|
||||||
// * namespace the Up() and Down() funcs so we can compile several
|
// * namespace the Up() and Down() funcs so we can compile several
|
||||||
// .go migrations into the same binary for execution
|
// .go migrations into the same binary for execution
|
||||||
//
|
//
|
||||||
func writeSubstituted(inpath, outpath string, version int) error {
|
func writeSubstituted(inpath, outpath string, version int64) error {
|
||||||
|
|
||||||
fin, e := os.Open(inpath)
|
fin, e := os.Open(inpath)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
//
|
//
|
||||||
// All statements following an Up or Down directive are grouped together
|
// All statements following an Up or Down directive are grouped together
|
||||||
// until another direction directive is found.
|
// until another direction directive is found.
|
||||||
func runSQLMigration(db *sql.DB, script string, v int, direction bool) (count int, err error) {
|
func runSQLMigration(db *sql.DB, script string, v int64, direction bool) (count int, err error) {
|
||||||
|
|
||||||
txn, err := db.Begin()
|
txn, err := db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -70,7 +70,7 @@ func runSQLMigration(db *sql.DB, script string, v int, direction bool) (count in
|
||||||
|
|
||||||
// Update the version table for the given migration,
|
// Update the version table for the given migration,
|
||||||
// and finalize the transaction.
|
// and finalize the transaction.
|
||||||
func finalizeMigration(txn *sql.Tx, direction bool, v int) error {
|
func finalizeMigration(txn *sql.Tx, direction bool, v int64) error {
|
||||||
|
|
||||||
// XXX: drop goose_db_version table on some minimum version number?
|
// XXX: drop goose_db_version table on some minimum version number?
|
||||||
versionStmt := fmt.Sprintf("INSERT INTO goose_db_version (version_id, is_applied) VALUES (%d, %t);", v, direction)
|
versionStmt := fmt.Sprintf("INSERT INTO goose_db_version (version_id, is_applied) VALUES (%d, %t);", v, direction)
|
||||||
|
|
|
@ -37,7 +37,7 @@ func pendingRun(cmd *Command, args ...string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect all migrations that specify a version later than our current version
|
// collect all migrations that specify a version later than our current version
|
||||||
func collectPendingMigrations(dirpath string, current int) []string {
|
func collectPendingMigrations(dirpath string, current int64) []string {
|
||||||
|
|
||||||
var pendingScripts []string
|
var pendingScripts []string
|
||||||
|
|
||||||
|
|
4
up.go
4
up.go
|
@ -26,9 +26,9 @@ func upRun(cmd *Command, args ...string) {
|
||||||
|
|
||||||
// helper to identify the most recent possible version
|
// helper to identify the most recent possible version
|
||||||
// within a folder of migration scripts
|
// within a folder of migration scripts
|
||||||
func mostRecentVersionAvailable(dirpath string) int {
|
func mostRecentVersionAvailable(dirpath string) int64 {
|
||||||
|
|
||||||
mostRecent := -1
|
mostRecent := int64(-1)
|
||||||
|
|
||||||
filepath.Walk(dirpath, func(name string, info os.FileInfo, err error) error {
|
filepath.Walk(dirpath, func(name string, info os.FileInfo, err error) error {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue