From 1f3e92f2e786d49b5a6754d7c07381f6d809c9f6 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 2 Aug 2013 08:56:36 +0200 Subject: [PATCH] ido: Keep track of insert IDs. --- components/ido_mysql/mysqldbconnection.cpp | 91 +++++++++++++--------- components/ido_mysql/mysqldbconnection.h | 2 +- lib/ido/dbconnection.cpp | 33 ++++++-- lib/ido/dbconnection.h | 10 ++- lib/ido/dbobject.cpp | 52 ++++++------- lib/ido/dbquery.h | 11 ++- 6 files changed, 120 insertions(+), 79 deletions(-) diff --git a/components/ido_mysql/mysqldbconnection.cpp b/components/ido_mysql/mysqldbconnection.cpp index 449d8eacc..f59216aa9 100644 --- a/components/ido_mysql/mysqldbconnection.cpp +++ b/components/ido_mysql/mysqldbconnection.cpp @@ -125,7 +125,7 @@ void MysqlDbConnection::ReconnectTimerHandler(void) if (rows->GetLength() == 0) { Query("INSERT INTO " + GetTablePrefix() + "instances (instance_name, instance_description) VALUES ('" + Escape(instanceName) + "', '" + m_InstanceDescription + "')"); - m_InstanceID = GetInsertID(); + m_InstanceID = GetLastInsertID(); } else { Dictionary::Ptr row = rows->Get(0); m_InstanceID = DbReference(row->Get("instance_id")); @@ -149,7 +149,7 @@ void MysqlDbConnection::ReconnectTimerHandler(void) continue; DbObject::Ptr dbobj = dbtype->GetOrCreateObjectByName(row->Get("name1"), row->Get("name2")); - SetReference(dbobj, DbReference(row->Get("object_id"))); + SetObjectID(dbobj, DbReference(row->Get("object_id"))); } Query("BEGIN"); @@ -190,7 +190,7 @@ Array::Ptr MysqlDbConnection::Query(const String& query) return rows; } -DbReference MysqlDbConnection::GetInsertID(void) +DbReference MysqlDbConnection::GetLastInsertID(void) { return DbReference(mysql_insert_id(&m_Connection)); } @@ -251,7 +251,7 @@ void MysqlDbConnection::InternalActivateObject(const DbObject::Ptr& dbobj) if (!m_Connected) return; - DbReference dbref = GetReference(dbobj); + DbReference dbref = GetObjectID(dbobj); std::ostringstream qbuf; if (!dbref.IsValid()) { @@ -259,7 +259,7 @@ void MysqlDbConnection::InternalActivateObject(const DbObject::Ptr& dbobj) << static_cast(m_InstanceID) << ", " << dbobj->GetType()->GetTypeID() << ", " << "'" << Escape(dbobj->GetName1()) << "', '" << Escape(dbobj->GetName2()) << "', 1)"; Query(qbuf.str()); - SetReference(dbobj, GetInsertID()); + SetObjectID(dbobj, GetLastInsertID()); } else { qbuf << "UPDATE " + GetTablePrefix() + "objects SET is_active = 1 WHERE object_id = " << static_cast(dbref); Query(qbuf.str()); @@ -273,7 +273,7 @@ void MysqlDbConnection::DeactivateObject(const DbObject::Ptr& dbobj) if (!m_Connected) return; - DbReference dbref = GetReference(dbobj); + DbReference dbref = GetObjectID(dbobj); if (!dbref.IsValid()) return; @@ -299,12 +299,12 @@ bool MysqlDbConnection::FieldToEscapedString(const String& key, const Value& val return true; } - DbReference dbrefcol = GetReference(dbobjcol); + DbReference dbrefcol = GetObjectID(dbobjcol); if (!dbrefcol.IsValid()) { InternalActivateObject(dbobjcol); - dbrefcol = GetReference(dbobjcol); + dbrefcol = GetObjectID(dbobjcol); if (!dbrefcol.IsValid()) return false; @@ -332,14 +332,51 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) if (!m_Connected) return; - std::ostringstream qbuf; + std::ostringstream qbuf, where; + int type; - switch (query.Type) { + if (query.WhereCriteria) { + where << " WHERE "; + + ObjectLock olock(query.WhereCriteria); + + String key; + Value value; + bool first = true; + BOOST_FOREACH(boost::tie(key, value), query.WhereCriteria) { + if (!FieldToEscapedString(key, value, &value)) + return; + + if (!first) + qbuf << " AND "; + + where << key << " = " << value; + + if (first) + first = false; + } + } + + if ((query.Type & DbQueryInsert) && (query.Type & DbQueryUpdate)) { + assert(query.Object); + + if (GetInsertID(query.Object).IsValid()) + type = DbQueryUpdate; + else { + if (query.WhereCriteria) + Query("DELETE FROM " + GetTablePrefix() + query.Table + where.str()); + + type = DbQueryInsert; + } + } else + type = query.Type; + + switch (type) { case DbQueryInsert: qbuf << "INSERT INTO " << GetTablePrefix() << query.Table; break; case DbQueryUpdate: - qbuf << "UPDATE " << GetTablePrefix() << query.Table << "SET"; + qbuf << "UPDATE " << GetTablePrefix() << query.Table << " SET"; break; case DbQueryDelete: qbuf << "DELETE FROM " << GetTablePrefix() << query.Table; @@ -348,7 +385,7 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) ASSERT(!"Invalid query type."); } - if (query.Type == DbQueryInsert || query.Type == DbQueryUpdate) { + if (type == DbQueryInsert || type == DbQueryUpdate) { String cols; String values; @@ -361,7 +398,7 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) if (!FieldToEscapedString(key, value, &value)) return; - if (query.Type == DbQueryInsert) { + if (type == DbQueryInsert) { if (!first) { cols += ", "; values += ", "; @@ -380,31 +417,15 @@ void MysqlDbConnection::ExecuteQuery(const DbQuery& query) first = false; } - if (query.Type == DbQueryInsert) + if (type == DbQueryInsert) qbuf << " (" << cols << ") VALUES (" << values << ")"; } - if (query.WhereCriteria) { - qbuf << " WHERE "; - - ObjectLock olock(query.WhereCriteria); - - String key; - Value value; - bool first = true; - BOOST_FOREACH(boost::tie(key, value), query.WhereCriteria) { - if (!FieldToEscapedString(key, value, &value)) - return; - - if (!first) - qbuf << " AND "; - - qbuf << key << " = " << value; - - if (first) - first = false; - } - } + if (type != DbQueryInsert) + qbuf << where.str(); Query(qbuf.str()); + + if (type == DbQueryInsert && query.Object) + SetInsertID(query.Object, GetLastInsertID()); } diff --git a/components/ido_mysql/mysqldbconnection.h b/components/ido_mysql/mysqldbconnection.h index 628615582..5d71dc2e4 100644 --- a/components/ido_mysql/mysqldbconnection.h +++ b/components/ido_mysql/mysqldbconnection.h @@ -69,7 +69,7 @@ private: Timer::Ptr m_TxTimer; Array::Ptr Query(const String& query); - DbReference GetInsertID(void); + DbReference GetLastInsertID(void); String Escape(const String& s); Dictionary::Ptr FetchRow(MYSQL_RES *result); diff --git a/lib/ido/dbconnection.cpp b/lib/ido/dbconnection.cpp index 408d5270c..35768e53f 100644 --- a/lib/ido/dbconnection.cpp +++ b/lib/ido/dbconnection.cpp @@ -91,26 +91,47 @@ void DbConnection::ProgramStatusHandler(void) DbObject::OnQuery(query2); } -void DbConnection::SetReference(const DbObject::Ptr& dbobj, const DbReference& dbref) +void DbConnection::SetObjectID(const DbObject::Ptr& dbobj, const DbReference& dbref) { if (dbref.IsValid()) - m_References[dbobj] = dbref; + m_ObjectIDs[dbobj] = dbref; else - m_References.erase(dbobj); + m_ObjectIDs.erase(dbobj); } -DbReference DbConnection::GetReference(const DbObject::Ptr& dbobj) const +DbReference DbConnection::GetObjectID(const DbObject::Ptr& dbobj) const { std::map::const_iterator it; - it = m_References.find(dbobj); + it = m_ObjectIDs.find(dbobj); - if (it == m_References.end()) + if (it == m_ObjectIDs.end()) return DbReference(); return it->second; } +void DbConnection::SetInsertID(const DbObject::Ptr& dbobj, const DbReference& dbref) +{ + if (dbref.IsValid()) + m_InsertIDs[dbobj] = dbref; + else + m_InsertIDs.erase(dbobj); +} + +DbReference DbConnection::GetInsertID(const DbObject::Ptr& dbobj) const +{ + std::map::const_iterator it; + + it = m_InsertIDs.find(dbobj); + + if (it == m_InsertIDs.end()) + return DbReference(); + + return it->second; +} + + void DbConnection::ExecuteQuery(const DbQuery&) { /* Default handler does nothing. */ diff --git a/lib/ido/dbconnection.h b/lib/ido/dbconnection.h index 7aa2163b2..0a7949ca4 100644 --- a/lib/ido/dbconnection.h +++ b/lib/ido/dbconnection.h @@ -42,8 +42,11 @@ public: static void StaticInitialize(void); - void SetReference(const DbObject::Ptr& dbobj, const DbReference& dbref); - DbReference GetReference(const DbObject::Ptr& dbobj) const; + void SetObjectID(const DbObject::Ptr& dbobj, const DbReference& dbref); + DbReference GetObjectID(const DbObject::Ptr& dbobj) const; + + void SetInsertID(const DbObject::Ptr& dbobj, const DbReference& dbref); + DbReference GetInsertID(const DbObject::Ptr& dbobj) const; String GetTablePrefix(void) const; @@ -59,7 +62,8 @@ protected: private: Attribute m_TablePrefix; - std::map m_References; + std::map m_ObjectIDs; + std::map m_InsertIDs; static Timer::Ptr m_ProgramStatusTimer; static void ProgramStatusHandler(void); diff --git a/lib/ido/dbobject.cpp b/lib/ido/dbobject.cpp index 11d27204a..d8b3a9ca4 100644 --- a/lib/ido/dbobject.cpp +++ b/lib/ido/dbobject.cpp @@ -79,21 +79,17 @@ void DbObject::SendConfigUpdate(void) if (!fields) return; - DbQuery query1; - query1.Table = GetType()->GetTable() + "s"; - query1.Type = DbQueryDelete; - query1.WhereCriteria = boost::make_shared(); - query1.WhereCriteria->Set(GetType()->GetIDColumn(), GetObject()); - OnQuery(query1); - - DbQuery query2; - query2.Table = GetType()->GetTable() + "s"; - query2.Type = DbQueryInsert; - query2.Fields = fields; - query2.Fields->Set(GetType()->GetIDColumn(), GetObject()); - query2.Fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ - query2.Fields->Set("config_type", 1); - OnQuery(query2); + DbQuery query; + query.Table = GetType()->GetTable() + "s"; + query.Type = DbQueryInsert | DbQueryUpdate; + query.Fields = fields; + query.Fields->Set(GetType()->GetIDColumn(), GetObject()); + query.Fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ + query.Fields->Set("config_type", 1); + query.WhereCriteria = boost::make_shared(); + query.WhereCriteria->Set(GetType()->GetIDColumn(), GetObject()); + query.Object = GetSelf(); + OnQuery(query); m_LastConfigUpdate = Utility::GetTime(); @@ -107,21 +103,17 @@ void DbObject::SendStatusUpdate(void) if (!fields) return; - DbQuery query1; - query1.Table = GetType()->GetTable() + "status"; - query1.Type = DbQueryDelete; - query1.WhereCriteria = boost::make_shared(); - query1.WhereCriteria->Set(GetType()->GetIDColumn(), GetObject()); - OnQuery(query1); - - DbQuery query2; - query2.Table = GetType()->GetTable() + "status"; - query2.Type = DbQueryInsert; - query2.Fields = fields; - query2.Fields->Set(GetType()->GetIDColumn(), GetObject()); - query2.Fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ - query2.Fields->Set("status_update_time", DbValue::FromTimestamp(Utility::GetTime())); - OnQuery(query2); + DbQuery query; + query.Table = GetType()->GetTable() + "status"; + query.Type = DbQueryInsert | DbQueryUpdate; + query.Fields = fields; + query.Fields->Set(GetType()->GetIDColumn(), GetObject()); + query.Fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ + query.Fields->Set("status_update_time", DbValue::FromTimestamp(Utility::GetTime())); + query.WhereCriteria = boost::make_shared(); + query.WhereCriteria->Set(GetType()->GetIDColumn(), GetObject()); + query.Object = GetSelf(); + OnQuery(query); m_LastStatusUpdate = Utility::GetTime(); diff --git a/lib/ido/dbquery.h b/lib/ido/dbquery.h index 223dcc50e..7f2c78050 100644 --- a/lib/ido/dbquery.h +++ b/lib/ido/dbquery.h @@ -27,17 +27,20 @@ namespace icinga enum DbQueryType { - DbQueryInsert, - DbQueryUpdate, - DbQueryDelete + DbQueryInsert = 1, + DbQueryUpdate = 2, + DbQueryDelete = 4 }; +class DbObject; + struct DbQuery { - DbQueryType Type; + int Type; String Table; Dictionary::Ptr Fields; Dictionary::Ptr WhereCriteria; + boost::shared_ptr Object; }; }