}
bool PostgreSqlStorage::isAvailable() const {
+ qDebug() << QSqlDatabase::drivers();
if(!QSqlDatabase::isDriverAvailable("QPSQL")) return false;
return true;
}
return tr("PostgreSQL Turbo Bomber HD!");
}
-QVariantMap PostgreSqlStorage::setupKeys() const {
+QStringList PostgreSqlStorage::setupKeys() const {
+ QStringList keys;
+ keys << "Username"
+ << "Password"
+ << "Hostname"
+ << "Port"
+ << "Database";
+ return keys;
+}
+QVariantMap PostgreSqlStorage::setupDefaults() const {
QVariantMap map;
map["Username"] = QVariant(QString("quassel"));
- map["Password"] = QVariant(QString());
map["Hostname"] = QVariant(QString("localhost"));
map["Port"] = QVariant(5432);
map["Database"] = QVariant(QString("quassel"));
return map;
}
-bool PostgreSqlStorage::setup(const QVariantMap &settings) {
- bool success = AbstractSqlStorage::setup(settings);
- if(success) {
- logDb().exec(QString("ALTER USER %1 SET standard_conforming_strings TO on").arg(userName()));
- }
- return success;
+void PostgreSqlStorage::initDbSession(QSqlDatabase &db) {
+ // this blows... but unfortunately Qt's PG driver forces us to this...
+ db.exec("set standard_conforming_strings = off");
+ db.exec("set escape_string_warning = off");
}
void PostgreSqlStorage::setConnectionProperties(const QVariantMap &properties) {
return uid;
}
-void PostgreSqlStorage::updateUser(UserId user, const QString &password) {
+bool PostgreSqlStorage::updateUser(UserId user, const QString &password) {
QSqlQuery query(logDb());
query.prepare(queryString("update_userpassword"));
query.bindValue(":userid", user.toInt());
query.bindValue(":password", cryptedPassword(password));
safeExec(query);
+ return query.numRowsAffected() != 0;
}
void PostgreSqlStorage::renameUser(UserId user, const QString &newName) {
}
}
+UserId PostgreSqlStorage::getUserId(const QString &user) {
+ QSqlQuery query(logDb());
+ query.prepare(queryString("select_userid"));
+ query.bindValue(":username", user);
+ safeExec(query);
+
+ if(query.first()) {
+ return query.value(0).toInt();
+ } else {
+ return 0;
+ }
+}
+
UserId PostgreSqlStorage::internalUser() {
QSqlQuery query(logDb());
query.prepare(queryString("select_internaluser"));
}
if(!db.commit()) {
- qWarning() << "PostgreSqlStorage::updateNetwork(): commiting data failed!";
+ qWarning() << "PostgreSqlStorage::createNetwork(): commiting data failed!";
qWarning() << " -" << qPrintable(db.lastError().text());
return NetworkId();
}
void PostgreSqlStorage::bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info) {
query.bindValue(":networkname", info.networkName);
- query.bindValue(":identityid", info.identity.toInt());
+ query.bindValue(":identityid", info.identity.isValid() ? info.identity.toInt() : QVariant());
query.bindValue(":encodingcodec", QString(info.codecForEncoding));
query.bindValue(":decodingcodec", QString(info.codecForDecoding));
query.bindValue(":servercodec", QString(info.codecForServer));
createQuery.bindValue(":buffertype", (int)type);
createQuery.bindValue(":buffername", buffer);
createQuery.bindValue(":buffercname", buffer.toLower());
+ createQuery.bindValue(":joined", type & BufferInfo::ChannelBuffer ? true : false);
+
safeExec(createQuery);
if(createQuery.lastError().isValid()) {
return false;
case 1:
db.commit();
- return false;
+ return true;
default:
// there was more then one buffer deleted...
qWarning() << "PostgreSqlStorage::removeBuffer(): Userid" << user << "BufferId" << "caused deletion of" << numRows << "Buffers! Rolling back transaction...";
return false;
case 1:
db.commit();
- return false;
+ return true;
default:
// there was more then one buffer deleted...
qWarning() << "PostgreSqlStorage::renameBuffer(): Userid" << user << "BufferId" << "affected" << numRows << "Buffers! Rolling back transaction...";
}
QSqlQuery checkQuery(db);
- checkQuery.prepare("SELECT count(*) FROM buffer"
+ checkQuery.prepare("SELECT count(*) FROM buffer "
"WHERE userid = :userid AND bufferid IN (:buffer1, :buffer2)");
checkQuery.bindValue(":userid", user.toInt());
checkQuery.bindValue(":buffer1", bufferId1.toInt());
return lastSeenHash;
}
+void PostgreSqlStorage::setBufferMarkerLineMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) {
+ QSqlQuery query(logDb());
+ query.prepare(queryString("update_buffer_markerlinemsgid"));
+
+ query.bindValue(":userid", user.toInt());
+ query.bindValue(":bufferid", bufferId.toInt());
+ query.bindValue(":lastseenmsgid", msgId.toInt());
+ safeExec(query);
+ watchQuery(query);
+}
+
+QHash<BufferId, MsgId> PostgreSqlStorage::bufferMarkerLineMsgIds(UserId user) {
+ QHash<BufferId, MsgId> markerLineHash;
+
+ QSqlDatabase db = logDb();
+ if(!beginReadOnlyTransaction(db)) {
+ qWarning() << "PostgreSqlStorage::bufferMarkerLineMsgIds(): cannot start read only transaction!";
+ qWarning() << " -" << qPrintable(db.lastError().text());
+ return markerLineHash;
+ }
+
+ QSqlQuery query(db);
+ query.prepare(queryString("select_buffer_markerlinemsgids"));
+ query.bindValue(":userid", user.toInt());
+ safeExec(query);
+ if(!watchQuery(query)) {
+ db.rollback();
+ return markerLineHash;
+ }
+
+ while(query.next()) {
+ markerLineHash[query.value(0).toInt()] = query.value(1).toInt();
+ }
+
+ db.commit();
+ return markerLineHash;
+}
+
bool PostgreSqlStorage::logMessage(Message &msg) {
QSqlDatabase db = logDb();
if(!db.transaction()) {
return messagelist;
}
- QSqlQuery query(db);
+ QString queryName;
+ QVariantList params;
if(last == -1 && first == -1) {
- query.prepare(queryString("select_messages"));
+ queryName = "select_messages";
} else if(last == -1) {
- query.prepare(queryString("select_messagesNewerThan"));
- query.bindValue(":firstmsg", first.toInt());
+ queryName = "select_messagesNewerThan";
+ params << first.toInt();
} else {
- query.prepare(queryString("select_messagesRange"));
- query.bindValue(":lastmsg", last.toInt());
- query.bindValue(":firstmsg", first.toInt());
+ queryName = "select_messagesRange";
+ params << first.toInt();
+ params << last.toInt();
}
- query.bindValue(":bufferid", bufferId.toInt());
- safeExec(query);
+ params << bufferId.toInt();
+ if(limit != -1)
+ params << limit;
+ else
+ params << "ALL";
+
+ if(!prepareQuery(queryName, queryString(queryName), db)) {
+ qWarning() << "PostgreSqlStorage::logMessages(): unable to prepare query:" << queryString(queryName);
+ qWarning() << " Error:" << db.lastError().text();
+ db.rollback();
+ return messagelist;
+ }
+
+ QSqlQuery query = executePreparedQuery(queryName, params, db);
+
if(!watchQuery(query)) {
+ qDebug() << "select_messages failed";
db.rollback();
return messagelist;
}
QDateTime timestamp;
- for(int i = 0; i < limit && query.next(); i++) {
+ while(query.next()) {
timestamp = query.value(1).toDateTime();
timestamp.setTimeSpec(Qt::UTC);
Message msg(timestamp,
- bufferInfo,
- (Message::Type)query.value(2).toUInt(),
- query.value(5).toString(),
- query.value(4).toString(),
- (Message::Flags)query.value(3).toUInt());
+ bufferInfo,
+ (Message::Type)query.value(2).toUInt(),
+ query.value(5).toString(),
+ query.value(4).toString(),
+ (Message::Flags)query.value(3).toUInt());
msg.setMsgId(query.value(0).toInt());
messagelist << msg;
}
QSqlQuery PostgreSqlStorage::executePreparedQuery(const QString &handle, const QVariantList ¶ms, const QSqlDatabase &db) {
if(!_preparedQueries.contains(db.connectionName()) || !_preparedQueries[db.connectionName()].contains(handle)) {
qWarning() << "PostgreSqlStorage::executePreparedQuery() no prepared Query with handle" << handle << "on Database" << db.connectionName();
- return QSqlQuery();
+ return QSqlQuery(db);
}
QSqlDriver *driver = db.driver();
QSqlQuery PostgreSqlStorage::executePreparedQuery(const QString &handle, const QVariant ¶m, const QSqlDatabase &db) {
if(!_preparedQueries.contains(db.connectionName()) || !_preparedQueries[db.connectionName()].contains(handle)) {
qWarning() << "PostgreSqlStorage::executePreparedQuery() no prepared Query with handle" << handle << "on Database" << db.connectionName();
- return QSqlQuery();
+ return QSqlQuery(db);
}
QSqlField field;
db.exec(QString("DEALLOCATE %1").arg(queryId));
}
-
-
-
-
// ========================================
// PostgreSqlMigrationWriter
// ========================================
query = queryString("migrate_write_sender");
break;
case Identity:
+ _validIdentities.clear();
query = queryString("migrate_write_identity");
break;
case IdentityNick:
//bool PostgreSqlMigrationWriter::writeIdentity(const IdentityMO &identity) {
bool PostgreSqlMigrationWriter::writeMo(const IdentityMO &identity) {
+ _validIdentities << identity.id.toInt();
bindValue(0, identity.id.toInt());
bindValue(1, identity.userid.toInt());
bindValue(2, identity.identityname);
bindValue(0, network.networkid.toInt());
bindValue(1, network.userid.toInt());
bindValue(2, network.networkname);
- bindValue(3, network.identityid.toInt());
+ if(_validIdentities.contains(network.identityid.toInt()))
+ bindValue(3, network.identityid.toInt());
+ else
+ bindValue(3, QVariant());
bindValue(4, network.encodingcodec);
bindValue(5, network.decodingcodec);
bindValue(6, network.servercodec);
bindValue(5, buffer.buffercname);
bindValue(6, (int)buffer.buffertype);
bindValue(7, buffer.lastseenmsgid);
- bindValue(8, buffer.key);
- bindValue(9, buffer.joined);
+ bindValue(8, buffer.markerlinemsgid);
+ bindValue(9, buffer.key);
+ bindValue(10, buffer.joined);
return exec();
}
QSqlDatabase db = logDb();
QList<Sequence> sequences;
sequences << Sequence("backlog", "messageid")
+ << Sequence("buffer", "bufferid")
<< Sequence("identity", "identityid")
<< Sequence("identity_nick", "nickid")
<< Sequence("ircserver", "serverid")