mirror of https://github.com/pressly/goose.git
parent
43bbf73c63
commit
11a1b26516
41
README.md
41
README.md
|
@ -37,38 +37,43 @@ Drivers:
|
||||||
redshift
|
redshift
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
up Migrate the DB to the most recent version available
|
up Migrate the DB to the most recent version available
|
||||||
up-to VERSION Migrate the DB to a specific VERSION
|
up-to VERSION Migrate the DB to a specific VERSION
|
||||||
down Roll back the version by 1
|
down Roll back the version by 1
|
||||||
down-to VERSION Roll back to a specific VERSION
|
down-to VERSION Roll back to a specific VERSION
|
||||||
redo Re-run the latest migration
|
redo Re-run the latest migration
|
||||||
status Dump the migration status for the current DB
|
status Dump the migration status for the current DB
|
||||||
version Print the current version of the database
|
version Print the current version of the database
|
||||||
create Creates a blank migration template
|
create NAME [sql|go] Creates new migration file with next version
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-dir string
|
-dir string
|
||||||
directory with migration files (default ".")
|
directory with migration files (default ".")
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
goose postgres "user=postgres dbname=postgres sslmode=disable" up
|
|
||||||
goose mysql "user:password@/dbname" down
|
|
||||||
goose sqlite3 ./foo.db status
|
goose sqlite3 ./foo.db status
|
||||||
goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" create init sql
|
goose sqlite3 ./foo.db create init sql
|
||||||
|
goose sqlite3 ./foo.db create add_some_column sql
|
||||||
|
goose sqlite3 ./foo.db create fetch_user_data go
|
||||||
|
goose sqlite3 ./foo.db up
|
||||||
|
|
||||||
|
goose postgres "user=postgres dbname=postgres sslmode=disable" status
|
||||||
|
goose mysql "user:password@/dbname" status
|
||||||
|
goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" status
|
||||||
```
|
```
|
||||||
## create
|
## create
|
||||||
|
|
||||||
Create a new Go migration.
|
Create a new SQL migration.
|
||||||
|
|
||||||
$ goose create AddSomeColumns
|
$ goose create add_some_column sql
|
||||||
$ goose: created db/migrations/20130106093224_AddSomeColumns.go
|
$ Created new file: 00001_add_some_column.sql
|
||||||
|
|
||||||
Edit the newly created script to define the behavior of your migration.
|
Edit the newly created file to define the behavior of your migration.
|
||||||
|
|
||||||
You can also create an SQL migration:
|
You can also create a Go migration, if you then invoke it with [your own goose binary](#go-migrations):
|
||||||
|
|
||||||
$ goose create AddSomeColumns sql
|
$ goose create fetch_user_data go
|
||||||
$ goose: created db/migrations/20130106093224_AddSomeColumns.sql
|
$ Created new file: 00002_fetch_user_data.go
|
||||||
|
|
||||||
## up
|
## up
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/pressly/goose"
|
"github.com/pressly/goose"
|
||||||
|
|
||||||
|
// Init DB drivers.
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
@ -95,23 +96,28 @@ Drivers:
|
||||||
redshift
|
redshift
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
goose postgres "user=postgres dbname=postgres sslmode=disable" up
|
|
||||||
goose mysql "user:password@/dbname" down
|
|
||||||
goose sqlite3 ./foo.db status
|
goose sqlite3 ./foo.db status
|
||||||
goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" create init sql
|
goose sqlite3 ./foo.db create init sql
|
||||||
|
goose sqlite3 ./foo.db create add_some_column sql
|
||||||
|
goose sqlite3 ./foo.db create fetch_user_data go
|
||||||
|
goose sqlite3 ./foo.db up
|
||||||
|
|
||||||
|
goose postgres "user=postgres dbname=postgres sslmode=disable" status
|
||||||
|
goose mysql "user:password@/dbname" status
|
||||||
|
goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" status
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
`
|
`
|
||||||
|
|
||||||
usageCommands = `
|
usageCommands = `
|
||||||
Commands:
|
Commands:
|
||||||
up Migrate the DB to the most recent version available
|
up Migrate the DB to the most recent version available
|
||||||
up-to VERSION Migrate the DB to a specific VERSION
|
up-to VERSION Migrate the DB to a specific VERSION
|
||||||
down Roll back the version by 1
|
down Roll back the version by 1
|
||||||
down-to VERSION Roll back to a specific VERSION
|
down-to VERSION Roll back to a specific VERSION
|
||||||
redo Re-run the latest migration
|
redo Re-run the latest migration
|
||||||
status Dump the migration status for the current DB
|
status Dump the migration status for the current DB
|
||||||
version Print the current version of the database
|
version Print the current version of the database
|
||||||
create Creates a blank migration template
|
create NAME [sql|go] Creates new migration file with next version
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
76
create.go
76
create.go
|
@ -3,16 +3,86 @@ package goose
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create writes a new blank migration file.
|
// Create writes a new blank migration file.
|
||||||
func Create(db *sql.DB, dir, name, migrationType string) error {
|
func Create(db *sql.DB, dir, name, migrationType string) error {
|
||||||
path, err := CreateMigration(name, migrationType, dir, time.Now())
|
migrations, err := CollectMigrations(dir, minVersion, maxVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println(fmt.Sprintf("Created %s migration at %s", migrationType, path))
|
|
||||||
|
|
||||||
|
// Initial version.
|
||||||
|
version := "00001"
|
||||||
|
|
||||||
|
if last, err := migrations.Last(); err == nil {
|
||||||
|
version = fmt.Sprintf("%05v", last.Version+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := fmt.Sprintf("%v_%v.%v", version, name, migrationType)
|
||||||
|
|
||||||
|
fpath := filepath.Join(dir, filename)
|
||||||
|
tmpl := sqlMigrationTemplate
|
||||||
|
if migrationType == "go" {
|
||||||
|
tmpl = goSQLMigrationTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := writeTemplateToFile(fpath, tmpl, version)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Created new file: %s\n", path)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeTemplateToFile(path string, t *template.Template, version string) (string, error) {
|
||||||
|
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||||
|
return "", fmt.Errorf("failed to create file: %v already exists", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
err = t.Execute(f, version)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var sqlMigrationTemplate = template.Must(template.New("goose.sql-migration").Parse(`-- +goose Up
|
||||||
|
-- SQL in this section is executed when the migration is applied.
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- SQL in this section is executed when the migration is rolled back.
|
||||||
|
`))
|
||||||
|
|
||||||
|
var goSQLMigrationTemplate = template.Must(template.New("goose.go-migration").Parse(`package migration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"github.com/pressly/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
goose.AddMigration(Up{{.}}, Down{{.}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Up{{.}}(tx *sql.Tx) error {
|
||||||
|
// This code is executed when the migration is applied.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Down{{.}}(tx *sql.Tx) error {
|
||||||
|
// This code is executed when the migration is rolled back.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
|
55
migration.go
55
migration.go
|
@ -8,7 +8,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,27 +101,6 @@ func NumericComponent(name string) (int64, error) {
|
||||||
return n, e
|
return n, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateMigration creates a migration.
|
|
||||||
func CreateMigration(name, migrationType, dir string, t time.Time) (path string, err error) {
|
|
||||||
|
|
||||||
if migrationType != "go" && migrationType != "sql" {
|
|
||||||
return "", errors.New("migration type must be 'go' or 'sql'")
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp := t.Format("20060102150405")
|
|
||||||
filename := fmt.Sprintf("%v_%v.%v", timestamp, name, migrationType)
|
|
||||||
|
|
||||||
fpath := filepath.Join(dir, filename)
|
|
||||||
tmpl := sqlMigrationTemplate
|
|
||||||
if migrationType == "go" {
|
|
||||||
tmpl = goSQLMigrationTemplate
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err = writeTemplateToFile(fpath, tmpl, timestamp)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// FinalizeMigration updates the version table for the given migration,
|
// FinalizeMigration updates the version table for the given migration,
|
||||||
// and finalize the transaction.
|
// and finalize the transaction.
|
||||||
func FinalizeMigration(tx *sql.Tx, direction bool, v int64) error {
|
func FinalizeMigration(tx *sql.Tx, direction bool, v int64) error {
|
||||||
|
@ -136,36 +114,3 @@ func FinalizeMigration(tx *sql.Tx, direction bool, v int64) error {
|
||||||
|
|
||||||
return tx.Commit()
|
return tx.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
var sqlMigrationTemplate = template.Must(template.New("goose.sql-migration").Parse(`
|
|
||||||
-- +goose Up
|
|
||||||
-- SQL in section 'Up' is executed when this migration is applied
|
|
||||||
|
|
||||||
|
|
||||||
-- +goose Down
|
|
||||||
-- SQL section 'Down' is executed when this migration is rolled back
|
|
||||||
|
|
||||||
`))
|
|
||||||
|
|
||||||
var goSQLMigrationTemplate = template.Must(template.New("goose.go-migration").Parse(`
|
|
||||||
package migration
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"github.com/pressly/goose"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
goose.AddMigration(Up{{.}}, Down{{.}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Up{{.}} updates the database to the new requirements
|
|
||||||
func Up{{.}}(tx *sql.Tx) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Down{{.}} should send the database back to the state it was from before Up was ran
|
|
||||||
func Down{{.}}(tx *sql.Tx) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
`))
|
|
||||||
|
|
40
util.go
40
util.go
|
@ -1,40 +0,0 @@
|
||||||
package goose
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
// common routines
|
|
||||||
|
|
||||||
func writeTemplateToFile(path string, t *template.Template, data interface{}) (string, error) {
|
|
||||||
f, e := os.Create(path)
|
|
||||||
if e != nil {
|
|
||||||
return "", e
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
e = t.Execute(f, data)
|
|
||||||
if e != nil {
|
|
||||||
return "", e
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.Name(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyFile(dst, src string) (int64, error) {
|
|
||||||
sf, err := os.Open(src)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer sf.Close()
|
|
||||||
|
|
||||||
df, err := os.Create(dst)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer df.Close()
|
|
||||||
|
|
||||||
return io.Copy(df, sf)
|
|
||||||
}
|
|
Loading…
Reference in New Issue