From 1d402b32ffcc30d66ffa02885e3b3ed32e9b0b11 Mon Sep 17 00:00:00 2001 From: Nicholas Duffy Date: Wed, 3 May 2017 17:41:20 -0600 Subject: [PATCH] Add Redshift driver support Redshift can be accessed and `up`/`down` SQL executed with the `pq` library by default, however, the `createVersionTableSql` of the `PostgresDialect` is not compatible with Redshift due to the `serial` datatype and `now()` default on. This PR creates a new Redshift dialect. The dialect still uses the `pq` library and only updates the SQL in `createVersionTableSql` to be compatible with Redshift. Closes #32. --- README.md | 1 + cmd/goose/main.go | 8 ++++++-- dialect.go | 31 +++++++++++++++++++++++++++++++ example/migrations-go/cmd/main.go | 7 ++++++- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1832072..e140701 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Examples: goose postgres "user=postgres dbname=postgres sslmode=disable" up goose mysql "user:password@/dbname" down goose sqlite3 ./foo.db status + goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" create init sql Options: -dir string diff --git a/cmd/goose/main.go b/cmd/goose/main.go index 94527a7..407b889 100644 --- a/cmd/goose/main.go +++ b/cmd/goose/main.go @@ -46,7 +46,7 @@ func main() { driver, dbstring, command := args[0], args[1], args[2] switch driver { - case "postgres", "mysql", "sqlite3": + case "postgres", "mysql", "sqlite3", "redshift": if err := goose.SetDialect(driver); err != nil { log.Fatal(err) } @@ -60,6 +60,10 @@ func main() { default: } + if driver == "redshift" { + driver = "postgres" + } + db, err := sql.Open(driver, dbstring) if err != nil { log.Fatalf("-dbstring=%q: %v\n", dbstring, err) @@ -88,7 +92,7 @@ Examples: goose postgres "user=postgres dbname=postgres sslmode=disable" up goose mysql "user:password@/dbname" down goose sqlite3 ./foo.db status - goose postgres "user=postgres dbname=postgres sslmode=disable" create init sql + goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" create init sql Options: ` diff --git a/dialect.go b/dialect.go index 536152b..8237849 100644 --- a/dialect.go +++ b/dialect.go @@ -27,6 +27,8 @@ func SetDialect(d string) error { dialect = &MySqlDialect{} case "sqlite3": dialect = &Sqlite3Dialect{} + case "redshift": + dialect = &RedshiftDialect{} default: return fmt.Errorf("%q: unknown dialect", d) } @@ -119,3 +121,32 @@ func (m Sqlite3Dialect) dbVersionQuery(db *sql.DB) (*sql.Rows, error) { return rows, err } + +//////////////////////////// +// Redshift +//////////////////////////// + +type RedshiftDialect struct{} + +func (rs RedshiftDialect) createVersionTableSql() string { + return `CREATE TABLE goose_db_version ( + id integer NOT NULL identity(1, 1), + version_id bigint NOT NULL, + is_applied boolean NOT NULL, + tstamp timestamp NULL default sysdate, + PRIMARY KEY(id) + );` +} + +func (rs RedshiftDialect) insertVersionSql() string { + return "INSERT INTO goose_db_version (version_id, is_applied) VALUES ($1, $2);" +} + +func (rs RedshiftDialect) dbVersionQuery(db *sql.DB) (*sql.Rows, error) { + rows, err := db.Query("SELECT version_id, is_applied from goose_db_version ORDER BY id DESC") + if err != nil { + return nil, err + } + + return rows, err +} diff --git a/example/migrations-go/cmd/main.go b/example/migrations-go/cmd/main.go index 797b471..a7d3ce9 100644 --- a/example/migrations-go/cmd/main.go +++ b/example/migrations-go/cmd/main.go @@ -40,7 +40,7 @@ func main() { driver, dbstring, command := args[0], args[1], args[2] switch driver { - case "postgres", "mysql", "sqlite3": + case "postgres", "mysql", "sqlite3", "redshift": if err := goose.SetDialect(driver); err != nil { log.Fatal(err) } @@ -54,6 +54,10 @@ func main() { default: } + if driver == "redshift" { + driver = "postgres" + } + db, err := sql.Open(driver, dbstring) if err != nil { log.Fatalf("-dbstring=%q: %v\n", dbstring, err) @@ -77,6 +81,7 @@ Examples: goose postgres "user=postgres dbname=postgres sslmode=disable" up goose mysql "user:password@/dbname" down goose sqlite3 ./foo.db status + goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" create init sql Options: `