summaryrefslogtreecommitdiff
path: root/plugins/Dbx_sqlite/src/dbevents.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Dbx_sqlite/src/dbevents.cpp')
-rw-r--r--plugins/Dbx_sqlite/src/dbevents.cpp377
1 files changed, 377 insertions, 0 deletions
diff --git a/plugins/Dbx_sqlite/src/dbevents.cpp b/plugins/Dbx_sqlite/src/dbevents.cpp
new file mode 100644
index 0000000000..bff8362c41
--- /dev/null
+++ b/plugins/Dbx_sqlite/src/dbevents.cpp
@@ -0,0 +1,377 @@
+#include "stdafx.h"
+
+enum {
+ SQL_EVT_STMT_COUNT = 0,
+ SQL_EVT_STMT_ADD,
+ SQL_EVT_STMT_DELETE,
+ SQL_EVT_STMT_BLOBSIZE,
+ SQL_EVT_STMT_GET,
+ SQL_EVT_STMT_GETFLAGS,
+ SQL_EVT_STMT_SETFLAGS,
+ SQL_EVT_STMT_GETCONTACT,
+ SQL_EVT_STMT_FINDFIRST,
+ SQL_EVT_STMT_FINDFIRSTUNREAD,
+ SQL_EVT_STMT_FINDLAST,
+ SQL_EVT_STMT_FINDNEXT,
+ SQL_EVT_STMT_FINDPREV,
+ SQL_EVT_STMT_GETIDBYSRVID,
+ SQL_EVT_STMT_SETSRVID,
+ SQL_EVT_STMT_NUM
+};
+
+static char *evt_stmts[SQL_EVT_STMT_NUM] = {
+ "select count(1) from events limit 1;",
+ "insert into events values (null, ?, ?, ?, ?, ?, ?, ?);",
+ "delete from events where id = ?;",
+ "select size from events where id = ? limit 1;",
+ "select module, timestamp, flags, type, size, blob from events where id = ? limit 1;",
+ "select flags from events where id = ? limit 1;",
+ "update events set flag = ? where id = ?;",
+ "select contactid from events where id = ? limit 1;",
+ "select id from events where contactid = ? order by id limit 1;",
+ "select flags, id from events where contactid = ? order by id;",
+ "select max(id) from events where contactid = ? limit 1;",
+ "select id from events where contactid = ? and id > ? order by id limit 1;",
+ "select id from events where contactid = ? and id < ? order by id desc limit 1;",
+ "select id from events where module = ? and serverid = ? limit 1;",
+ "update events set serverid = ? where id = ?;",
+};
+
+static sqlite3_stmt *evt_stmts_prep[SQL_EVT_STMT_NUM] = { 0 };
+
+void CDbxSQLite::InitEvents()
+{
+ for (size_t i = 0; i < SQL_EVT_STMT_NUM; i++)
+ sqlite3_prepare_v3(m_db, evt_stmts[i], -1, SQLITE_PREPARE_PERSISTENT, &evt_stmts_prep[i], nullptr);
+}
+
+void CDbxSQLite::UninitEvents()
+{
+ for (size_t i = 0; i < SQL_EVT_STMT_NUM; i++)
+ sqlite3_finalize(evt_stmts_prep[i]);
+}
+
+LONG CDbxSQLite::GetEventCount(MCONTACT hContact)
+{
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_COUNT];
+ int rc = sqlite3_step(stmt);
+ int count = sqlite3_column_int(stmt, 0);
+ sqlite3_reset(stmt);
+ return count;
+}
+
+MEVENT CDbxSQLite::AddEvent(MCONTACT hContact, DBEVENTINFO *dbei)
+{
+ if (dbei == nullptr)
+ return 0;
+
+ if (dbei->timestamp == 0)
+ return 0;
+
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return 0;
+
+ if (NotifyEventHooks(hEventFilterAddedEvent, hContact, (LPARAM)dbei))
+ return 0;
+
+ MEVENT hDbEvent = 0;
+ {
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_ADD];
+ sqlite3_bind_int64(stmt, 1, hContact);
+ sqlite3_bind_text(stmt, 2, dbei->szModule, mir_strlen(dbei->szModule), nullptr);
+ sqlite3_bind_int64(stmt, 3, dbei->timestamp);
+ sqlite3_bind_int(stmt, 4, dbei->eventType);
+ sqlite3_bind_int64(stmt, 5, dbei->flags);
+ sqlite3_bind_int64(stmt, 6, dbei->cbBlob);
+ sqlite3_bind_blob(stmt, 7, dbei->pBlob, dbei->cbBlob, nullptr);
+ int rc = sqlite3_step(stmt);
+ sqlite3_reset(stmt);
+ if (rc != SQLITE_DONE)
+ return 0;
+ hDbEvent = sqlite3_last_insert_rowid(m_db);
+ }
+
+ bool neednotify;
+ if (!(dbei->flags & (DBEF_READ | DBEF_SENT)))
+ neednotify = true;
+ //else neednotify = m_safetyMode;
+
+ // notify only in safe mode or on really new events
+ if (neednotify)
+ NotifyEventHooks(hEventAddedEvent, hContact, (LPARAM)hDbEvent);
+
+ return hDbEvent;
+}
+
+BOOL CDbxSQLite::DeleteEvent(MCONTACT hContact, MEVENT hDbEvent)
+{
+ if (hDbEvent == 0)
+ return 1;
+
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return 1;
+
+ {
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_DELETE];
+ sqlite3_bind_int64(stmt, 1, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ sqlite3_reset(stmt);
+ if (rc != SQLITE_DONE)
+ return 1;
+ }
+
+ NotifyEventHooks(hEventDeletedEvent, hContact, (LPARAM)hDbEvent);
+
+ return 0;
+}
+
+LONG CDbxSQLite::GetBlobSize(MEVENT hDbEvent)
+{
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_BLOBSIZE];
+ sqlite3_bind_int(stmt, 1, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE) {
+ sqlite3_reset(stmt);
+ return -1;
+ }
+ LONG res = sqlite3_column_int64(stmt, 0);
+ sqlite3_reset(stmt);
+ return res;
+}
+
+BOOL CDbxSQLite::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei)
+{
+ if (hDbEvent == 0)
+ return 1;
+
+ if (dbei == nullptr)
+ return 1;
+
+ if (dbei->cbBlob > 0 && dbei->pBlob == nullptr) {
+ dbei->cbBlob = 0;
+ return 1;
+ }
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GET];
+ sqlite3_bind_int64(stmt, 1, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return 1;
+ }
+ dbei->szModule = (char*)sqlite3_column_text(stmt, 0);
+ dbei->timestamp = sqlite3_column_int64(stmt, 1);
+ dbei->eventType = sqlite3_column_int(stmt, 2);
+ dbei->flags = sqlite3_column_int64(stmt, 3);
+ dbei->cbBlob = sqlite3_column_int64(stmt, 4);
+ dbei->pBlob = (BYTE*)sqlite3_column_blob(stmt, 5);
+ sqlite3_reset(stmt);
+ return 0;
+}
+
+BOOL CDbxSQLite::MarkEventRead(MCONTACT hContact, MEVENT hDbEvent)
+{
+ if (hDbEvent == 0)
+ return -1;
+
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return -1;
+
+ DWORD flags = 0;
+ {
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GETFLAGS];
+ sqlite3_bind_int64(stmt, 1, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return -1;
+ }
+ flags = sqlite3_column_int64(stmt, 0);
+ sqlite3_reset(stmt);
+ }
+
+ if ((flags & DBEF_READ) == DBEF_READ)
+ return flags;
+
+ flags |= DBEF_READ;
+ {
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_SETFLAGS];
+ sqlite3_bind_int(stmt, 1, flags);
+ sqlite3_bind_int64(stmt, 2, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ sqlite3_reset(stmt);
+ if (rc != SQLITE_DONE)
+ return -1;
+ }
+
+ NotifyEventHooks(hEventMarkedRead, hContact, (LPARAM)hDbEvent);
+
+ return flags;
+}
+
+MCONTACT CDbxSQLite::GetEventContact(MEVENT hDbEvent)
+{
+ if (hDbEvent == 0)
+ return INVALID_CONTACT_ID;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GETCONTACT];
+ sqlite3_bind_int64(stmt, 1, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return INVALID_CONTACT_ID;
+ }
+ MCONTACT hContact = sqlite3_column_int64(stmt, 0);
+ sqlite3_reset(stmt);
+ return hContact;
+}
+
+MEVENT CDbxSQLite::FindFirstEvent(MCONTACT hContact)
+{
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return 0;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDFIRST];
+ sqlite3_bind_int64(stmt, 1, hContact);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return 0;
+ }
+ MEVENT hDbEvent = sqlite3_column_int64(stmt, 0);
+ sqlite3_reset(stmt);
+ return hDbEvent;
+}
+
+MEVENT CDbxSQLite::FindFirstUnreadEvent(MCONTACT hContact)
+{
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return 0;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD];
+ sqlite3_bind_int64(stmt, 1, hContact);
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ DWORD flags = sqlite3_column_int64(stmt, 0);
+ if (!(flags & (DBEF_READ | DBEF_SENT))) {
+ MEVENT hDbEvent = sqlite3_column_int64(stmt, 1);
+ sqlite3_reset(stmt);
+ return hDbEvent;
+ break;
+ }
+ }
+ sqlite3_reset(stmt);
+ return 0;
+}
+
+MEVENT CDbxSQLite::FindLastEvent(MCONTACT hContact)
+{
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return 0;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDLAST];
+ sqlite3_bind_int64(stmt, 1, hContact);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return 0;
+ }
+ MEVENT hDbEvent = sqlite3_column_int64(stmt, 0);
+ sqlite3_reset(stmt);
+ return hDbEvent;
+}
+
+MEVENT CDbxSQLite::FindNextEvent(MCONTACT hContact, MEVENT hDbEvent)
+{
+ if (hDbEvent == 0)
+ return 0;
+
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return 0;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDNEXT];
+ sqlite3_bind_int64(stmt, 1, hContact);
+ sqlite3_bind_int64(stmt, 2, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return 0;
+ }
+ hDbEvent = sqlite3_column_int64(stmt, 0);
+ sqlite3_reset(stmt);
+ return hDbEvent;
+}
+
+MEVENT CDbxSQLite::FindPrevEvent(MCONTACT hContact, MEVENT hDbEvent)
+{
+ if (hDbEvent == 0)
+ return 0;
+
+ DBCachedContact *cc = m_cache->GetCachedContact(hContact);
+ if (cc == nullptr)
+ return 0;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDPREV];
+ sqlite3_bind_int64(stmt, 1, hContact);
+ sqlite3_bind_int64(stmt, 2, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return 0;
+ }
+ hDbEvent = sqlite3_column_int64(stmt, 0);
+ sqlite3_finalize(stmt);
+ return hDbEvent;
+}
+
+MEVENT CDbxSQLite::GetEventById(LPCSTR szModule, LPCSTR szId)
+{
+ if (szModule == nullptr || szId == nullptr)
+ return 0;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GETIDBYSRVID];
+ sqlite3_bind_text(stmt, 1, szModule, mir_strlen(szModule), nullptr);
+ sqlite3_bind_text(stmt, 2, szId, mir_strlen(szId), nullptr);
+ int rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ sqlite3_reset(stmt);
+ return 0;
+ }
+ MEVENT hDbEvent = sqlite3_column_int64(stmt, 0);
+ sqlite3_reset(stmt);
+ return hDbEvent;
+}
+
+BOOL CDbxSQLite::SetEventId(LPCSTR, MEVENT hDbEvent, LPCSTR szId)
+{
+ if (hDbEvent == 0 || szId == nullptr)
+ return 1;
+
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_SETSRVID];
+ sqlite3_bind_text(stmt, 1, szId, mir_strlen(szId), nullptr);
+ sqlite3_bind_int64(stmt, 2, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ sqlite3_reset(stmt);
+ return (rc != SQLITE_DONE);
+}