X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=DBBackends%2FRtcomEventLoggerComponents%2FTriggerDisabler.cpp;fp=DBBackends%2FRtcomEventLoggerComponents%2FTriggerDisabler.cpp;h=e7edc8e8fe7c1ea0334f16f53133f3914aa70717;hb=d270693d12f8d9c45d08c4f6f4f4151e4edf0f87;hp=0000000000000000000000000000000000000000;hpb=09cf284409d11f5269cbc106429046f993bffa68;p=qwerkisync diff --git a/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp b/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp new file mode 100644 index 0000000..e7edc8e --- /dev/null +++ b/DBBackends/RtcomEventLoggerComponents/TriggerDisabler.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2011, Jamie Thompson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see + * . + */ + +#include "TriggerDisabler.h" + +#include "Settings.h" + +#include + +#include + +#include + +static void _sqlite3ORStep(sqlite3_context *context, int numArgs, sqlite3_value **value); +static void _sqlite3ORFinal(sqlite3_context *context); +bool createSQLiteFunctions(const QSqlDatabase &db); + +using namespace DBBackends::RtcomEventLoggerComponents; + +TriggerDisabler::TriggerDisabler(const Settings &settings) + : m_Settings(settings), m_Reenabled(false) +{ + // Preserve default cache triggers + // Set up the database connection... + QSqlDatabase db(QSqlDatabase::addDatabase( "QSQLITE" )); + + db.setDatabaseName(CurrentSettings().DBPath()); + if ( ! db.open() ) + throw std::runtime_error("Cannot open database: Unable to establish database connection"); + else + { + qDebug() << "DB Opened"; + + QSqlQuery dbqGetTriggers(db); + dbqGetTriggers.setForwardOnly( true ); + + const char * sqlGetTriggers("SELECT name, sql FROM sqlite_master WHERE type = \"trigger\" AND name LIKE \"gc_update_ev_%\""); + if(dbqGetTriggers.exec(sqlGetTriggers)) + { + qDebug() << "Query OK, " << dbqGetTriggers.numRowsAffected() << " rows affected."; + + while( dbqGetTriggers.next()) + { + QString name(dbqGetTriggers.value(0).value()); + QString sqlTrigger(dbqGetTriggers.value(1).value()); + + qDebug() << "( " << name << ", " << sqlTrigger << " )"; + + Triggers().insert(name, sqlTrigger); + } + + qDebug() << Triggers().count() << " triggers found."; + + QSqlQuery dbqRemoveTriggers(db); + dbqRemoveTriggers.setForwardOnly( true ); + + const QString sqlRemoveTriggers("DROP TRIGGER "); + foreach(QString triggerName, Triggers().keys()) + { + qDebug() << "Executing: " << sqlRemoveTriggers + triggerName; + if(dbqRemoveTriggers.exec(sqlRemoveTriggers + triggerName)) + qDebug() << "Query OK, " << dbqGetTriggers.numRowsAffected() << " rows affected."; + else + qDebug() << "Query failed, " << dbqGetTriggers.numRowsAffected() << " rows affected. Error: " << dbqRemoveTriggers.lastError().text(); + } + } + else + { + qDebug() << "SQL EXEC Error: " << "EXEC query failed"; + qDebug() << "Query: " << sqlGetTriggers; + } + + qDebug() << "Closing."; + db.close(); + } + + QSqlDatabase::removeDatabase("QSQLITE"); + + return; +} + +TriggerDisabler::~TriggerDisabler() +{ + // Restore default cache triggers + if(!Reenabled()) + Reenable(); +} + +void TriggerDisabler::Reenable() +{ + // Set up the database connection... + QSqlDatabase db(QSqlDatabase::addDatabase( "QSQLITE" )); + + db.setDatabaseName(CurrentSettings().DBPath()); + if (!db.open()) + throw std::runtime_error("Cannot open database: Unable to establish database connection"); + else + { + qDebug() << "DB Opened"; + + RestoreTriggers(db); + + UpdateGroupCache(db); + + qDebug() << "Closing DB."; + db.close(); + } + + QSqlDatabase::removeDatabase( "QSQLITE" ); + + Reenabled(true); +} + +void TriggerDisabler::RestoreTriggers(QSqlDatabase &db) +{ + QSqlQuery dbqRestoreTriggers(db); + dbqRestoreTriggers.setForwardOnly( true ); + + foreach(QString triggerName, Triggers().keys()) + { + qDebug() << "Restoring trigger " << triggerName; + qDebug() << "\tSQL: " << Triggers().value(triggerName); + if(dbqRestoreTriggers.exec(Triggers().value(triggerName))) + qDebug() << "Query OK, " << dbqRestoreTriggers.numRowsAffected() << " rows affected."; + else + qDebug() << "Query failed, " << dbqRestoreTriggers.numRowsAffected() << " rows affected. Error: " << dbqRestoreTriggers.lastError().text(); + } +} + +void TriggerDisabler::UpdateGroupCache(QSqlDatabase &db) +{ + const char * sqlUpdateGroupCache( + "INSERT OR REPLACE INTO groupcache " + "SELECT id, service_id, group_uid, total, readcount, mergedflags " + "FROM events e, " + "(SELECT max(start_time) as maxdate, group_uid as maxgid, count(group_uid) as total, total(is_read) as readcount, _OR(flags) as mergedflags " + "FROM events " + "GROUP BY maxgid) maxresults " + "WHERE group_uid = maxgid AND start_time=maxresults.maxdate " + "GROUP BY group_uid"); + + QSqlQuery dbqRecalculateGroupCache(db); + dbqRecalculateGroupCache.setForwardOnly(true); + + createSQLiteFunctions(db); + + qDebug() << "Updating group cache..."; + if(dbqRecalculateGroupCache.exec(sqlUpdateGroupCache)) + { + qDebug() << "Query OK, " << dbqRecalculateGroupCache.numRowsAffected() << " rows affected."; + + while(dbqRecalculateGroupCache.next()) + { + int id(dbqRecalculateGroupCache.value(0).value()); + QString group_uid(dbqRecalculateGroupCache.value(1).value()); + int total(dbqRecalculateGroupCache.value(2).value()); + int readcount(dbqRecalculateGroupCache.value(3).value()); + int flags(dbqRecalculateGroupCache.value(4).value()); + + qDebug() << "( " << id << ", " << group_uid << ", " << total << ", " << readcount << ", " << flags << " )"; + } + } + else + { + qDebug() << "SQL EXEC Error: " << "EXEC query failed. Error: " << dbqRecalculateGroupCache.lastError().text(); + qDebug() << "Query: " << sqlUpdateGroupCache; + } +} + +bool createSQLiteFunctions(const QSqlDatabase &db) +{ + // Get handle to the driver and check it is both valid and refers to SQLite3. + QVariant v(db.driver()->handle()); + if (!v.isValid() || qstrcmp(v.typeName(), "sqlite3*") != 0) + { + qDebug() << "Cannot get a sqlite3 handle to the driver."; + return false; + } + + // Create a handler and attach functions. + sqlite3 *handler(*static_cast(v.data())); + if (!handler) + { + qDebug() << "Cannot get a sqlite3 handler."; + return false; + } + + // Check validity of the state. + if (!db.isValid()) + { + qDebug() << "Cannot create SQLite custom functions: db object is not valid."; + return false; + } + + if (!db.isOpen()) + { + qDebug() << "Cannot create SQLite custom functions: db object is not open."; + return false; + } + + if (sqlite3_create_function(handler, "_OR", 1, SQLITE_ANY, NULL, NULL, _sqlite3ORStep, _sqlite3ORFinal)) + qDebug() << "Cannot create SQLite functions: sqlite3_create_function failed."; + + return true; +} + +static void _sqlite3ORStep(sqlite3_context *context, int, sqlite3_value **value) +{ + int *result((int *)sqlite3_aggregate_context(context, sizeof(int))); + *result |= sqlite3_value_int(*value); +} + +static void _sqlite3ORFinal(sqlite3_context *context) +{ + sqlite3_result_int(context, *(int *)sqlite3_aggregate_context(context, sizeof(int))); +}