+}
+
+
+bool AbstractSqlStorage::watchQuery(QSqlQuery &query)
+{
+ bool queryError = query.lastError().isValid();
+ if (queryError || _debug) {
+ if (queryError)
+ qCritical() << "unhandled Error in QSqlQuery!";
+ qCritical() << " last Query:\n" << qPrintable(query.lastQuery());
+ qCritical() << " executed Query:\n" << qPrintable(query.executedQuery());
+ QVariantMap boundValues = query.boundValues();
+ QStringList valueStrings;
+ QVariantMap::const_iterator iter;
+ for (iter = boundValues.constBegin(); iter != boundValues.constEnd(); iter++) {
+ QString value;
+ QSqlField field;
+ if (query.driver()) {
+ // let the driver do the formatting
+ field.setType(iter.value().type());
+ if (iter.value().isNull())
+ field.clear();
+ else
+ field.setValue(iter.value());
+ value = query.driver()->formatValue(field);
+ }
+ else {
+ switch (iter.value().type()) {
+ case QVariant::Invalid:
+ value = "NULL";
+ break;
+ case QVariant::Int:
+ value = iter.value().toString();
+ break;
+ default:
+ value = QString("'%1'").arg(iter.value().toString());
+ }
+ }
+ valueStrings << QString("%1=%2").arg(iter.key(), value);
+ }
+ qCritical() << " bound Values:" << qPrintable(valueStrings.join(", "));
+ qCritical() << " Error Number:" << query.lastError().number();
+ qCritical() << " Error Message:" << qPrintable(query.lastError().text());
+ qCritical() << " Driver Message:" << qPrintable(query.lastError().driverText());
+ qCritical() << " DB Message:" << qPrintable(query.lastError().databaseText());
+
+ return !queryError;
+ }
+ return true;
+}
+
+
+void AbstractSqlStorage::connectionDestroyed()
+{
+ QMutexLocker locker(&_connectionPoolMutex);
+ _connectionPool.remove(sender()->thread());
+}
+
+
+// ========================================
+// AbstractSqlStorage::Connection
+// ========================================
+AbstractSqlStorage::Connection::Connection(const QString &name, QObject *parent)
+ : QObject(parent),
+ _name(name.toLatin1())
+{
+}
+
+
+AbstractSqlStorage::Connection::~Connection()
+{
+ {
+ QSqlDatabase db = QSqlDatabase::database(name(), false);
+ if (db.isOpen()) {
+ db.commit();
+ db.close();
+ }
+ }
+ QSqlDatabase::removeDatabase(name());
+}
+
+
+// ========================================
+// AbstractSqlMigrator
+// ========================================
+AbstractSqlMigrator::AbstractSqlMigrator()
+ : _query(0)
+{
+}
+
+
+void AbstractSqlMigrator::newQuery(const QString &query, QSqlDatabase db)
+{
+ Q_ASSERT(!_query);
+ _query = new QSqlQuery(db);
+ _query->prepare(query);
+}
+
+
+void AbstractSqlMigrator::resetQuery()
+{
+ delete _query;
+ _query = 0;
+}
+
+
+bool AbstractSqlMigrator::exec()
+{
+ Q_ASSERT(_query);
+ _query->exec();
+ return !_query->lastError().isValid();
+}
+
+
+QString AbstractSqlMigrator::migrationObject(MigrationObject moType)
+{
+ switch (moType) {
+ case QuasselUser:
+ return "QuasselUser";
+ case Sender:
+ return "Sender";
+ case Identity:
+ return "Identity";
+ case IdentityNick:
+ return "IdentityNick";
+ case Network:
+ return "Network";
+ case Buffer:
+ return "Buffer";
+ case Backlog:
+ return "Backlog";
+ case IrcServer:
+ return "IrcServer";
+ case UserSetting:
+ return "UserSetting";
+ };
+ return QString();
+}
+
+
+QVariantList AbstractSqlMigrator::boundValues()
+{
+ QVariantList values;
+ if (!_query)
+ return values;
+
+ int numValues = _query->boundValues().count();
+ for (int i = 0; i < numValues; i++) {
+ values << _query->boundValue(i);
+ }
+ return values;
+}
+
+
+void AbstractSqlMigrator::dumpStatus()
+{
+ qWarning() << " executed Query:";
+ qWarning() << qPrintable(executedQuery());
+ qWarning() << " bound Values:";
+ QList<QVariant> list = boundValues();
+ for (int i = 0; i < list.size(); ++i)
+ qWarning() << i << ": " << list.at(i).toString().toAscii().data();
+ qWarning() << " Error Number:" << lastError().number();
+ qWarning() << " Error Message:" << lastError().text();
+}
+
+
+// ========================================
+// AbstractSqlMigrationReader
+// ========================================
+AbstractSqlMigrationReader::AbstractSqlMigrationReader()
+ : AbstractSqlMigrator(),
+ _writer(0)
+{
+}
+
+
+bool AbstractSqlMigrationReader::migrateTo(AbstractSqlMigrationWriter *writer)
+{
+ if (!transaction()) {
+ qWarning() << "AbstractSqlMigrationReader::migrateTo(): unable to start reader's transaction!";
+ return false;
+ }
+ if (!writer->transaction()) {
+ qWarning() << "AbstractSqlMigrationReader::migrateTo(): unable to start writer's transaction!";
+ rollback(); // close the reader transaction;
+ return false;
+ }
+
+ _writer = writer;