diff --git a/api/repositories/gameRepository.go b/api/repositories/gameRepository.go index 382611e..6667dc0 100644 --- a/api/repositories/gameRepository.go +++ b/api/repositories/gameRepository.go @@ -3,6 +3,7 @@ package repositories import ( "api/models" "database/sql" + "errors" "github.com/google/uuid" ) @@ -12,6 +13,9 @@ type IGameRepository interface { Delete(id uuid.UUID) error FindAllByOwner(owner string) ([]models.Game, error) ReadOwner(id uuid.UUID) (string, error) + IsExisting(id uuid.UUID) bool + Update(game *models.Game) error + Create(game *models.Game) error } type gameRepository struct { @@ -24,7 +28,7 @@ func GameRepository(db *sql.DB) IGameRepository { } } -// Read the owner of a specific game or empty if the game has not been found +// ReadOwner Reads the owner of a specific game or empty if the game has not been found func (g gameRepository) ReadOwner(id uuid.UUID) (string, error) { var owner string err := g.db.QueryRow("SELECT Owner FROM games WHERE ID = ?", id).Scan(&owner) @@ -34,7 +38,7 @@ func (g gameRepository) ReadOwner(id uuid.UUID) (string, error) { return owner, nil } -// FindAll returns all games of a specific owner from the database or (nil, err) if an error occurred. +// FindAllByOwner returns all games of a specific owner from the database or (nil, err) if an error occurred. func (g gameRepository) FindAllByOwner(owner string) ([]models.Game, error) { stmt, err := g.db.Prepare("SELECT * FROM games WHERE owner = ?") if err != nil { @@ -54,7 +58,7 @@ func (g gameRepository) FindByID(id uuid.UUID) (*models.Game, error) { err := g.db.QueryRow("SELECT * FROM games WHERE ID = ?", id). Scan(&game.ID, &game.Title, &game.StorageLocation, &game.Status, &game.Url, &game.Owner, &game.FileName) if err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err @@ -62,30 +66,50 @@ func (g gameRepository) FindByID(id uuid.UUID) (*models.Game, error) { return &game, nil } +// IsExisting will return true if no game with the given id has been found. +func (g gameRepository) IsExisting(id uuid.UUID) bool { + var game models.Game + err := g.db.QueryRow("SELECT id FROM games WHERE ID = ?", id). + Scan(&game.ID) + + return !errors.Is(err, sql.ErrNoRows) +} + // Save will update the database entry if the game is already in the database. // If not it will create an uuid and save it in the database. func (g gameRepository) Save(game *models.Game) error { - if game.ID != uuid.Nil { - //Check if uuid is already in database - existing, err := g.FindByID(game.ID) - if err != nil { - return err - } + if game.ID == uuid.Nil || !g.IsExisting(game.ID) { + return g.Create(game) + } else { + return g.Update(game) + } +} + +// Update updates an existing game. It doesn't check if the game is already existing or not. +// If you are not sure that the game is already existing you should use Save. +func (g gameRepository) Update(game *models.Game) error { + if game == nil { + return errors.New("cannot update game, game is nil") + } - if existing != nil { - //If yes, update the existing entry - stmt, err := g.db.Prepare("UPDATE games SET Title=?, StorageLocation=?, Status=?, Url=?, FileName=? WHERE ID = ?") - if err != nil { - return err - } + stmt, err := g.db.Prepare("UPDATE games SET Title=?, StorageLocation=?, Status=?, Url=?, FileName=? WHERE ID = ?") + if err != nil { + return err + } - return checkResult(stmt.Exec(game.Title, game.StorageLocation, game.Status, game.Url, game.FileName, game.ID)) - } - } else { + return checkResult(stmt.Exec(game.Title, game.StorageLocation, game.Status, game.Url, game.FileName, game.ID,)) +} + +// Create inserts a new game to the games database +func (g gameRepository) Create(game *models.Game) error { + if game == nil { + return errors.New("cannot create new game, game is nil") + } + + if game.ID == uuid.Nil { game.ID = uuid.New() } - //If not create a new one stmt, err := g.db.Prepare("INSERT INTO games (ID, Title, StorageLocation, Status, Url, Owner, FileName) VALUES (?,?,?,?,?,?,?)") if err != nil { return err diff --git a/api/tests/gameRepository_test.go b/api/tests/gameRepository_test.go index 99be84f..165159e 100644 --- a/api/tests/gameRepository_test.go +++ b/api/tests/gameRepository_test.go @@ -132,7 +132,7 @@ func Test_Create_Game_With_Id_Should_Succeed(t *testing.T) { FileName: "TestFile.nes", } - mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM games WHERE ID = ?")). + mock.ExpectQuery(regexp.QuoteMeta("SELECT id FROM games WHERE ID = ?")). WithArgs(id).WillReturnError(sql.ErrNoRows) mock.ExpectPrepare("INSERT INTO games") @@ -181,11 +181,8 @@ func Test_Save_Existing_Game_Should_Succeed(t *testing.T) { FileName: "TestFile.nes", } - mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM games WHERE ID = ?")). - WithArgs(id).WillReturnRows( - sqlmock.NewRows([]string{"Id", "Title", "StorageLocation", "Status", "Url", "Owner", "FileName"}). - AddRow(id, "", "", "", "", "", ""), - ) + mock.ExpectQuery(regexp.QuoteMeta("SELECT id FROM games WHERE ID = ?")). + WithArgs(id).WillReturnRows(sqlmock.NewRows([]string{"Id"}).AddRow(id)) mock.ExpectPrepare(regexp. QuoteMeta("UPDATE games SET Title=?, StorageLocation=?, Status=?, Url=?, FileName=? WHERE ID = ?"))