/***************************************************************************
- * Copyright (C) 2005-07 by the Quassel IRC Team *
+ * Copyright (C) 2005-07 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include <QtSql>
-#include "network.h"
-
-#include "util.h"
#include "logger.h"
+#include "network.h"
+#include "quassel.h"
int SqliteStorage::_maxRetryCount = 150; // yes this is a large number... only other way to "handle" this is bailing out...
return AbstractSqlStorage::installedSchemaVersion();
}
+bool SqliteStorage::updateSchemaVersion(int newVersion) {
+ QSqlQuery query(logDb());
+ query.prepare("UPDATE coreinfo SET value = :version WHERE key = 'schemaversion'");
+ query.bindValue(":version", newVersion);
+ query.exec();
+
+ bool success = true;
+ if(query.lastError().isValid()) {
+ qCritical() << "SqliteStorage::updateSchemaVersion(int): Updating schema version failed!";
+ success = false;
+ }
+ return success;
+}
+
+bool SqliteStorage::setupSchemaVersion(int version) {
+ QSqlQuery query(logDb());
+ query.prepare("INSERT INTO coreinfo (key, value) VALUES ('schemaversion', :version)");
+ query.bindValue(":version", version);
+ query.exec();
+
+ bool success = true;
+ if(query.lastError().isValid()) {
+ qCritical() << "SqliteStorage::setupSchemaVersion(int): Updating schema version failed!";
+ success = false;
+ }
+ return success;
+}
+
UserId SqliteStorage::addUser(const QString &user, const QString &password) {
QSqlQuery query(logDb());
query.prepare(queryString("insert_quasseluser"));
#endif
query.bindValue(":identityid", identity.id().toInt());
safeExec(query);
+ watchQuery(query);
QSqlQuery deleteNickQuery(logDb());
deleteNickQuery.prepare(queryString("delete_nicks"));
deleteNickQuery.bindValue(":identityid", identity.id().toInt());
safeExec(deleteNickQuery);
+ watchQuery(deleteNickQuery);
QSqlQuery insertNickQuery(logDb());
insertNickQuery.prepare(queryString("insert_nick"));
insertNickQuery.bindValue(":identityid", identity.id().toInt());
insertNickQuery.bindValue(":nick", nick);
safeExec(insertNickQuery);
+ watchQuery(insertNickQuery);
}
return true;
watchQuery(query);
}
+QString SqliteStorage::awayMessage(UserId user, NetworkId networkId) {
+ QSqlQuery query(logDb());
+ query.prepare(queryString("select_network_awaymsg"));
+ query.bindValue(":userid", user.toInt());
+ query.bindValue(":networkid", networkId.toInt());
+ safeExec(query);
+ watchQuery(query);
+ QString awayMsg;
+ if(query.first())
+ awayMsg = query.value(0).toString();
+ return awayMsg;
+}
+
+void SqliteStorage::setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) {
+ QSqlQuery query(logDb());
+ query.prepare(queryString("update_network_set_awaymsg"));
+ query.bindValue(":userid", user.toInt());
+ query.bindValue(":networkid", networkId.toInt());
+ query.bindValue(":awaymsg", awayMsg);
+ safeExec(query);
+ watchQuery(query);
+}
+
+QString SqliteStorage::userModes(UserId user, NetworkId networkId) {
+ QSqlQuery query(logDb());
+ query.prepare(queryString("select_network_usermode"));
+ query.bindValue(":userid", user.toInt());
+ query.bindValue(":networkid", networkId.toInt());
+ safeExec(query);
+ watchQuery(query);
+ QString modes;
+ if(query.first())
+ modes = query.value(0).toString();
+ return modes;
+}
+
+void SqliteStorage::setUserModes(UserId user, NetworkId networkId, const QString &userModes) {
+ QSqlQuery query(logDb());
+ query.prepare(queryString("update_network_set_usermode"));
+ query.bindValue(":userid", user.toInt());
+ query.bindValue(":networkid", networkId.toInt());
+ query.bindValue(":usermode", userModes);
+ safeExec(query);
+ watchQuery(query);
+}
void SqliteStorage::createBuffer(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer) {
QSqlQuery query(logDb());
watchQuery(query);
}
-BufferInfo SqliteStorage::getBufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer) {
+BufferInfo SqliteStorage::bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer, bool create) {
QSqlQuery query(logDb());
query.prepare(queryString("select_bufferByName"));
query.bindValue(":networkid", networkId.toInt());
safeExec(query);
if(!query.first()) {
+ if(!create)
+ return BufferInfo();
+
createBuffer(user, networkId, type, buffer);
safeExec(query);
if(!query.first()) {
return true;
}
-BufferId SqliteStorage::renameBuffer(const UserId &user, const NetworkId &networkId, const QString &newName, const QString &oldName) {
- // check if such a buffer exists...
- QSqlQuery existsQuery(logDb());
- existsQuery.prepare(queryString("select_bufferByName"));
- existsQuery.bindValue(":networkid", networkId.toInt());
- existsQuery.bindValue(":userid", user.toInt());
- existsQuery.bindValue(":buffercname", oldName.toLower());
- safeExec(existsQuery);
- if(!watchQuery(existsQuery))
+bool SqliteStorage::renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) {
+ if(!isValidBuffer(user, bufferId))
return false;
- if(!existsQuery.first())
+ QSqlQuery query(logDb());
+ query.prepare(queryString("update_buffer_name"));
+ query.bindValue(":buffername", newName);
+ query.bindValue(":buffercname", newName.toLower());
+ query.bindValue(":bufferid", bufferId.toInt());
+ safeExec(query);
+ if(query.lastError().isValid()) {
+ // unexepcted error occured (19 == constraint violation)
+ if(query.lastError().number() != 19)
+ watchQuery(query);
return false;
+ }
- const int bufferid = existsQuery.value(0).toInt();
-
- Q_ASSERT(!existsQuery.next());
+ return true;
+}
- // ... and if the new name is still free.
- existsQuery.bindValue(":networkid", networkId.toInt());
- existsQuery.bindValue(":userid", user.toInt());
- existsQuery.bindValue(":buffercname", newName.toLower());
- safeExec(existsQuery);
- if(!watchQuery(existsQuery))
+bool SqliteStorage::mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) {
+ if(!isValidBuffer(user, bufferId1) || !isValidBuffer(user, bufferId2))
return false;
- if(existsQuery.first())
+ QSqlQuery query(logDb());
+ query.prepare(queryString("update_backlog_bufferid"));
+ query.bindValue(":oldbufferid", bufferId2.toInt());
+ query.bindValue(":newbufferid", bufferId1.toInt());
+ safeExec(query);
+ if(!watchQuery(query))
return false;
- QSqlQuery renameBufferQuery(logDb());
- renameBufferQuery.prepare(queryString("update_buffer_name"));
- renameBufferQuery.bindValue(":buffername", newName);
- renameBufferQuery.bindValue(":buffercname", newName.toLower());
- renameBufferQuery.bindValue(":bufferid", bufferid);
- safeExec(renameBufferQuery);
- if(watchQuery(existsQuery))
- return BufferId(bufferid);
- else
- return BufferId();
+ QSqlQuery delBufferQuery(logDb());
+ delBufferQuery.prepare(queryString("delete_buffer_for_bufferid"));
+ delBufferQuery.bindValue(":bufferid", bufferId2.toInt());
+ safeExec(delBufferQuery);
+ watchQuery(delBufferQuery);
+
+ return true;
}
void SqliteStorage::setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) {
return lastSeenHash;
}
-MsgId SqliteStorage::logMessage(Message msg) {
+bool SqliteStorage::logMessage(Message &msg) {
QSqlQuery logMessageQuery(logDb());
logMessageQuery.prepare(queryString("insert_message"));
safeExec(addSenderQuery);
safeExec(logMessageQuery);
if(!watchQuery(logMessageQuery))
- return 0;
+ return false;
} else {
watchQuery(logMessageQuery);
}
}
MsgId msgId = logMessageQuery.lastInsertId().toInt();
- Q_ASSERT(msgId.isValid());
- return msgId;
+ if(msgId.isValid()) {
+ msg.setMsgId(msgId);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool SqliteStorage::logMessages(MessageList &msgs) {
+ // FIXME: optimize!
+ for(int i = 0; i < msgs.count(); i++) {
+ if(!logMessage(msgs[i]))
+ return false;
+ }
+ return true;
}
QList<Message> SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) {
return messagelist;
QSqlQuery query(logDb());
- if(last == -1) {
- query.prepare(queryString("select_messagesNew"));
+
+ if(last == -1 && first == -1) {
+ query.prepare(queryString("select_messagesNewestK"));
+ } else if(last == -1) {
+ query.prepare(queryString("select_messagesNewerThan"));
+ query.bindValue(":firstmsg", first.toInt());
} else {
query.prepare(queryString("select_messages"));
query.bindValue(":lastmsg", last.toInt());
+ query.bindValue(":firstmsg", first.toInt());
}
query.bindValue(":bufferid", bufferId.toInt());
- query.bindValue(":firstmsg", first.toInt());
query.bindValue(":limit", limit);
safeExec(query);
}
QString SqliteStorage::backlogFile() {
- return quasselDir().absolutePath() + "/quassel-storage.sqlite";
+ return Quassel::configDirPath() + "quassel-storage.sqlite";
}
bool SqliteStorage::safeExec(QSqlQuery &query, int retryCount) {
return false;
}
}
+
+
+// ========================================
+// SqliteMigration
+// ========================================
+SqliteMigrationReader::SqliteMigrationReader()
+ : SqliteStorage(),
+ _maxId(0)
+{
+}
+
+void SqliteMigrationReader::setMaxId(MigrationObject mo) {
+ QString queryString;
+ switch(mo) {
+ case Sender:
+ queryString = "SELECT max(senderid) FROM sender";
+ break;
+ case Backlog:
+ queryString = "SELECT max(messageid) FROM backlog";
+ break;
+ default:
+ _maxId = 0;
+ return;
+ }
+ QSqlQuery query = logDb().exec(queryString);
+ query.first();
+ _maxId = query.value(0).toInt();
+}
+
+bool SqliteMigrationReader::prepareQuery(MigrationObject mo) {
+ setMaxId(mo);
+
+ switch(mo) {
+ case QuasselUser:
+ newQuery(queryString("migrate_read_quasseluser"), logDb());
+ break;
+ case Identity:
+ newQuery(queryString("migrate_read_identity"), logDb());
+ break;
+ case IdentityNick:
+ newQuery(queryString("migrate_read_identity_nick"), logDb());
+ break;
+ case Network:
+ newQuery(queryString("migrate_read_network"), logDb());
+ break;
+ case Buffer:
+ newQuery(queryString("migrate_read_buffer"), logDb());
+ break;
+ case Sender:
+ newQuery(queryString("migrate_read_sender"), logDb());
+ bindValue(0, 0);
+ bindValue(1, stepSize());
+ break;
+ case Backlog:
+ newQuery(queryString("migrate_read_backlog"), logDb());
+ bindValue(0, 0);
+ bindValue(1, stepSize());
+ break;
+ case IrcServer:
+ newQuery(queryString("migrate_read_ircserver"), logDb());
+ break;
+ case UserSetting:
+ newQuery(queryString("migrate_read_usersetting"), logDb());
+ break;
+ }
+ return exec();
+}
+
+bool SqliteMigrationReader::readMo(QuasselUserMO &user) {
+ if(!next())
+ return false;
+
+ user.id = value(0).toInt();
+ user.username = value(1).toString();
+ user.password = value(2).toString();
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(IdentityMO &identity) {
+ if(!next())
+ return false;
+
+ identity.id = value(0).toInt();
+ identity.userid = value(1).toInt();
+ identity.identityname = value(2).toString();
+ identity.realname = value(3).toString();
+ identity.awayNick = value(4).toString();
+ identity.awayNickEnabled = value(5).toInt() == 1 ? true : false;
+ identity.awayReason = value(6).toString();
+ identity.awayReasonEnabled = value(7).toInt() == 1 ? true : false;
+ identity.autoAwayEnabled = value(8).toInt() == 1 ? true : false;
+ identity.autoAwayTime = value(9).toInt();
+ identity.autoAwayReason = value(10).toString();
+ identity.autoAwayReasonEnabled = value(11).toInt() == 1 ? true : false;
+ identity.detachAwayEnabled = value(12).toInt() == 1 ? true : false;
+ identity.detachAwayReason = value(13).toString();
+ identity.detchAwayReasonEnabled = value(14).toInt() == 1 ? true : false;
+ identity.ident = value(15).toString();
+ identity.kickReason = value(16).toString();
+ identity.partReason = value(17).toString();
+ identity.quitReason = value(18).toString();
+ identity.sslCert = value(19).toByteArray();
+ identity.sslKey = value(20).toByteArray();
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(IdentityNickMO &identityNick) {
+ if(!next())
+ return false;
+
+ identityNick.nickid = value(0).toInt();
+ identityNick.identityId = value(1).toInt();
+ identityNick.nick = value(2).toString();
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(NetworkMO &network) {
+ if(!next())
+ return false;
+
+ network.networkid = value(0).toInt();
+ network.userid = value(1).toInt();
+ network.networkname = value(2).toString();
+ network.identityid = value(3).toInt();
+ network.encodingcodec = value(4).toString();
+ network.decodingcodec = value(5).toString();
+ network.servercodec = value(6).toString();
+ network.userandomserver = value(7).toInt() == 1 ? true : false;
+ network.perform = value(8).toString();
+ network.useautoidentify = value(9).toInt() == 1 ? true : false;
+ network.autoidentifyservice = value(10).toString();
+ network.autoidentifypassword = value(11).toString();
+ network.useautoreconnect = value(12).toInt() == 1 ? true : false;
+ network.autoreconnectinterval = value(13).toInt();
+ network.autoreconnectretries = value(14).toInt();
+ network.unlimitedconnectretries = value(15).toInt() == 1 ? true : false;
+ network.rejoinchannels = value(16).toInt() == 1 ? true : false;
+ network.connected = value(17).toInt() == 1 ? true : false;
+ network.usermode = value(18).toString();
+ network.awaymessage = value(19).toString();
+ network.attachperform = value(20).toString();
+ network.detachperform = value(21).toString();
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(BufferMO &buffer) {
+ if(!next())
+ return false;
+
+ buffer.bufferid = value(0).toInt();
+ buffer.userid = value(1).toInt();
+ buffer.groupid = value(2).toInt();
+ buffer.networkid = value(3).toInt();
+ buffer.buffername = value(4).toString();
+ buffer.buffercname = value(5).toString();
+ buffer.buffertype = value(6).toInt();
+ buffer.lastseenmsgid = value(7).toInt();
+ buffer.key = value(8).toString();
+ buffer.joined = value(9).toInt() == 1 ? true : false;
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(SenderMO &sender) {
+ int skipSteps = 0;
+ while(!next()) {
+ if(sender.senderId < _maxId) {
+ bindValue(0, sender.senderId + (skipSteps * stepSize()));
+ bindValue(1, sender.senderId + ((skipSteps + 1) * stepSize()));
+ skipSteps++;
+ if(!exec())
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ sender.senderId = value(0).toInt();
+ sender.sender = value(1).toString();
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(BacklogMO &backlog) {
+ int skipSteps = 0;
+ while(!next()) {
+ if(backlog.messageid < _maxId) {
+ bindValue(0, backlog.messageid.toInt() + (skipSteps * stepSize()));
+ bindValue(1, backlog.messageid.toInt() + ((skipSteps + 1) * stepSize()));
+ skipSteps++;
+ if(!exec())
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ backlog.messageid = value(0).toInt();
+ backlog.time = QDateTime::fromTime_t(value(1).toInt());
+ backlog.bufferid = value(2).toInt();
+ backlog.type = value(3).toInt();
+ backlog.flags = value(4).toInt();
+ backlog.senderid = value(5).toInt();
+ backlog.message = value(6).toString();
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(IrcServerMO &ircserver) {
+ if(!next())
+ return false;
+
+ ircserver.serverid = value(0).toInt();
+ ircserver.userid = value(1).toInt();
+ ircserver.networkid = value(2).toInt();
+ ircserver.hostname = value(3).toString();
+ ircserver.port = value(4).toInt();
+ ircserver.password = value(5).toString();
+ ircserver.ssl = value(6).toInt() == 1 ? true : false;
+ ircserver.sslversion = value(7).toInt();
+ ircserver.useproxy = value(8).toInt() == 1 ? true : false;
+ ircserver.proxytype = value(9).toInt();
+ ircserver.proxyhost = value(10).toString();
+ ircserver.proxyport = value(11).toInt();
+ ircserver.proxyuser = value(12).toString();
+ ircserver.proxypass = value(13).toString();
+ return true;
+}
+
+bool SqliteMigrationReader::readMo(UserSettingMO &userSetting) {
+ if(!next())
+ return false;
+
+ userSetting.userid = value(0).toInt();
+ userSetting.settingname = value(1).toString();
+ userSetting.settingvalue = value(2).toByteArray();
+
+ return true;
+}