X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fsqlitestorage.cpp;h=1a75713aa5aeae66b0013fc71e43077b80b04387;hp=893bd77496df4355f97f1d522333326a9e5b35af;hb=HEAD;hpb=de04705745cf92be498a1273fdc4abf84d2649c9 diff --git a/src/core/sqlitestorage.cpp b/src/core/sqlitestorage.cpp index 893bd774..3ca0344e 100644 --- a/src/core/sqlitestorage.cpp +++ b/src/core/sqlitestorage.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2019 by the Quassel Project * + * Copyright (C) 2005-2022 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -20,7 +20,10 @@ #include "sqlitestorage.h" -#include +#include +#include +#include +#include #include "network.h" #include "quassel.h" @@ -192,7 +195,7 @@ UserId SqliteStorage::addUser(const QString& user, const QString& password, cons lockForWrite(); safeExec(query); if (query.lastError().isValid() - && query.lastError().nativeErrorCode() == "19") { // user already exists - sadly 19 seems to be the general constraint violation error... + && query.lastError().nativeErrorCode() == QLatin1String{"19"}) { // user already exists - sadly 19 seems to be the general constraint violation error... db.rollback(); } else { @@ -500,13 +503,8 @@ IdentityId SqliteStorage::createIdentity(UserId user, CoreIdentity& identity) query.bindValue(":kickreason", identity.kickReason()); query.bindValue(":partreason", identity.partReason()); query.bindValue(":quitreason", identity.quitReason()); -#ifdef HAVE_SSL query.bindValue(":sslcert", identity.sslCert().toPem()); query.bindValue(":sslkey", identity.sslKey().toPem()); -#else - query.bindValue(":sslcert", QByteArray()); - query.bindValue(":sslkey", QByteArray()); -#endif lockForWrite(); safeExec(query); @@ -578,13 +576,8 @@ bool SqliteStorage::updateIdentity(UserId user, const CoreIdentity& identity) query.bindValue(":kickreason", identity.kickReason()); query.bindValue(":partreason", identity.partReason()); query.bindValue(":quitreason", identity.quitReason()); -#ifdef HAVE_SSL query.bindValue(":sslcert", identity.sslCert().toPem()); query.bindValue(":sslkey", identity.sslKey().toPem()); -#else - query.bindValue(":sslcert", QByteArray()); - query.bindValue(":sslkey", QByteArray()); -#endif query.bindValue(":identityid", identity.id().toInt()); safeExec(query); watchQuery(query); @@ -647,9 +640,9 @@ void SqliteStorage::removeIdentity(UserId user, IdentityId identityId) unlock(); } -QList SqliteStorage::identities(UserId user) +std::vector SqliteStorage::identities(UserId user) { - QList identities; + std::vector identities; QSqlDatabase db = logDb(); db.transaction(); @@ -684,10 +677,8 @@ QList SqliteStorage::identities(UserId user) identity.setKickReason(query.value(15).toString()); identity.setPartReason(query.value(16).toString()); identity.setQuitReason(query.value(17).toString()); -#ifdef HAVE_SSL identity.setSslCert(query.value(18).toByteArray()); identity.setSslKey(query.value(19).toByteArray()); -#endif nickQuery.bindValue(":identityid", identity.id().toInt()); QList nicks; @@ -696,8 +687,8 @@ QList SqliteStorage::identities(UserId user) while (nickQuery.next()) { nicks << nickQuery.value(0).toString(); } - identity.setNicks(nicks); - identities << identity; + identity.setNicks(std::move(nicks)); + identities.push_back(std::move(identity)); } db.commit(); } @@ -782,6 +773,7 @@ void SqliteStorage::bindNetworkInfo(QSqlQuery& query, const NetworkInfo& info) query.bindValue(":messagerateburstsize", info.messageRateBurstSize); query.bindValue(":messageratedelay", info.messageRateDelay); query.bindValue(":unlimitedmessagerate", info.unlimitedMessageRate ? 1 : 0); + query.bindValue(":skipcaps", info.skipCapsToString()); if (info.networkId.isValid()) query.bindValue(":networkid", info.networkId.toInt()); } @@ -935,9 +927,9 @@ bool SqliteStorage::removeNetwork(UserId user, const NetworkId& networkId) return true; } -QList SqliteStorage::networks(UserId user) +std::vector SqliteStorage::networks(UserId user) { - QList nets; + std::vector nets; QSqlDatabase db = logDb(); db.transaction(); @@ -979,6 +971,7 @@ QList SqliteStorage::networks(UserId user) net.messageRateBurstSize = networksQuery.value(20).toUInt(); net.messageRateDelay = networksQuery.value(21).toUInt(); net.unlimitedMessageRate = networksQuery.value(22).toInt() == 1 ? true : false; + net.skipCapsFromString(networksQuery.value(23).toString()); serversQuery.bindValue(":networkid", net.networkId.toInt()); safeExec(serversQuery); @@ -1005,7 +998,7 @@ QList SqliteStorage::networks(UserId user) servers << server; } net.serverList = servers; - nets << net; + nets.push_back(std::move(net)); } } } @@ -1015,9 +1008,9 @@ QList SqliteStorage::networks(UserId user) return nets; } -QList SqliteStorage::connectedNetworks(UserId user) +std::vector SqliteStorage::connectedNetworks(UserId user) { - QList connectedNets; + std::vector connectedNets; QSqlDatabase db = logDb(); db.transaction(); @@ -1031,7 +1024,7 @@ QList SqliteStorage::connectedNetworks(UserId user) watchQuery(query); while (query.next()) { - connectedNets << query.value(0).toInt(); + connectedNets.emplace_back(query.value(0).toInt()); } db.commit(); } @@ -1292,9 +1285,9 @@ BufferInfo SqliteStorage::getBufferInfo(UserId user, const BufferId& bufferId) return bufferInfo; } -QList SqliteStorage::requestBuffers(UserId user) +std::vector SqliteStorage::requestBuffers(UserId user) { - QList bufferlist; + std::vector bufferlist; QSqlDatabase db = logDb(); db.transaction(); @@ -1308,11 +1301,11 @@ QList SqliteStorage::requestBuffers(UserId user) safeExec(query); watchQuery(query); while (query.next()) { - bufferlist << BufferInfo(query.value(0).toInt(), - query.value(1).toInt(), - (BufferInfo::Type)query.value(2).toInt(), - query.value(3).toInt(), - query.value(4).toString()); + bufferlist.emplace_back(query.value(0).toInt(), + query.value(1).toInt(), + (BufferInfo::Type)query.value(2).toInt(), + query.value(3).toInt(), + query.value(4).toString()); } db.commit(); } @@ -1321,9 +1314,9 @@ QList SqliteStorage::requestBuffers(UserId user) return bufferlist; } -QList SqliteStorage::requestBufferIdsForNetwork(UserId user, NetworkId networkId) +std::vector SqliteStorage::requestBufferIdsForNetwork(UserId user, NetworkId networkId) { - QList bufferList; + std::vector bufferList; QSqlDatabase db = logDb(); db.transaction(); @@ -1338,7 +1331,7 @@ QList SqliteStorage::requestBufferIdsForNetwork(UserId user, NetworkId safeExec(query); watchQuery(query); while (query.next()) { - bufferList << BufferId(query.value(0).toInt()); + bufferList.emplace_back(query.value(0).toInt()); } db.commit(); } @@ -1408,8 +1401,8 @@ bool SqliteStorage::renameBuffer(const UserId& user, const BufferId& bufferId, c safeExec(query); error = query.lastError().isValid(); - // unexepcted error occured (19 == constraint violation) - if (error && query.lastError().nativeErrorCode() != "19") { + // unexpected error occurred (19 == constraint violation) + if (error && query.lastError().nativeErrorCode() != QLatin1String{"19"}) { watchQuery(query); } else { @@ -1482,6 +1475,34 @@ bool SqliteStorage::mergeBuffersPermanently(const UserId& user, const BufferId& return !error; } +QHash SqliteStorage::bufferLastMsgIds(UserId user) +{ + QHash lastMsgHash; + + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + { + QSqlQuery query(db); + query.prepare(queryString("select_buffer_last_messages")); + query.bindValue(":userid", user.toInt()); + + lockForRead(); + safeExec(query); + error = !watchQuery(query); + if (!error) { + while (query.next()) { + lastMsgHash[query.value(0).toInt()] = query.value(1).toLongLong(); + } + } + } + + db.commit(); + unlock(); + return lastMsgHash; +} + void SqliteStorage::setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) { QSqlDatabase db = logDb(); @@ -1631,7 +1652,7 @@ Message::Types SqliteStorage::bufferActivity(BufferId bufferId, MsgId lastSeenMs QSqlDatabase db = logDb(); db.transaction(); - Message::Types result = Message::Types(nullptr); + Message::Types result{}; { QSqlQuery query(db); query.prepare(queryString("select_buffer_bufferactivity")); @@ -1790,7 +1811,7 @@ bool SqliteStorage::logMessage(Message& msg) if (logMessageQuery.lastError().isValid()) { // constraint violation - must be NOT NULL constraint - probably the sender is missing... - if (logMessageQuery.lastError().nativeErrorCode() == "19") { + if (logMessageQuery.lastError().nativeErrorCode() == QLatin1String{"19"}) { QSqlQuery addSenderQuery(db); addSenderQuery.prepare(queryString("insert_sender")); addSenderQuery.bindValue(":sender", msg.sender()); @@ -1894,9 +1915,9 @@ bool SqliteStorage::logMessages(MessageList& msgs) return !error; } -QList SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) +std::vector SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) { - QList messagelist; + std::vector messagelist; QSqlDatabase db = logDb(); db.transaction(); @@ -1963,7 +1984,7 @@ QList SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId query.value(7).toString(), (Message::Flags)query.value(3).toInt()); msg.setMsgId(query.value(0).toLongLong()); - messagelist << msg; + messagelist.push_back(std::move(msg)); } } db.commit(); @@ -1972,10 +1993,10 @@ QList SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId return messagelist; } -QList SqliteStorage::requestMsgsFiltered( +std::vector SqliteStorage::requestMsgsFiltered( UserId user, BufferId bufferId, MsgId first, MsgId last, int limit, Message::Types type, Message::Flags flags) { - QList messagelist; + std::vector messagelist; QSqlDatabase db = logDb(); db.transaction(); @@ -2047,7 +2068,95 @@ QList SqliteStorage::requestMsgsFiltered( query.value(7).toString(), Message::Flags{query.value(3).toInt()}); msg.setMsgId(query.value(0).toLongLong()); - messagelist << msg; + messagelist.push_back(std::move(msg)); + } + } + db.commit(); + unlock(); + + return messagelist; +} + +std::vector SqliteStorage::requestMsgsForward( + UserId user, BufferId bufferId, MsgId first, MsgId last, int limit, Message::Types type, Message::Flags flags) +{ + std::vector messagelist; + + QSqlDatabase db = logDb(); + db.transaction(); + + bool error = false; + BufferInfo bufferInfo; + { + // code dupication from getBufferInfo: + // this is due to the impossibility of nesting transactions and recursive locking + QSqlQuery bufferInfoQuery(db); + bufferInfoQuery.prepare(queryString("select_buffer_by_id")); + bufferInfoQuery.bindValue(":userid", user.toInt()); + bufferInfoQuery.bindValue(":bufferid", bufferId.toInt()); + + lockForRead(); + safeExec(bufferInfoQuery); + error = !watchQuery(bufferInfoQuery) || !bufferInfoQuery.first(); + if (!error) { + bufferInfo = BufferInfo(bufferInfoQuery.value(0).toInt(), + bufferInfoQuery.value(1).toInt(), + (BufferInfo::Type)bufferInfoQuery.value(2).toInt(), + 0, + bufferInfoQuery.value(4).toString()); + error = !bufferInfo.isValid(); + } + } + if (error) { + db.rollback(); + unlock(); + return messagelist; + } + + { + QSqlQuery query(db); + query.prepare(queryString("select_messagesForward")); + + if (first == -1) { + query.bindValue(":firstmsg", std::numeric_limits::min()); + } else { + query.bindValue(":firstmsg", first.toQint64()); + } + + if (last == -1) { + query.bindValue(":lastmsg", std::numeric_limits::max()); + } else { + query.bindValue(":lastmsg", last.toQint64()); + } + + query.bindValue(":bufferid", bufferId.toInt()); + + int typeRaw = type; + int flagsRaw = flags; + query.bindValue(":type", typeRaw); + query.bindValue(":flags", flagsRaw); + + query.bindValue(":limit", limit); + + safeExec(query); + watchQuery(query); + + while (query.next()) { + Message msg( + // As of SQLite schema version 31, timestamps are stored in milliseconds + // instead of seconds. This nets us more precision as well as simplifying + // 64-bit time. + QDateTime::fromMSecsSinceEpoch(query.value(1).toLongLong()), + bufferInfo, + (Message::Type)query.value(2).toInt(), + query.value(8).toString(), + query.value(4).toString(), + query.value(5).toString(), + query.value(6).toString(), + query.value(7).toString(), + Message::Flags{query.value(3).toInt()}); + msg.setMsgId(query.value(0).toLongLong()); + messagelist.push_back(std::move(msg)); } } db.commit(); @@ -2056,9 +2165,9 @@ QList SqliteStorage::requestMsgsFiltered( return messagelist; } -QList SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId last, int limit) +std::vector SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId last, int limit) { - QList messagelist; + std::vector messagelist; QSqlDatabase db = logDb(); db.transaction(); @@ -2110,7 +2219,7 @@ QList SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId las query.value(8).toString(), (Message::Flags)query.value(4).toInt()); msg.setMsgId(query.value(0).toLongLong()); - messagelist << msg; + messagelist.push_back(std::move(msg)); } } db.commit(); @@ -2118,9 +2227,9 @@ QList SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId las return messagelist; } -QList SqliteStorage::requestAllMsgsFiltered(UserId user, MsgId first, MsgId last, int limit, Message::Types type, Message::Flags flags) +std::vector SqliteStorage::requestAllMsgsFiltered(UserId user, MsgId first, MsgId last, int limit, Message::Types type, Message::Flags flags) { - QList messagelist; + std::vector messagelist; QSqlDatabase db = logDb(); db.transaction(); @@ -2177,7 +2286,7 @@ QList SqliteStorage::requestAllMsgsFiltered(UserId user, MsgId first, M query.value(8).toString(), Message::Flags{query.value(4).toInt()}); msg.setMsgId(query.value(0).toLongLong()); - messagelist << msg; + messagelist.push_back(std::move(msg)); } } db.commit(); @@ -2223,7 +2332,7 @@ bool SqliteStorage::safeExec(QSqlQuery& query, int retryCount) // SQLITE_BUSY 5 /* The database file is locked */ // SQLITE_LOCKED 6 /* A table in the database is locked */ - if (nativeErrorCode == "5" || nativeErrorCode == "6") { + if (nativeErrorCode == QLatin1String{"5"} || nativeErrorCode == QLatin1String{"6"}) { if (retryCount < _maxRetryCount) return safeExec(query, retryCount + 1); } @@ -2387,6 +2496,8 @@ bool SqliteMigrationReader::readMo(NetworkMO& network) network.messagerateburstsize = value(26).toInt(); network.messageratedelay = value(27).toUInt(); network.unlimitedmessagerate = value(28).toInt() == 1 ? true : false; + // Skipped IRCv3 caps + network.skipcaps = value(29).toString(); return true; }