summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/Dbx_sqlite/src/dbcontacts.cpp84
-rw-r--r--plugins/Dbx_sqlite/src/dbevents.cpp349
-rw-r--r--plugins/Dbx_sqlite/src/dbintf.cpp12
-rw-r--r--plugins/Dbx_sqlite/src/dbintf.h22
-rw-r--r--plugins/Dbx_sqlite/src/version.h2
5 files changed, 358 insertions, 111 deletions
diff --git a/plugins/Dbx_sqlite/src/dbcontacts.cpp b/plugins/Dbx_sqlite/src/dbcontacts.cpp
index 63347e74c4..ad4ed0ec7c 100644
--- a/plugins/Dbx_sqlite/src/dbcontacts.cpp
+++ b/plugins/Dbx_sqlite/src/dbcontacts.cpp
@@ -21,14 +21,14 @@ void CDbxSQLite::InitContacts()
sqlite3_prepare_v3(m_db, ctc_stmts[i], -1, SQLITE_PREPARE_PERSISTENT, &ctc_stmts_prep[i], nullptr);
sqlite3_stmt *stmt = nullptr;
- sqlite3_prepare_v2(m_db, "select contacts.id, count(event_id) from contacts left join contact_events on contact_events.contact_id = contacts.id group by contacts.id;", -1, &stmt, nullptr);
+ sqlite3_prepare_v2(m_db, "select contacts.id, count(events.id) from contacts left join events on events.contact_id = contacts.id group by contacts.id;", -1, &stmt, nullptr);
int rc = 0;
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
MCONTACT hContact = sqlite3_column_int64(stmt, 0);
DBCachedContact *cc = (hContact)
? m_cache->AddContactToCache(hContact)
: &m_system;
- cc->count = sqlite3_column_int64(stmt, 1);
+ cc->m_count = sqlite3_column_int64(stmt, 1);
DBVARIANT dbv = { DBVT_DWORD };
cc->nSubs = (0 != GetContactSetting(cc->contactID, META_PROTO, "NumContacts", &dbv)) ? -1 : dbv.dVal;
@@ -119,3 +119,83 @@ LONG CDbxSQLite::GetContactSize(void)
{
return sizeof(DBCachedContact);
}
+
+/////////////////////////////////////
+
+bool DBCachedContact::HasCount() const
+{
+ return m_count > -1;
+}
+
+void DBCachedContact::AddEvent(MEVENT hDbEvent, uint32_t timestamp, bool unread)
+{
+ m_count = HasCount()
+ ? m_count + 1
+ : 1;
+ if (m_firstTimestamp > timestamp) {
+ m_first = hDbEvent;
+ m_firstTimestamp = timestamp;
+ }
+ if (unread && m_unreadTimestamp > timestamp) {
+ m_unread = hDbEvent;
+ m_unreadTimestamp = timestamp;
+ }
+ if (m_lastTimestamp <= timestamp) {
+ m_last = hDbEvent;
+ m_lastTimestamp = timestamp;
+ }
+}
+
+void DBCachedContact::EditEvent(MEVENT hDbEvent, uint32_t timestamp, bool unread)
+{
+ if (m_first = hDbEvent && m_firstTimestamp != timestamp) {
+ m_first = 0;
+ m_firstTimestamp = 0;
+ }
+ else if (m_firstTimestamp > timestamp) {
+ m_first = hDbEvent;
+ m_firstTimestamp = timestamp;
+ }
+ if (m_unread = hDbEvent && (!unread || m_unreadTimestamp != timestamp)) {
+ m_unread = 0;
+ m_unreadTimestamp = 0;
+ }
+ else if (unread && m_unreadTimestamp > timestamp) {
+ m_unread = hDbEvent;
+ m_unreadTimestamp = timestamp;
+ }
+ if (m_last = hDbEvent && m_lastTimestamp != timestamp) {
+ m_last = 0;
+ m_lastTimestamp = 0;
+ }
+ else if (m_lastTimestamp <= timestamp) {
+ m_last = hDbEvent;
+ m_lastTimestamp = timestamp;
+ }
+}
+
+void DBCachedContact::DeleteEvent(MEVENT hDbEvent)
+{
+ if (m_count > 0)
+ m_count--;
+ if (m_first == hDbEvent) {
+ m_first = 0;
+ m_firstTimestamp = 0;
+ }
+ if (m_unread == hDbEvent) {
+ m_unread = 0;
+ m_unreadTimestamp = 0;
+ }
+ if (m_last == hDbEvent) {
+ m_last = 0;
+ m_lastTimestamp = 0;
+ }
+}
+
+void DBCachedContact::MarkRead(MEVENT hDbEvent)
+{
+ if (m_unread == hDbEvent) {
+ m_unread = 0;
+ m_unreadTimestamp = 0;
+ }
+}
diff --git a/plugins/Dbx_sqlite/src/dbevents.cpp b/plugins/Dbx_sqlite/src/dbevents.cpp
index 3718b37817..762343c4b9 100644
--- a/plugins/Dbx_sqlite/src/dbevents.cpp
+++ b/plugins/Dbx_sqlite/src/dbevents.cpp
@@ -3,7 +3,6 @@
enum {
SQL_EVT_STMT_COUNT = 0,
SQL_EVT_STMT_ADDEVENT,
- SQL_EVT_STMT_ADDCONTACTEVENT,
SQL_EVT_STMT_DELETE,
SQL_EVT_STMT_EDIT,
SQL_EVT_STMT_BLOBSIZE,
@@ -24,22 +23,21 @@ enum {
};
static char *evt_stmts[SQL_EVT_STMT_NUM] = {
- "select count(1) from contact_events where contact_id = ? limit 1;",
- "insert into events(module, timestamp, type, flags, size, data) values (?, ?, ?, ?, ?, ?);",
- "insert into contact_events(contact_id, event_id, timestamp) values (?, ?, ?);",
- "delete from contact_events where contact_id = ?1 and event_id = ?2; delete from events where id = ?2;",
+ "select count(1) from events where contact_id = ? limit 1;",
+ "insert into events(contact_id, module, timestamp, type, flags, size, data) values (?, ?, ?, ?, ?, ?, ?);",
+ "delete from events where id = ?;",
"update events set module = ?, timestamp = ?, type = ?, flags = ?, size = ?, blob = ? where id = ?;",
"select size from events where id = ? limit 1;",
"select module, timestamp, type, flags, size, data from events where id = ? limit 1;",
"select flags from events where id = ? limit 1;",
"update events set flags = ? where id = ?;",
- "select contact_id from contact_events where event_id = ? limit 1;",
- "select event_id from contact_events where contact_id = ? order by timestamp, event_id limit 1;",
- "select events.id from events join contact_events on contact_events.event_id = events.id where contact_events.contact_id = ? and (events.flags & ?) = 0 order by events.timestamp, events.id limit 1;",
- "select event_id from contact_events where contact_id = ? order by timestamp desc, event_id desc limit 1;",
- "select event_id from contact_events where contact_id = ?1 and event_id <> ?2 and timestamp > (select timestamp from contact_events where contact_id = ?1 and event_id = ?2 limit 1) order by timestamp, event_id limit 1;",
- "select event_id from contact_events where contact_id = ? and event_id <> ? and timestamp < (select timestamp from contact_events where contact_id = ?1 and event_id = ?2 limit 1) order by timestamp desc, event_id desc limit 1;",
- "select id from events where module = ? and server_id = ? limit 1;",
+ "select contact_id from events where id = ? limit 1;",
+ "select id, timestamp from events where contact_id = ? order by timestamp, id limit 1;",
+ "select id, timestamp from events where contact_id = ? and (flags & ?) = 0 order by timestamp, id limit 1;",
+ "select id, timestamp from events where contact_id = ? order by timestamp desc, id desc limit 1;",
+ "select id, timestamp from events where contact_id = ?1 and id <> ?2 and timestamp > (select timestamp from events where contact_id = ?1 and id = ?2 limit 1) order by timestamp, id limit 1;",
+ "select id, timestamp from events where contact_id = ?1 and id <> ?2 and timestamp < (select timestamp from events where contact_id = ?1 and id = ?2 limit 1) order by timestamp desc, id desc limit 1;",
+ "select id, timestamp from events where module = ? and server_id = ? limit 1;",
"update events set server_id = ? where id = ?;",
"insert into contact_events(contact_id, event_id, timestamp) select ?1, event_id, timestamp from contact_events where contact_id = ?2 order by timestamp, event_id;",
"delete from contact_events where contact_id = ? and event_id in (select event_id from contact_events where contact_id = ?);",
@@ -81,10 +79,36 @@ LONG CDbxSQLite::GetEventCount(MCONTACT hContact)
? m_cache->GetCachedContact(hContact)
: &m_system;
- if (cc->count)
- return cc->count;
+ if (cc->HasCount())
+ return cc->m_count;
mir_cslock lock(m_csDbAccess);
+
+ if (cc->IsMeta()) {
+ if (cc->nSubs == 0) {
+ cc->m_count = 0;
+ return 0;
+ }
+
+ CMStringA query = "select count(1) from events where contact_id in (";
+ for (int k = 0; k < cc->nSubs; k++)
+ query.AppendFormat("%lu, ", cc->pSubs[k]);
+ query.Delete(query.GetLength() - 2, 2);
+ query.Append(") limit 1;");
+
+ sqlite3_stmt *stmt = nullptr;
+ sqlite3_prepare_v2(m_db, query, -1, &stmt, nullptr);
+ int rc = sqlite3_step(stmt);
+ assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
+ if (rc != SQLITE_ROW) {
+ sqlite3_finalize(stmt);
+ return 0;
+ }
+ cc->m_count = sqlite3_column_int64(stmt, 0);
+ sqlite3_finalize(stmt);
+ return cc->m_count;
+ }
+
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_COUNT];
sqlite3_bind_int64(stmt, 1, hContact);
int rc = sqlite3_step(stmt);
@@ -93,9 +117,10 @@ LONG CDbxSQLite::GetEventCount(MCONTACT hContact)
sqlite3_reset(stmt);
return 0;
}
- cc->count = sqlite3_column_int64(stmt, 0);
+ cc->m_count = sqlite3_column_int64(stmt, 0);
sqlite3_reset(stmt);
- return cc->count;
+
+ return cc->m_count;
}
MEVENT CDbxSQLite::AddEvent(MCONTACT hContact, DBEVENTINFO *dbei)
@@ -120,7 +145,6 @@ MEVENT CDbxSQLite::AddEvent(MCONTACT hContact, DBEVENTINFO *dbei)
// set default sub to the event's source
if (!(dbei->flags & DBEF_SENT))
db_mc_setDefault(cc->contactID, hContact, false);
- hContact = cc->contactID; // and add an event to a metahistory
if (db_mc_isEnabled())
hNotifyContact = hContact;
}
@@ -136,57 +160,28 @@ MEVENT CDbxSQLite::AddEvent(MCONTACT hContact, DBEVENTINFO *dbei)
MEVENT hDbEvent = 0;
{
- sqlite3_exec(m_db, "begin transaction;", nullptr, nullptr, nullptr);
-
mir_cslock lock(m_csDbAccess);
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_ADDEVENT];
- sqlite3_bind_text(stmt, 1, dbei->szModule, mir_strlen(dbei->szModule), nullptr);
- sqlite3_bind_int64(stmt, 2, dbei->timestamp);
- sqlite3_bind_int(stmt, 3, dbei->eventType);
- sqlite3_bind_int64(stmt, 4, dbei->flags);
- sqlite3_bind_int64(stmt, 5, dbei->cbBlob);
- sqlite3_bind_blob(stmt, 6, dbei->pBlob, dbei->cbBlob, nullptr);
+ 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);
assert(rc == SQLITE_DONE);
sqlite3_reset(stmt);
- if (rc != SQLITE_DONE) {
- sqlite3_exec(m_db, "rollback;", nullptr, nullptr, nullptr);
- return 0;
- }
+
hDbEvent = sqlite3_last_insert_rowid(m_db);
- stmt = evt_stmts_prep[SQL_EVT_STMT_ADDCONTACTEVENT];
- sqlite3_bind_int64(stmt, 1, hContact);
- sqlite3_bind_int64(stmt, 2, hDbEvent);
- sqlite3_bind_int64(stmt, 3, dbei->timestamp);
- rc = sqlite3_step(stmt);
- assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
- sqlite3_reset(stmt);
- if (rc != SQLITE_DONE) {
- sqlite3_exec(m_db, "rollback;", nullptr, nullptr, nullptr);
- return 0;
- }
+ cc->AddEvent(hDbEvent, dbei->timestamp, !dbei->markedRead());
+ if (ccSub != nullptr)
+ ccSub->AddEvent(hDbEvent, dbei->timestamp, !dbei->markedRead());
- // insert an event into a sub's history too
- if (ccSub != nullptr) {
- sqlite3_bind_int64(stmt, 1, ccSub->contactID);
- sqlite3_bind_int64(stmt, 2, hDbEvent);
- sqlite3_bind_int64(stmt, 3, dbei->timestamp);
- rc = sqlite3_step(stmt);
- assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
- sqlite3_reset(stmt);
- if (rc != SQLITE_DONE) {
- sqlite3_exec(m_db, "rollback;", nullptr, nullptr, nullptr);
- return 0;
- }
- }
-
- sqlite3_exec(m_db, "commit;", nullptr, nullptr, nullptr);
-
- cc->count++;
- cc->first = cc->last = 0;
- if (!dbei->markedRead())
- cc->unread = 0;
+ char *module = m_modules.find(dbei->szModule);
+ if (module == nullptr)
+ m_modules.insert(mir_strdup(dbei->szModule));
}
if (m_safetyMode)
@@ -217,10 +212,9 @@ BOOL CDbxSQLite::DeleteEvent(MCONTACT hContact, MEVENT hDbEvent)
if (rc != SQLITE_DONE)
return 1;
- if (cc->count > 0)
- cc->count--;
-
- cc->first = cc->unread = cc->last = 0;
+ cc->DeleteEvent(hDbEvent);
+ if (cc->IsSub() && (cc = m_cache->GetCachedContact(cc->parentID)))
+ cc->DeleteEvent(hDbEvent);
}
NotifyEventHooks(g_hevEventDeleted, hContact, (LPARAM)hDbEvent);
@@ -242,23 +236,31 @@ BOOL CDbxSQLite::EditEvent(MCONTACT hContact, MEVENT hDbEvent, DBEVENTINFO *dbei
if (cc == nullptr)
return 1;
- mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_EDIT];
- sqlite3_bind_text(stmt, 1, dbei->szModule, mir_strlen(dbei->szModule), nullptr);
- sqlite3_bind_int64(stmt, 2, dbei->timestamp);
- sqlite3_bind_int(stmt, 3, dbei->eventType);
- sqlite3_bind_int64(stmt, 4, dbei->flags);
- sqlite3_bind_int64(stmt, 5, dbei->cbBlob);
- sqlite3_bind_blob(stmt, 6, dbei->pBlob, dbei->cbBlob, nullptr);
- sqlite3_bind_int64(stmt, 7, hDbEvent);
- int rc = sqlite3_step(stmt);
- assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
- if (rc == SQLITE_DONE) {
- cc->first = cc->unread = cc->last = 0;
- NotifyEventHooks(g_hevEventEdited, hContact, (LPARAM)hDbEvent);
+ {
+ mir_cslock lock(m_csDbAccess);
+ sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_EDIT];
+ sqlite3_bind_text(stmt, 1, dbei->szModule, mir_strlen(dbei->szModule), nullptr);
+ sqlite3_bind_int64(stmt, 2, dbei->timestamp);
+ sqlite3_bind_int(stmt, 3, dbei->eventType);
+ sqlite3_bind_int64(stmt, 4, dbei->flags);
+ sqlite3_bind_int64(stmt, 5, dbei->cbBlob);
+ sqlite3_bind_blob(stmt, 6, dbei->pBlob, dbei->cbBlob, nullptr);
+ sqlite3_bind_int64(stmt, 7, hDbEvent);
+ int rc = sqlite3_step(stmt);
+ assert(rc == SQLITE_DONE);
+ sqlite3_reset(stmt);
+
+ cc->EditEvent(hDbEvent, dbei->timestamp, !dbei->markedRead());
+ if (cc->IsSub() && (cc = m_cache->GetCachedContact(cc->parentID)))
+ cc->EditEvent(hDbEvent, dbei->timestamp, !dbei->markedRead());
+
+ char *module = m_modules.find(dbei->szModule);
+ if (module == nullptr)
+ m_modules.insert(mir_strdup(dbei->szModule));
}
- sqlite3_reset(stmt);
- return (rc != SQLITE_DONE);
+
+ NotifyEventHooks(g_hevEventEdited, hContact, (LPARAM)hDbEvent);
+ return 0;
}
LONG CDbxSQLite::GetBlobSize(MEVENT hDbEvent)
@@ -363,8 +365,10 @@ BOOL CDbxSQLite::MarkEventRead(MCONTACT hContact, MEVENT hDbEvent)
sqlite3_reset(stmt);
if (rc != SQLITE_DONE)
return -1;
- if (cc->unread = hDbEvent)
- cc->unread = 0;
+
+ cc->MarkRead(hDbEvent);
+ if (cc->IsSub() && (cc = m_cache->GetCachedContact(cc->parentID)))
+ cc->MarkRead(hDbEvent);
}
NotifyEventHooks(g_hevMarkedRead, hContact, (LPARAM)hDbEvent);
@@ -399,10 +403,38 @@ MEVENT CDbxSQLite::FindFirstEvent(MCONTACT hContact)
if (cc == nullptr)
return 0;
- if (cc->first)
- return cc->first;
+ if (cc->m_first)
+ return cc->m_first;
mir_cslock lock(m_csDbAccess);
+
+ if (cc->IsMeta()) {
+ if (cc->nSubs == 0) {
+ cc->m_first = 0;
+ cc->m_firstTimestamp = 0;
+ return 0;
+ }
+
+ CMStringA query = "select id, timestamp from events where contact_id in (";
+ for (int k = 0; k < cc->nSubs; k++)
+ query.AppendFormat("%lu, ", cc->pSubs[k]);
+ query.Delete(query.GetLength() - 2, 2);
+ query.Append(") order by timestamp, id limit 1;");
+
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2(m_db, query, -1, &stmt, nullptr);
+ int rc = sqlite3_step(stmt);
+ assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
+ if (rc != SQLITE_ROW) {
+ sqlite3_finalize(stmt);
+ return 0;
+ }
+ cc->m_first = sqlite3_column_int64(stmt, 0);
+ cc->m_firstTimestamp = sqlite3_column_int64(stmt, 1);
+ sqlite3_finalize(stmt);
+ return cc->m_first;
+ }
+
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDFIRST];
sqlite3_bind_int64(stmt, 1, hContact);
int rc = sqlite3_step(stmt);
@@ -411,9 +443,10 @@ MEVENT CDbxSQLite::FindFirstEvent(MCONTACT hContact)
sqlite3_reset(stmt);
return 0;
}
- cc->first = sqlite3_column_int64(stmt, 0);
+ cc->m_first = sqlite3_column_int64(stmt, 0);
+ cc->m_firstTimestamp = sqlite3_column_int64(stmt, 1);
sqlite3_reset(stmt);
- return cc->first;
+ return cc->m_first;
}
MEVENT CDbxSQLite::FindFirstUnreadEvent(MCONTACT hContact)
@@ -424,10 +457,38 @@ MEVENT CDbxSQLite::FindFirstUnreadEvent(MCONTACT hContact)
if (cc == nullptr)
return 0;
- if (cc->unread)
- return cc->unread;
+ if (cc->m_unread)
+ return cc->m_unread;
mir_cslock lock(m_csDbAccess);
+
+ if (cc->IsMeta()) {
+ if (cc->nSubs == 0) {
+ cc->m_unread = 0;
+ cc->m_unreadTimestamp = 0;
+ return 0;
+ }
+
+ CMStringA query(FORMAT, "select id from events where (flags & %d) = 0 and contact_id in (", DBEF_READ | DBEF_SENT);
+ for (int k = 0; k < cc->nSubs; k++)
+ query.AppendFormat("%lu, ", cc->pSubs[k]);
+ query.Delete(query.GetLength() - 2, 2);
+ query.Append(") order by timestamp, id limit 1;");
+
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2(m_db, query, -1, &stmt, nullptr);
+ int rc = sqlite3_step(stmt);
+ assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
+ if (rc != SQLITE_ROW) {
+ sqlite3_finalize(stmt);
+ return 0;
+ }
+ cc->m_unread = sqlite3_column_int64(stmt, 0);
+ cc->m_unreadTimestamp = sqlite3_column_int64(stmt, 1);
+ sqlite3_finalize(stmt);
+ return cc->m_unread;
+ }
+
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD];
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_int(stmt, 2, DBEF_READ | DBEF_SENT);
@@ -437,9 +498,10 @@ MEVENT CDbxSQLite::FindFirstUnreadEvent(MCONTACT hContact)
sqlite3_reset(stmt);
return 0;
}
- cc->unread = sqlite3_column_int64(stmt, 0);
+ cc->m_unread = sqlite3_column_int64(stmt, 0);
+ cc->m_unreadTimestamp = sqlite3_column_int64(stmt, 1);
sqlite3_reset(stmt);
- return cc->unread;
+ return cc->m_unread;
}
MEVENT CDbxSQLite::FindLastEvent(MCONTACT hContact)
@@ -450,10 +512,38 @@ MEVENT CDbxSQLite::FindLastEvent(MCONTACT hContact)
if (cc == nullptr)
return 0;
- if (cc->last)
- return cc->last;
+ if (cc->m_last)
+ return cc->m_last;
mir_cslock lock(m_csDbAccess);
+
+ if (cc->IsMeta()) {
+ if (cc->nSubs == 0) {
+ cc->m_last = 0;
+ cc->m_lastTimestamp = 0;
+ return 0;
+ }
+
+ CMStringA query = "select id from events where contact_id in (";
+ for (int k = 0; k < cc->nSubs; k++)
+ query.AppendFormat("%lu, ", cc->pSubs[k]);
+ query.Delete(query.GetLength() - 2, 2);
+ query.Append(") order by timestamp desc, id desc limit 1;");
+
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2(m_db, query, -1, &stmt, nullptr);
+ int rc = sqlite3_step(stmt);
+ assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
+ if (rc != SQLITE_ROW) {
+ sqlite3_finalize(stmt);
+ return 0;
+ }
+ cc->m_last = sqlite3_column_int64(stmt, 0);
+ cc->m_lastTimestamp = sqlite3_column_int64(stmt, 1);
+ sqlite3_finalize(stmt);
+ return cc->m_last;
+ }
+
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDLAST];
sqlite3_bind_int64(stmt, 1, hContact);
int rc = sqlite3_step(stmt);
@@ -462,9 +552,10 @@ MEVENT CDbxSQLite::FindLastEvent(MCONTACT hContact)
sqlite3_reset(stmt);
return 0;
}
- cc->last = sqlite3_column_int64(stmt, 0);
+ cc->m_last = sqlite3_column_int64(stmt, 0);
+ cc->m_lastTimestamp = sqlite3_column_int64(stmt, 1);
sqlite3_reset(stmt);
- return cc->last;
+ return cc->m_last;
}
MEVENT CDbxSQLite::FindNextEvent(MCONTACT hContact, MEVENT hDbEvent)
@@ -476,7 +567,35 @@ MEVENT CDbxSQLite::FindNextEvent(MCONTACT hContact, MEVENT hDbEvent)
if (cc == nullptr)
return 0;
- mir_cslock lock(m_csDbAccess);
+ if (cc->IsMeta()) {
+ if (cc->nSubs == 0)
+ return 0;
+
+ CMStringA in = "(";
+ for (int k = 0; k < cc->nSubs; k++)
+ in.AppendFormat("%lu, ", cc->pSubs[k]);
+ in.Delete(in.GetLength() - 2, 2);
+ in.Append(")");
+
+ CMStringA query(FORMAT, "select id from events where contact_id in %s and id <> %lu and timestamp > (select timestamp from events where contact_id in %s and id = %lu limit 1) order by timestamp, id limit 1;",
+ in,
+ hDbEvent,
+ in,
+ hDbEvent);
+
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2(m_db, query, -1, &stmt, nullptr);
+ int rc = sqlite3_step(stmt);
+ assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
+ if (rc != SQLITE_ROW) {
+ sqlite3_finalize(stmt);
+ return 0;
+ }
+ hDbEvent = sqlite3_column_int64(stmt, 0);
+ sqlite3_finalize(stmt);
+ return hDbEvent;
+ }
+
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDNEXT];
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_int64(stmt, 2, hDbEvent);
@@ -501,6 +620,36 @@ MEVENT CDbxSQLite::FindPrevEvent(MCONTACT hContact, MEVENT hDbEvent)
return 0;
mir_cslock lock(m_csDbAccess);
+
+ if (cc->IsMeta()) {
+ if (cc->nSubs == 0)
+ return 0;
+
+ CMStringA in = "(";
+ for (int k = 0; k < cc->nSubs; k++)
+ in.AppendFormat("%lu, ", cc->pSubs[k]);
+ in.Delete(in.GetLength() - 2, 2);
+ in.Append(")");
+
+ CMStringA query(FORMAT, "select id from events where contact_id in %s and id <> %lu and timestamp < (select timestamp from events where contact_id in %s and id = %lu limit 1) order by timestamp desc, id desc limit 1;",
+ in,
+ hDbEvent,
+ in,
+ hDbEvent);
+
+ sqlite3_stmt *stmt;
+ sqlite3_prepare_v2(m_db, query, -1, &stmt, nullptr);
+ int rc = sqlite3_step(stmt);
+ assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
+ if (rc != SQLITE_ROW) {
+ sqlite3_finalize(stmt);
+ return 0;
+ }
+ hDbEvent = sqlite3_column_int64(stmt, 0);
+ sqlite3_finalize(stmt);
+ return hDbEvent;
+ }
+
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_FINDPREV];
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_int64(stmt, 2, hDbEvent);
@@ -552,7 +701,8 @@ BOOL CDbxSQLite::SetEventId(LPCSTR, MEVENT hDbEvent, LPCSTR szId)
BOOL CDbxSQLite::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
{
- mir_cslock lock(m_csDbAccess);
+ return TRUE;
+ /*mir_cslock lock(m_csDbAccess);
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_MERGE];
sqlite3_bind_int64(stmt, 1, ccMeta->contactID);
sqlite3_bind_int64(stmt, 2, ccSub->contactID);
@@ -560,12 +710,13 @@ BOOL CDbxSQLite::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSu
assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
sqlite3_reset(stmt);
ccMeta->first = ccMeta->unread = ccMeta->last = 0;
- return (rc != SQLITE_DONE);
+ return (rc != SQLITE_DONE);*/
}
BOOL CDbxSQLite::MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
{
- mir_cslock lock(m_csDbAccess);
+ return TRUE;
+ /*mir_cslock lock(m_csDbAccess);
sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_MERGE];
sqlite3_bind_int64(stmt, 1, ccMeta->contactID);
sqlite3_bind_int64(stmt, 2, ccSub->contactID);
@@ -573,5 +724,5 @@ BOOL CDbxSQLite::MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSu
assert(rc == SQLITE_ROW || rc == SQLITE_DONE);
sqlite3_reset(stmt);
ccMeta->first = ccMeta->unread = ccMeta->last = 0;
- return (rc != SQLITE_DONE);
+ return (rc != SQLITE_DONE);*/
} \ No newline at end of file
diff --git a/plugins/Dbx_sqlite/src/dbintf.cpp b/plugins/Dbx_sqlite/src/dbintf.cpp
index ef32f8eddb..1109eb6784 100644
--- a/plugins/Dbx_sqlite/src/dbintf.cpp
+++ b/plugins/Dbx_sqlite/src/dbintf.cpp
@@ -28,11 +28,10 @@ int CDbxSQLite::Create(const wchar_t *profile)
return 1;
sqlite3_exec(database, "create table contacts (id integer not null primary key autoincrement);", nullptr, nullptr, nullptr);
- sqlite3_exec(database, "create table events (id integer not null primary key autoincrement, timestamp integer not null, type integer not null, flags integer not null, size integer not null, data blob, module varchar(255) not null, server_id varchar(64));", nullptr, nullptr, nullptr);
+ sqlite3_exec(database, "create table events (id integer not null primary key autoincrement, contact_id integer not null, module text not null, timestamp integer not null, type integer not null, flags integer not null, size integer not null, data blob, server_id text);", nullptr, nullptr, nullptr);
+ sqlite3_exec(database, "create index idx_events_contactid_timestamp on events(contact_id, timestamp);", nullptr, nullptr, nullptr);
sqlite3_exec(database, "create index idx_events_module_serverid on events(module, server_id);", nullptr, nullptr, nullptr);
- sqlite3_exec(database, "create table contact_events (contact_id integer not null, event_id integer not null, timestamp integer not null, primary key(contact_id, event_id)) without rowid;", nullptr, nullptr, nullptr);
- sqlite3_exec(database, "create index idx_contact_events_eventid on contact_events(event_id);", nullptr, nullptr, nullptr);
- sqlite3_exec(database, "create table settings (contact_id integer not null, module varchar(255) not null, setting varchar(255) not null, type integer not null, value any, primary key(contact_id, module, setting)) without rowid;", nullptr, nullptr, nullptr);
+ sqlite3_exec(database, "create table settings (contact_id integer not null, module text not null, setting text not null, type integer not null, value any, primary key(contact_id, module, setting)) without rowid;", nullptr, nullptr, nullptr);
sqlite3_exec(database, "create index idx_settings_module on settings(module);", nullptr, nullptr, nullptr);
sqlite3_close(database);
@@ -130,5 +129,10 @@ BOOL CDbxSQLite::IsRelational()
void CDbxSQLite::SetCacheSafetyMode(BOOL value)
{
+ // hack to increase import speed
+ if (!value)
+ sqlite3_exec(m_db, "pragma synchronous = OFF;", nullptr, nullptr, nullptr);
+ else
+ sqlite3_exec(m_db, "pragma synchronous = NORMAL;", nullptr, nullptr, nullptr);
m_safetyMode = value != FALSE;
}
diff --git a/plugins/Dbx_sqlite/src/dbintf.h b/plugins/Dbx_sqlite/src/dbintf.h
index 196242a4d1..3d780073e9 100644
--- a/plugins/Dbx_sqlite/src/dbintf.h
+++ b/plugins/Dbx_sqlite/src/dbintf.h
@@ -6,12 +6,24 @@
struct DBCachedContact : public DBCachedContactBase
{
- uint32_t count;
- MEVENT first;
- MEVENT unread;
- MEVENT last;
+ uint32_t m_count;
+ MEVENT m_first;
+ uint32_t m_firstTimestamp;
+ MEVENT m_unread;
+ uint32_t m_unreadTimestamp;
+ MEVENT m_last;
+ uint32_t m_lastTimestamp;
- DBCachedContact() { count = first = unread = last = 0; }
+ DBCachedContact()
+ : m_count(-1), m_first(0), m_unread(0), m_last(0) { }
+
+ bool HasCount() const;
+
+ void AddEvent(MEVENT hDbEvent, uint32_t timestamp, bool unread);
+ void EditEvent(MEVENT hDbEvent, uint32_t timestamp, bool unread);
+ void DeleteEvent(MEVENT hDbEvent);
+
+ void MarkRead(MEVENT hDbEvent);
};
struct CDbxSQLite : public MDatabaseCommon, public MZeroedObject
diff --git a/plugins/Dbx_sqlite/src/version.h b/plugins/Dbx_sqlite/src/version.h
index 2eaac196d0..65c0508616 100644
--- a/plugins/Dbx_sqlite/src/version.h
+++ b/plugins/Dbx_sqlite/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 95
#define __RELEASE_NUM 10
-#define __BUILD_NUM 1
+#define __BUILD_NUM 2
#include <stdver.h>