diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 0015c1947..6c4968657 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -294,21 +294,36 @@ public: } template - void bind (const T &var, const char *name) { - mStmt.exchange(soci::use(var, name)); + StatementBind &in (const T &var) { + mStmt.exchange(soci::use(var)); + return *this; } template - void bindResult (T &var) { + StatementBind &out (T &var) { mStmt.exchange(soci::into(var)); + return *this; + } + + StatementBind &out (soci::row &row) { + mUseRow = true; + mStmt.define_and_bind(); + mStmt.exchange_for_rowset(soci::into(row)); + return *this; + } + + soci::statement &getStatement () const { + return mStmt; } bool exec () { - mStmt.define_and_bind(); + if (!mUseRow) + mStmt.define_and_bind(); return mStmt.execute(true); } private: + bool mUseRow = false; soci::statement &mStmt; }; @@ -321,6 +336,10 @@ struct MainDbPrivate::Statements { Statement selectSipAddressId; Statement selectChatRoomId; + + Statement selectConferenceChatMessageEvent; + Statement selectConferenceChatMessageContent; + Statement selectConferenceChatMessageFileContent; }; void MainDbPrivate::initStatements () { @@ -332,6 +351,29 @@ void MainDbPrivate::initStatements () { *session, "SELECT id FROM chat_room WHERE peer_sip_address_id = :peerSipAddressId AND local_sip_address_id = :localSipAddressId" ); + + statements->selectConferenceChatMessageEvent = makeStatement( + *session, + "SELECT from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured" + " FROM event, conference_chat_message_event, sip_address AS from_sip_address, sip_address AS to_sip_address" + " WHERE event_id = :eventId" + " AND event_id = event.id" + " AND from_sip_address_id = from_sip_address.id" + " AND to_sip_address_id = to_sip_address.id" + ); + + statements->selectConferenceChatMessageContent = makeStatement( + *session, + "SELECT chat_message_content.id, content_type.id, content_type.value, body" + " FROM chat_message_content, content_type" + " WHERE event_id = :eventId AND content_type_id = content_type.id" + ); + + statements->selectConferenceChatMessageFileContent = makeStatement( + *session, + "SELECT name, size, path FROM chat_message_file_content" + " WHERE chat_message_content_id = :contentId" + ); } // ----------------------------------------------------------------------------- @@ -535,23 +577,14 @@ void MainDbPrivate::insertChatMessageParticipant (long long eventId, long long s long long MainDbPrivate::selectSipAddressId (const string &sipAddress) const { long long id; - - StatementBind stmt(*statements->selectSipAddressId); - stmt.bind(sipAddress, "sipAddress"); - stmt.bindResult(id); - - return stmt.exec() ? id : -1; + return StatementBind(*statements->selectSipAddressId) + .in(sipAddress).out(id).exec() ? id : -1; } long long MainDbPrivate::selectChatRoomId (long long peerSipAddressId, long long localSipAddressId) const { long long id; - - StatementBind stmt(*statements->selectChatRoomId); - stmt.bind(peerSipAddressId, "peerSipAddressId"); - stmt.bind(localSipAddressId, "localSipAddressId"); - stmt.bindResult(id); - - return stmt.exec() ? id : -1; + return StatementBind(*statements->selectChatRoomId) + .in(peerSipAddressId).in(localSipAddressId).out(id).exec() ? id : -1; } long long MainDbPrivate::selectChatRoomId (const ChatRoomId &chatRoomId) const { @@ -706,21 +739,18 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( ) const { L_Q(); - shared_ptr core = q->getCore(); - shared_ptr chatRoom = core->findChatRoom(chatRoomId); - if (!chatRoom) { - lError() << "Unable to find chat room storage id of (peer=" + - chatRoomId.getPeerAddress().asString() + - ", local=" + chatRoomId.getLocalAddress().asString() + "`)."; + shared_ptr chatRoom = q->getCore()->findChatRoom(chatRoomId); + if (!chatRoom) return nullptr; - } - - bool hasFileTransferContent = false; // 1 - Fetch chat message. shared_ptr chatMessage = getChatMessageFromCache(eventId); if (chatMessage) - goto end; + return make_shared( + creationTime, + chatMessage + ); + { string fromSipAddress; string toSipAddress; @@ -733,15 +763,16 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( int direction; int isSecured; - soci::session *session = dbSession.getBackendSession(); - *session << "SELECT from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured" - " FROM event, conference_chat_message_event, sip_address AS from_sip_address, sip_address AS to_sip_address" - " WHERE event_id = :eventId" - " AND event_id = event.id" - " AND from_sip_address_id = from_sip_address.id" - " AND to_sip_address_id = to_sip_address.id", soci::into(fromSipAddress), soci::into(toSipAddress), - soci::into(messageTime), soci::into(imdnMessageId), soci::into(state), soci::into(direction), - soci::into(isSecured), soci::use(eventId); + StatementBind(*statements->selectConferenceChatMessageEvent) + .in(eventId) + .out(fromSipAddress) + .out(toSipAddress) + .out(messageTime) + .out(imdnMessageId) + .out(state) + .out(direction) + .out(isSecured) + .exec(); chatMessage = shared_ptr(new ChatMessage( chatRoom, @@ -760,13 +791,17 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( } // 2 - Fetch contents. + bool hasFileTransferContent = false; { soci::session *session = dbSession.getBackendSession(); - static const string query = "SELECT chat_message_content.id, content_type.id, content_type.value, body" - " FROM chat_message_content, content_type" - " WHERE event_id = :eventId AND content_type_id = content_type.id"; - soci::rowset rows = (session->prepare << query, soci::use(eventId)); - for (const auto &row : rows) { + + soci::row row; + StatementBind stmtBind(*statements->selectConferenceChatMessageContent); + stmtBind.in(eventId).out(row).exec(); + + for (soci::rowset_iterator it(stmtBind.getStatement(), row), end; it != end; ++it) { + const soci::row &row = *it; + ContentType contentType(row.get(2)); const long long &contentId = dbSession.resolveId(row, 0); Content *content; @@ -781,9 +816,8 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( int size; string path; - *session << "SELECT name, size, path FROM chat_message_file_content" - " WHERE chat_message_content_id = :contentId", - soci::into(name), soci::into(size), soci::into(path), soci::use(contentId); + StatementBind(*statements->selectConferenceChatMessageFileContent) + .in(contentId).out(name).out(size).out(path).exec(); FileContent *fileContent = new FileContent(); fileContent->setFileName(name); @@ -816,7 +850,6 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( cache(chatMessage, eventId); -end: return make_shared( creationTime, chatMessage