diff --git a/datastore/datastore.go b/datastore/datastore.go index b18c012..94ff786 100644 --- a/datastore/datastore.go +++ b/datastore/datastore.go @@ -7,8 +7,9 @@ import ( // A datastore access point (in PostgreSQL) type Datastore struct { - Users models.UsersService - dbh modl.SqlExecutor + Users models.UsersService + Genera models.GeneraService + dbh modl.SqlExecutor } // NewDatastore creates a new client for accessing the datastore (in PostgreSQL). @@ -20,11 +21,13 @@ func NewDatastore(dbh modl.SqlExecutor) *Datastore { d := &Datastore{dbh: dbh} d.Users = &usersStore{d} + d.Genera = &generaStore{d} return d } func NewMockDatastore() *Datastore { return &Datastore{ - Users: &models.MockUsersService{}, + Users: &models.MockUsersService{}, + Genera: &models.MockGeneraService{}, } } diff --git a/datastore/genera.go b/datastore/genera.go new file mode 100644 index 0000000..260ff07 --- /dev/null +++ b/datastore/genera.go @@ -0,0 +1,47 @@ +package datastore + +import ( + "strings" + + "github.com/thermokarst/bactdb/models" +) + +func init() { + DB.AddTableWithName(models.Genus{}, "genera").SetKeys(true, "Id") +} + +type generaStore struct { + *Datastore +} + +func (s *generaStore) Get(id int64) (*models.Genus, error) { + var genus []*models.Genus + if err := s.dbh.Select(&genus, `SELECT * FROM genera WHERE id=$1;`, id); err != nil { + return nil, err + } + if len(genus) == 0 { + return nil, models.ErrGenusNotFound + } + return genus[0], nil +} + +func (s *generaStore) Create(genus *models.Genus) (bool, error) { + if err := s.dbh.Insert(genus); err != nil { + if strings.Contains(err.Error(), `violates unique constraint "genus_idx"`) { + return false, err + } + } + return true, nil +} + +func (s *generaStore) List(opt *models.GenusListOptions) ([]*models.Genus, error) { + if opt == nil { + opt = &models.GenusListOptions{} + } + var genera []*models.Genus + err := s.dbh.Select(&genera, `SELECT * FROM genera LIMIT $1 OFFSET $2;`, opt.PerPageOrDefault(), opt.Offset()) + if err != nil { + return nil, err + } + return genera, nil +} diff --git a/datastore/genera_test.go b/datastore/genera_test.go new file mode 100644 index 0000000..5eebae2 --- /dev/null +++ b/datastore/genera_test.go @@ -0,0 +1,81 @@ +package datastore + +import ( + "reflect" + "testing" + + "github.com/thermokarst/bactdb/models" +) + +func TestGeneraStore_Get_db(t *testing.T) { + want := &models.Genus{Id: 1, GenusName: "Test Genus"} + + tx, _ := DB.Begin() + defer tx.Rollback() + + // Test on a clean database + tx.Exec(`DELETE FROM genera;`) + if err := tx.Insert(want); err != nil { + t.Fatal(err) + } + + d := NewDatastore(tx) + genus, err := d.Genera.Get(1) + if err != nil { + t.Fatal(err) + } + + normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt) + if !reflect.DeepEqual(genus, want) { + t.Errorf("got genus %+v, want %+v", genus, want) + } +} + +func TestGeneraStore_Create_db(t *testing.T) { + genus := &models.Genus{Id: 1, GenusName: "Test Genus"} + + tx, _ := DB.Begin() + defer tx.Rollback() + + // Test on a clean database + tx.Exec(`DELETE FROM genera;`) + + d := NewDatastore(tx) + created, err := d.Genera.Create(genus) + if err != nil { + t.Fatal(err) + } + + if !created { + t.Error("!created") + } + if genus.Id == 0 { + t.Error("want nonzero genus.Id after submitting") + } +} + +func TestGeneraStore_List_db(t *testing.T) { + want := []*models.Genus{{Id: 1, GenusName: "Test Genus"}} + + tx, _ := DB.Begin() + defer tx.Rollback() + + // Test on a clean database + tx.Exec(`DELETE FROM genera;`) + if err := tx.Insert(want[0]); err != nil { + t.Fatal(err) + } + + d := NewDatastore(tx) + genera, err := d.Genera.List(&models.GenusListOptions{ListOptions: models.ListOptions{Page: 1, PerPage: 10}}) + if err != nil { + t.Fatal(err) + } + + for _, g := range want { + normalizeTime(&g.CreatedAt, &g.UpdatedAt, &g.DeletedAt) + } + if !reflect.DeepEqual(genera, want) { + t.Errorf("got genera %+v, want %+v", genera, want) + } +} diff --git a/datastore/migrations/00002_AddGenera_down.sql b/datastore/migrations/00002_AddGenera_down.sql new file mode 100644 index 0000000..672e1fc --- /dev/null +++ b/datastore/migrations/00002_AddGenera_down.sql @@ -0,0 +1,5 @@ +-- bactdb +-- Matthew R Dillon + +DROP TABLE genera; + diff --git a/datastore/migrations/00002_AddGenera_up.sql b/datastore/migrations/00002_AddGenera_up.sql new file mode 100644 index 0000000..a9e0f5c --- /dev/null +++ b/datastore/migrations/00002_AddGenera_up.sql @@ -0,0 +1,19 @@ +-- bactdb +-- Matthew R Dillon + +CREATE TABLE genera ( + id BIGSERIAL NOT NULL, + genusname CHARACTER VARYING(100), + + created_at TIMESTAMP WITH TIME ZONE, + updated_at TIMESTAMP WITH TIME ZONE, + deleted_at TIMESTAMP WITH TIME ZONE, + + CONSTRAINT genus_pkey PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX genusname_idx + ON genera + USING btree + (genusname COLLATE pg_catalog."default"); +