From 70f7950922643a6a97cb23719f2a5f098599758b Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 17 Jun 2024 18:26:13 +0200 Subject: [PATCH 1/7] Created IsExisting(id) . --- api/repositories/gameRepository.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/api/repositories/gameRepository.go b/api/repositories/gameRepository.go index a2b6b24..2227fd4 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,7 @@ 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 } type gameRepository struct { @@ -62,6 +64,15 @@ 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 { From 5cff1d7e6a01c9b011cf8e213fc1f302833bf649 Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 17 Jun 2024 18:28:03 +0200 Subject: [PATCH 2/7] seperated create & update game logic --- api/repositories/gameRepository.go | 45 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/api/repositories/gameRepository.go b/api/repositories/gameRepository.go index 2227fd4..5f6cb2f 100644 --- a/api/repositories/gameRepository.go +++ b/api/repositories/gameRepository.go @@ -14,6 +14,8 @@ type IGameRepository interface { 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 { @@ -76,27 +78,38 @@ func (g gameRepository) IsExisting(id uuid.UUID) bool { // 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) + } +} - if existing != nil { - //If yes, update the existing entry - stmt, err := g.db.Prepare("UPDATE games SET Title=?, StorageLocation=?, Status=?, Url=? WHERE ID = ?") - if err != nil { - return err - } +// 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") + } - return checkResult(stmt.Exec(game.Title, game.StorageLocation, game.Status, game.Url, game.ID)) - } - } else { + stmt, err := g.db.Prepare("UPDATE games SET Title=?, StorageLocation=?, Status=?, Url=? WHERE ID = ?") + if err != nil { + return err + } + + return checkResult(stmt.Exec(game.Title, game.StorageLocation, game.Status, game.Url, 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) VALUES (?,?,?,?,?,?)") if err != nil { return err From 58a504ffba6954722f66a1c2e2acd87ae33528cc Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 17 Jun 2024 18:28:53 +0200 Subject: [PATCH 3/7] gameRepository use errors.Is --- api/repositories/gameRepository.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/repositories/gameRepository.go b/api/repositories/gameRepository.go index 5f6cb2f..22d7311 100644 --- a/api/repositories/gameRepository.go +++ b/api/repositories/gameRepository.go @@ -58,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) if err != nil { - if err == sql.ErrNoRows { + if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err From 8c604fd56eaeb4d3bff7b47c2d2835e6f44dfab1 Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 17 Jun 2024 18:29:08 +0200 Subject: [PATCH 4/7] changed comments --- api/repositories/gameRepository.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/repositories/gameRepository.go b/api/repositories/gameRepository.go index 22d7311..8f23d68 100644 --- a/api/repositories/gameRepository.go +++ b/api/repositories/gameRepository.go @@ -28,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) @@ -38,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 { From 2cf87648b31ec18fcec0eb6515aa31f227eddc20 Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 17 Jun 2024 18:30:38 +0200 Subject: [PATCH 5/7] updated tests --- api/tests/gameRepository_test.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/api/tests/gameRepository_test.go b/api/tests/gameRepository_test.go index 42e1d16..0fc936f 100644 --- a/api/tests/gameRepository_test.go +++ b/api/tests/gameRepository_test.go @@ -130,7 +130,7 @@ func Test_Create_Game_With_Id_Should_Succeed(t *testing.T) { Owner: "MockOwner", } - 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") @@ -177,12 +177,9 @@ func Test_Save_Existing_Game_Should_Succeed(t *testing.T) { Url: "MockUrl", Owner: "MockOwner", } - - mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM games WHERE ID = ?")). - WithArgs(id).WillReturnRows( - sqlmock.NewRows([]string{"Id", "Title", "StorageLocation", "Status", "Url", "Owner"}). - 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=? WHERE ID = ?")) From c5cb492fd1957487a7d3426f2c8ae36ce944293b Mon Sep 17 00:00:00 2001 From: Kai Date: Tue, 18 Jun 2024 14:14:05 +0200 Subject: [PATCH 6/7] fileName --- api/repositories/gameRepository.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/repositories/gameRepository.go b/api/repositories/gameRepository.go index 1a93a2d..5c81e25 100644 --- a/api/repositories/gameRepository.go +++ b/api/repositories/gameRepository.go @@ -92,12 +92,12 @@ func (g gameRepository) Update(game *models.Game) error { return errors.New("cannot update game, game is nil") } - stmt, err := g.db.Prepare("UPDATE games SET Title=?, StorageLocation=?, Status=?, Url=? WHERE ID = ?") + 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.ID)) + return checkResult(stmt.Exec(game.Title, game.StorageLocation, game.Status, game.Url, game.ID, game.FileName)) } // Create inserts a new game to the games database @@ -110,7 +110,7 @@ func (g gameRepository) Create(game *models.Game) error { game.ID = uuid.New() } - stmt, err := g.db.Prepare("INSERT INTO games (ID, Title, StorageLocation, Status, Url, Owner) VALUES (?,?,?,?,?,?)") + stmt, err := g.db.Prepare("INSERT INTO games (ID, Title, StorageLocation, Status, Url, Owner, FileName) VALUES (?,?,?,?,?,?,?)") if err != nil { return err } From a81ede91c3c16f20bfe3543cef23c8c3dadcb911 Mon Sep 17 00:00:00 2001 From: Kai Date: Tue, 18 Jun 2024 14:14:17 +0200 Subject: [PATCH 7/7] updated tests --- api/tests/gameRepository_test.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/api/tests/gameRepository_test.go b/api/tests/gameRepository_test.go index a99cb8d..fa46781 100644 --- a/api/tests/gameRepository_test.go +++ b/api/tests/gameRepository_test.go @@ -180,16 +180,10 @@ func Test_Save_Existing_Game_Should_Succeed(t *testing.T) { Owner: "MockOwner", FileName: "TestFile.nes", } - + mock.ExpectQuery(regexp.QuoteMeta("SELECT id FROM games WHERE ID = ?")). WithArgs(id).WillReturnRows(sqlmock.NewRows([]string{"Id"}).AddRow(id)) - 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.ExpectPrepare(regexp. QuoteMeta("UPDATE games SET Title=?, StorageLocation=?, Status=?, Url=?, FileName=? WHERE ID = ?"))