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->Set("object_id", obj);
query.WhereCriteria->Set("varname", kv.first);
query.Object = this;
queries.push_back(query);
}

View File

@ -810,7 +810,7 @@ void IdoMysqlConnection::ExecuteQuery(const DbQuery& query)
{
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)
@ -870,11 +870,11 @@ void IdoMysqlConnection::InternalExecuteMultipleQueries(const std::vector<DbQuer
}
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();
@ -911,7 +911,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) {
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;
}
@ -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;
@ -945,6 +945,14 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
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) {
case DbQueryInsert:
qbuf << "INSERT INTO " << GetTablePrefix() << query.Table;
@ -975,7 +983,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
continue;
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;
}
@ -1011,8 +1019,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
void IdoMysqlConnection::FinishExecuteQuery(const DbQuery& query, int type, bool upsert)
{
if (upsert && GetAffectedRows() == 0) {
DbQueryType to = DbQueryInsert;
InternalExecuteQuery(query, &to);
InternalExecuteQuery(query, DbQueryDelete | DbQueryInsert);
return;
}

View File

@ -107,7 +107,7 @@ private:
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 FinishExecuteQuery(const DbQuery& query, int type, bool upsert);

View File

@ -667,7 +667,7 @@ void IdoPgsqlConnection::ExecuteQuery(const DbQuery& query)
{
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)
@ -727,11 +727,11 @@ void IdoPgsqlConnection::InternalExecuteMultipleQueries(const std::vector<DbQuer
}
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();
@ -768,7 +768,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) {
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;
}
@ -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;
@ -802,6 +802,14 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
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) {
case DbQueryInsert:
qbuf << "INSERT INTO " << GetTablePrefix() << query.Table;
@ -831,7 +839,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
continue;
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;
}
@ -864,8 +872,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType
Query(qbuf.str());
if (upsert && GetAffectedRows() == 0) {
DbQueryType to = DbQueryInsert;
InternalExecuteQuery(query, &to);
InternalExecuteQuery(query, DbQueryDelete | DbQueryInsert);
return;
}

View File

@ -95,7 +95,7 @@ private:
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 InternalCleanUpExecuteQuery(const String& table, const String& time_key, double time_value);