From 8fa594e3f0a1d82aec6462aafd7e58da051a130b Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 6 Oct 2014 17:09:41 -0800 Subject: [PATCH] =?UTF-8?q?DB=20Migrations=20Replacing=20modl=E2=80=99s=20?= =?UTF-8?q?built-in=20table=20creation=20and=20removal=20with=20manual=20m?= =?UTF-8?q?igrations.=20Thanks=20to=20@DavidHuie=20for=20gomigrate!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/bactdb/bactdb.go | 6 ++-- datastore/db.go | 32 ++++++++++++++------ datastore/db_test.go | 5 +-- datastore/migrations/00001_AddUsers_down.sql | 5 +++ datastore/migrations/00001_AddUsers_up.sql | 19 ++++++++++++ datastore/users.go | 3 -- 6 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 datastore/migrations/00001_AddUsers_down.sql create mode 100644 datastore/migrations/00001_AddUsers_up.sql diff --git a/cmd/bactdb/bactdb.go b/cmd/bactdb/bactdb.go index 2c563eb..63a228f 100644 --- a/cmd/bactdb/bactdb.go +++ b/cmd/bactdb/bactdb.go @@ -117,8 +117,10 @@ The options are: } datastore.Connect() + migrationsPath := "./datastore/migrations" + if *drop { - datastore.Drop() + datastore.Drop(migrationsPath) } - datastore.Create() + datastore.Create(migrationsPath) } diff --git a/datastore/db.go b/datastore/db.go index b2f4b96..e2d1b4d 100644 --- a/datastore/db.go +++ b/datastore/db.go @@ -5,6 +5,7 @@ import ( "os" "sync" + "github.com/DavidHuie/gomigrate" "github.com/jmoiron/modl" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" @@ -37,21 +38,32 @@ func Connect() { var createSQL []string // Create the database schema. It calls log.Fatal if it encounters an error. -func Create() { - if err := DB.CreateTablesIfNotExists(); err != nil { - log.Fatal("Error creating tables: ", err) +func Create(path string) { + migrator, err := gomigrate.NewMigrator(DB.Dbx.DB, gomigrate.Postgres{}, path) + if err != nil { + log.Fatal("Error initializing migrations: ", err) } - for _, query := range createSQL { - if _, err := DB.Exec(query); err != nil { - log.Fatalf("Error running query %q: %s", query, err) - } + + pwd, err := os.Getwd() + log.Print("current path: ", pwd) + + err = migrator.Migrate() + if err != nil { + log.Fatal("Error applying migrations: ", err) } } // Drop the database schema -func Drop() { - // TODO(mrd): raise errors. - DB.DropTables() +func Drop(path string) { + migrator, err := gomigrate.NewMigrator(DB.Dbx.DB, gomigrate.Postgres{}, path) + if err != nil { + log.Fatal("Error initializing migrations: ", err) + } + + err = migrator.RollbackAll() + if err != nil { + log.Fatal("Error rolling back migrations: ", err) + } } // transact calls fn in a DB transaction. If dbh is a transaction, then it just calls diff --git a/datastore/db_test.go b/datastore/db_test.go index c8103e0..e19317e 100644 --- a/datastore/db_test.go +++ b/datastore/db_test.go @@ -21,6 +21,7 @@ func init() { // Reset DB Connect() - Drop() - Create() + migrationsPath := "./migrations" + Drop(migrationsPath) + Create(migrationsPath) } diff --git a/datastore/migrations/00001_AddUsers_down.sql b/datastore/migrations/00001_AddUsers_down.sql new file mode 100644 index 0000000..5bc15a4 --- /dev/null +++ b/datastore/migrations/00001_AddUsers_down.sql @@ -0,0 +1,5 @@ +-- bactdb +-- Matthew R Dillon + +DROP TABLE users; + diff --git a/datastore/migrations/00001_AddUsers_up.sql b/datastore/migrations/00001_AddUsers_up.sql new file mode 100644 index 0000000..9dd8907 --- /dev/null +++ b/datastore/migrations/00001_AddUsers_up.sql @@ -0,0 +1,19 @@ +-- bactdb +-- Matthew R Dillon + +CREATE TABLE users ( + id BIGSERIAL NOT NULL, + username CHARACTER VARYING(100), + + createdat TIMESTAMP WITH TIME ZONE, + updatedat TIMESTAMP WITH TIME ZONE, + deletedat TIMESTAMP WITH TIME ZONE, + + CONSTRAINT users_pkey PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX username_idx + ON users + USING btree + (username COLLATE pg_catalog."default"); + diff --git a/datastore/users.go b/datastore/users.go index ee233a4..fdacc6c 100644 --- a/datastore/users.go +++ b/datastore/users.go @@ -12,9 +12,6 @@ import ( func init() { DB.AddTableWithName(models.User{}, "users").SetKeys(true, "Id") - createSQL = append(createSQL, - `CREATE UNIQUE INDEX username_idx ON users (username);`, - ) } type usersStore struct {