diff --git a/server/storage/database.go b/server/storage/database.go index 5816d57cbc..565369654b 100644 --- a/server/storage/database.go +++ b/server/storage/database.go @@ -39,12 +39,12 @@ func NewMySQLStorage(db *sql.DB) *MySQLStorage { // UpdateCurrent updates multiple TUF records in a single transaction. // Always insert a new row. The unique constraint will ensure there is only ever func (db *MySQLStorage) UpdateCurrent(gun, update MetaUpdate) error { - insertStmt := "INSERT INTO `tuf_files` (`gun`, `role`, `version`, `data`) VALUES (?,?,?,?) ;" + insertStmt := "INSERT INTO `tuf_files` (`gun`, `role`, `version`, `data`) VALUES (?,?,?,?) WHERE (SELECT count(*) FROM `tuf_files` WHERE `gun`=? AND `role`=? AND `version`>=?) = 0;" // attempt to insert. Due to race conditions with the check this could fail. // That's OK, we're doing first write wins. The client will be messaged it // needs to rebase. - _, err := db.Exec(insertStmt, gun, update.Role, update.Version, update.Data) + _, err := db.Exec(insertStmt, gun, update.Role, update.Version, update.Data, gun, update.Role, update.Version) if err != nil { if err, ok := err.(*mysql.MySQLError); ok { if err.Number == 1022 { // duplicate key error @@ -60,14 +60,14 @@ func (db *MySQLStorage) UpdateCurrent(gun, update MetaUpdate) error { // UpdateMany atomically updates many TUF records in a single transaction func (db *MySQLStorage) UpdateMany(gun string, updates []MetaUpdate) error { - insertStmt := "INSERT INTO `tuf_files` (`gun`, `role`, `version`, `data`) VALUES (?,?,?,?) ;" + insertStmt := "INSERT INTO `tuf_files` (`gun`, `role`, `version`, `data`) VALUES (?,?,?,?) WHERE (SELECT count(*) FROM `tuf_files` WHERE `gun`=? AND `role`=? AND `version`>=?) = 0;" tx, err := db.Begin() for _, u := range updates { // attempt to insert. Due to race conditions with the check this could fail. // That's OK, we're doing first write wins. The client will be messaged it // needs to rebase. - _, err = tx.Exec(insertStmt, gun, u.Role, u.Version, u.Data) + _, err = tx.Exec(insertStmt, gun, u.Role, u.Version, u.Data, u.Role, u.Version) if err != nil { // need to check error type for duplicate key exception // and return ErrOldVersion if duplicate