Skip inserting rows that would cause a duplicate primary key error.

The cause is that somehow, during regular play, MP campaigns can end up with duplicate values in the [content] data for each [addon]. A very similar issue was fixed in 6c980d12dcd56ccd16ff8b7150cd15ef19f0a821, but there's apparently some other way to trigger it that I haven't been able to reproduce. Since the error itself is harmless, it'll just be avoided server-side to avoid the spurious errors in the server log file.
This commit is contained in:
Pentarctagon 2022-12-23 12:32:05 -06:00 committed by Pentarctagon
parent 6457ceb206
commit e5023e40db
2 changed files with 10 additions and 5 deletions

View File

@ -1676,11 +1676,16 @@ void server::handle_player_in_game(player_iterator p, simple_wml::document& data
const simple_wml::node& m = *g.level().root().child("multiplayer");
DBG_SERVER << simple_wml::node_to_string(m);
// [addon] info handling
std::set<std::string> primary_keys;
for(const auto& addon : m.children("addon")) {
for(const auto& content : addon->children("content")) {
unsigned long long rows_inserted = user_handler_->db_insert_game_content_info(uuid_, g.db_id(), content->attr("type").to_string(), content->attr("name").to_string(), content->attr("id").to_string(), addon->attr("id").to_string(), addon->attr("version").to_string());
if(rows_inserted == 0) {
WRN_SERVER << "Did not insert content row for [addon] data with uuid '" << uuid_ << "', game ID '" << g.db_id() << "', type '" << content->attr("type").to_string() << "', and content ID '" << content->attr("id").to_string() << "'";
std::string key = uuid_+"-"+std::to_string(g.db_id())+"-"+content->attr("type").to_string()+"-"+content->attr("id").to_string()+"-"+addon->attr("id").to_string();
if(primary_keys.count(key) == 0) {
primary_keys.emplace(key);
unsigned long long rows_inserted = user_handler_->db_insert_game_content_info(uuid_, g.db_id(), content->attr("type").to_string(), content->attr("name").to_string(), content->attr("id").to_string(), addon->attr("id").to_string(), addon->attr("version").to_string());
if(rows_inserted == 0) {
WRN_SERVER << "Did not insert content row for [addon] data with uuid '" << uuid_ << "', game ID '" << g.db_id() << "', type '" << content->attr("type").to_string() << "', and content ID '" << content->attr("id").to_string() << "'";
}
}
}
}

View File

@ -108,7 +108,7 @@ create table game_player_info
CREATE INDEX USER_ID_IDX ON game_player_info(USER_ID);
-- information about the scenario/era/modifications for the game
-- TYPE: one of era/scenario/modification
-- TYPE: one of era/scenario/modification/campaign
-- ID: the id of the content
-- NAME: the content's user-visible name
-- SOURCE: the id of the add-on that the particular content came from
@ -122,7 +122,7 @@ create table game_content_info
NAME VARCHAR(255),
SOURCE VARCHAR(255) NOT NULL,
VERSION VARCHAR(255) NOT NULL,
PRIMARY KEY (INSTANCE_UUID, GAME_ID, TYPE, ID)
PRIMARY KEY (INSTANCE_UUID, GAME_ID, TYPE, ID, SOURCE)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- information about an uploaded addon