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 {