Fix problem with duplicate INSERTs for the same key columns

fixes #12461
fixes #12458
This commit is contained in:
Gunnar Beutner 2016-08-17 13:24:18 +02:00
parent b26b3a4f65
commit 4c54cddec8
5 changed files with 32 additions and 19 deletions

View File

@ -314,7 +314,6 @@ void DbObject::SendVarsStatusUpdate(void)
query.WhereCriteria = new Dictionary(); query.WhereCriteria = new Dictionary();
query.WhereCriteria->Set("object_id", obj); query.WhereCriteria->Set("object_id", obj);
query.WhereCriteria->Set("varname", kv.first); query.WhereCriteria->Set("varname", kv.first);
query.Object = this;
queries.push_back(query); queries.push_back(query);
} }

View File

@ -810,7 +810,7 @@ void IdoMysqlConnection::ExecuteQuery(const DbQuery& query)
{ {
ASSERT(query.Category != DbCatInvalid); ASSERT(query.Category != DbCatInvalid);
m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority, true); m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, -1), query.Priority, true);
} }
void IdoMysqlConnection::ExecuteMultipleQueries(const std::vector<DbQuery>& queries) void IdoMysqlConnection::ExecuteMultipleQueries(const std::vector<DbQuery>& queries)
@ -870,11 +870,11 @@ void IdoMysqlConnection::InternalExecuteMultipleQueries(const std::vector<DbQuer
} }
BOOST_FOREACH(const DbQuery& query, queries) { BOOST_FOREACH(const DbQuery& query, queries) {
InternalExecuteQuery(query, NULL); InternalExecuteQuery(query);
} }
} }
void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride) void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, int typeOverride)
{ {
AssertOnWorkQueue(); AssertOnWorkQueue();
@ -911,7 +911,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) { BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) {
if (!FieldToEscapedString(kv.first, kv.second, &value)) { if (!FieldToEscapedString(kv.first, kv.second, &value)) {
m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority); m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, -1), query.Priority);
return; return;
} }
@ -925,7 +925,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
} }
} }
type = typeOverride ? *typeOverride : query.Type; type = (typeOverride != -1) ? typeOverride : query.Type;
bool upsert = false; bool upsert = false;
@ -945,6 +945,14 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
type = DbQueryUpdate; type = DbQueryUpdate;
} }
if ((type & DbQueryInsert) && (type & DbQueryDelete)) {
std::ostringstream qdel;
qdel << "DELETE FROM " << GetTablePrefix() << query.Table << where.str();
AsyncQuery(qdel.str());
type = DbQueryInsert;
}
switch (type) { switch (type) {
case DbQueryInsert: case DbQueryInsert:
qbuf << "INSERT INTO " << GetTablePrefix() << query.Table; qbuf << "INSERT INTO " << GetTablePrefix() << query.Table;
@ -975,7 +983,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
continue; continue;
if (!FieldToEscapedString(kv.first, kv.second, &value)) { if (!FieldToEscapedString(kv.first, kv.second, &value)) {
m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority); m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, -1), query.Priority);
return; return;
} }
@ -1011,8 +1019,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
void IdoMysqlConnection::FinishExecuteQuery(const DbQuery& query, int type, bool upsert) void IdoMysqlConnection::FinishExecuteQuery(const DbQuery& query, int type, bool upsert)
{ {
if (upsert && GetAffectedRows() == 0) { if (upsert && GetAffectedRows() == 0) {
DbQueryType to = DbQueryInsert; InternalExecuteQuery(query, DbQueryDelete | DbQueryInsert);
InternalExecuteQuery(query, &to);
return; return;
} }

View File

@ -107,7 +107,7 @@ private:
bool CanExecuteQuery(const DbQuery& query); bool CanExecuteQuery(const DbQuery& query);
void InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride = NULL); void InternalExecuteQuery(const DbQuery& query, int typeOverride = -1);
void InternalExecuteMultipleQueries(const std::vector<DbQuery>& queries); void InternalExecuteMultipleQueries(const std::vector<DbQuery>& queries);
void FinishExecuteQuery(const DbQuery& query, int type, bool upsert); void FinishExecuteQuery(const DbQuery& query, int type, bool upsert);

View File

@ -667,7 +667,7 @@ void IdoPgsqlConnection::ExecuteQuery(const DbQuery& query)
{ {
ASSERT(query.Category != DbCatInvalid); ASSERT(query.Category != DbCatInvalid);
m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority, true); m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, -1), query.Priority, true);
} }
void IdoPgsqlConnection::ExecuteMultipleQueries(const std::vector<DbQuery>& queries) void IdoPgsqlConnection::ExecuteMultipleQueries(const std::vector<DbQuery>& queries)
@ -727,11 +727,11 @@ void IdoPgsqlConnection::InternalExecuteMultipleQueries(const std::vector<DbQuer
} }
BOOST_FOREACH(const DbQuery& query, queries) { BOOST_FOREACH(const DbQuery& query, queries) {
InternalExecuteQuery(query, NULL); InternalExecuteQuery(query);
} }
} }
void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride) void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, int typeOverride)
{ {
AssertOnWorkQueue(); AssertOnWorkQueue();
@ -768,7 +768,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) { BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) {
if (!FieldToEscapedString(kv.first, kv.second, &value)) { if (!FieldToEscapedString(kv.first, kv.second, &value)) {
m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority); m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, -1), query.Priority);
return; return;
} }
@ -782,7 +782,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
} }
} }
type = typeOverride ? *typeOverride : query.Type; type = (typeOverride != -1) ? typeOverride : query.Type;
bool upsert = false; bool upsert = false;
@ -802,6 +802,14 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
type = DbQueryUpdate; type = DbQueryUpdate;
} }
if ((type & DbQueryInsert) && (type & DbQueryDelete)) {
std::ostringstream qdel;
qdel << "DELETE FROM " << GetTablePrefix() << query.Table << where.str();
Query(qdel.str());
type = DbQueryInsert;
}
switch (type) { switch (type) {
case DbQueryInsert: case DbQueryInsert:
qbuf << "INSERT INTO " << GetTablePrefix() << query.Table; qbuf << "INSERT INTO " << GetTablePrefix() << query.Table;
@ -831,7 +839,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
continue; continue;
if (!FieldToEscapedString(kv.first, kv.second, &value)) { if (!FieldToEscapedString(kv.first, kv.second, &value)) {
m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority); m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, -1), query.Priority);
return; return;
} }
@ -864,8 +872,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
Query(qbuf.str()); Query(qbuf.str());
if (upsert && GetAffectedRows() == 0) { if (upsert && GetAffectedRows() == 0) {
DbQueryType to = DbQueryInsert; InternalExecuteQuery(query, DbQueryDelete | DbQueryInsert);
InternalExecuteQuery(query, &to);
return; return;
} }

View File

@ -95,7 +95,7 @@ private:
bool CanExecuteQuery(const DbQuery& query); bool CanExecuteQuery(const DbQuery& query);
void InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride = NULL); void InternalExecuteQuery(const DbQuery& query, int typeOverride = -1);
void InternalExecuteMultipleQueries(const std::vector<DbQuery>& queries); void InternalExecuteMultipleQueries(const std::vector<DbQuery>& queries);
void InternalCleanUpExecuteQuery(const String& table, const String& time_key, double time_value); void InternalCleanUpExecuteQuery(const String& table, const String& time_key, double time_value);