summaryrefslogtreecommitdiff
path: root/plugins/Dbx_sqlite/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2021-04-03 16:46:09 +0300
committerGeorge Hazan <ghazan@miranda.im>2021-04-03 16:46:09 +0300
commitdd212611826b7c44e8a3c6cd2209b46d7cd03177 (patch)
treecb7c81b58576b18af8eeb7f0537aab89e6348524 /plugins/Dbx_sqlite/src
parent9c11d6918afda6c9b326a794d25f65496ced081a (diff)
fix of crazy problems in SQLITE when two instances of database are running at a time
Diffstat (limited to 'plugins/Dbx_sqlite/src')
-rwxr-xr-xplugins/Dbx_sqlite/src/dbcontacts.cpp40
-rw-r--r--plugins/Dbx_sqlite/src/dbcrypt.cpp49
-rwxr-xr-xplugins/Dbx_sqlite/src/dbevents.cpp105
-rwxr-xr-xplugins/Dbx_sqlite/src/dbintf.cpp16
-rwxr-xr-xplugins/Dbx_sqlite/src/dbintf.h26
-rwxr-xr-xplugins/Dbx_sqlite/src/dbsettings.cpp38
-rw-r--r--plugins/Dbx_sqlite/src/stdafx.h6
-rw-r--r--plugins/Dbx_sqlite/src/utils.cpp16
8 files changed, 90 insertions, 206 deletions
diff --git a/plugins/Dbx_sqlite/src/dbcontacts.cpp b/plugins/Dbx_sqlite/src/dbcontacts.cpp
index 0fb15f7082..bd012ee4c8 100755
--- a/plugins/Dbx_sqlite/src/dbcontacts.cpp
+++ b/plugins/Dbx_sqlite/src/dbcontacts.cpp
@@ -1,29 +1,7 @@
#include "stdafx.h"
-enum {
- SQL_CTC_STMT_COUNT = 0,
- SQL_CTC_STMT_ADD,
- SQL_CTC_STMT_DELETE,
- SQL_CTC_STMT_DELETESETTINGS,
- SQL_CTC_STMT_DELETEEVENTS,
- SQL_CTC_STMT_DELETEEVENTS_SRT,
-};
-
-static CQuery ctc_stmts[] =
-{
- { "SELECT COUNT(1) FROM contacts LIMIT 1;" },
- { "INSERT INTO contacts VALUES (null);" },
- { "DELETE FROM contacts WHERE id = ?;" },
- { "DELETE FROM settings WHERE contact_id = ?;" },
- { "DELETE FROM events WHERE contact_id = ?;" },
- { "DELETE FROM events_srt WHERE contact_id = ?;" },
-};
-
void CDbxSQLite::InitContacts()
{
- for (auto &it : ctc_stmts)
- sqlite3_prepare_v3(m_db, it.szQuery, -1, SQLITE_PREPARE_PERSISTENT, &it.pQuery, nullptr);
-
sqlite3_stmt *stmt = nullptr;
sqlite3_prepare_v2(m_db, "SELECT contacts.id, COUNT(es.id) FROM contacts LEFT JOIN events_srt es ON es.contact_id = contacts.id GROUP BY contacts.id;", -1, &stmt, nullptr);
int rc = 0;
@@ -36,16 +14,10 @@ void CDbxSQLite::InitContacts()
sqlite3_finalize(stmt);
}
-void CDbxSQLite::UninitContacts()
-{
- for (auto &it : ctc_stmts)
- sqlite3_finalize(it.pQuery);
-}
-
LONG CDbxSQLite::GetContactCount()
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = ctc_stmts[SQL_CTC_STMT_COUNT].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT COUNT(1) FROM contacts LIMIT 1;", qCntCount);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
int count = sqlite3_column_int(stmt, 0);
@@ -58,7 +30,7 @@ MCONTACT CDbxSQLite::AddContact()
MCONTACT hContact = INVALID_CONTACT_ID;
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = ctc_stmts[SQL_CTC_STMT_ADD].pQuery;
+ sqlite3_stmt *stmt = InitQuery("INSERT INTO contacts VALUES (null);", qCntAdd);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
sqlite3_reset(stmt);
@@ -90,7 +62,7 @@ LONG CDbxSQLite::DeleteContact(MCONTACT hContact)
mir_cslockfull lock(m_csDbAccess);
- sqlite3_stmt *stmt = ctc_stmts[SQL_CTC_STMT_DELETEEVENTS].pQuery;
+ sqlite3_stmt *stmt = InitQuery("DELETE FROM events WHERE contact_id = ?;", qCntDelEvents);
sqlite3_bind_int64(stmt, 1, hContact);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -98,7 +70,7 @@ LONG CDbxSQLite::DeleteContact(MCONTACT hContact)
if (rc != SQLITE_DONE)
return 1;
- stmt = ctc_stmts[SQL_CTC_STMT_DELETEEVENTS_SRT].pQuery;
+ stmt = InitQuery("DELETE FROM events_srt WHERE contact_id = ?;", qCntDelEventSrt);
sqlite3_bind_int64(stmt, 1, hContact);
rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -106,7 +78,7 @@ LONG CDbxSQLite::DeleteContact(MCONTACT hContact)
if (rc != SQLITE_DONE)
return 1;
- stmt = ctc_stmts[SQL_CTC_STMT_DELETESETTINGS].pQuery;
+ stmt = InitQuery("DELETE FROM settings WHERE contact_id = ?;", qCntDelSettings);
sqlite3_bind_int64(stmt, 1, hContact);
rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -114,7 +86,7 @@ LONG CDbxSQLite::DeleteContact(MCONTACT hContact)
if (rc != SQLITE_DONE)
return 1;
- stmt = ctc_stmts[SQL_CTC_STMT_DELETE].pQuery;
+ stmt = InitQuery("DELETE FROM contacts WHERE id = ?;", qCntDel);
sqlite3_bind_int64(stmt, 1, hContact);
rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
diff --git a/plugins/Dbx_sqlite/src/dbcrypt.cpp b/plugins/Dbx_sqlite/src/dbcrypt.cpp
index 86f74505d8..5eee3f3c70 100644
--- a/plugins/Dbx_sqlite/src/dbcrypt.cpp
+++ b/plugins/Dbx_sqlite/src/dbcrypt.cpp
@@ -1,29 +1,5 @@
#include "stdafx.h"
-enum
-{
- SQL_CRYPT_GET_MODE,
- SQL_CRYPT_SET_MODE,
- SQL_CRYPT_GET_PROVIDER,
- SQL_CRYPT_SET_PROVIDER,
- SQL_CRYPT_GET_KEY,
- SQL_CRYPT_SET_KEY,
- SQL_CRYPT_ENCRYPT,
- SQL_CRYPT_ENCRYPT2,
-};
-
-static CQuery crypto_stmts[] =
-{
- { "SELECT data FROM crypto WHERE id=1;" }, // SQL_CRYPT_GET_MODE
- { "REPLACE INTO crypto VALUES (1, ?);" }, // SQL_CRYPT_SET_MODE
- { "SELECT data FROM crypto WHERE id=2;" }, // SQL_CRYPT_GET_PROVIDER
- { "REPLACE INTO crypto VALUES(2, ?);" }, // SQL_CRYPT_SET_PROVIDER
- { "SELECT data FROM crypto WHERE id=3;" }, // SQL_CRYPT_GET_KEY
- { "REPLACE INTO crypto VALUES(3, ?);" }, // SQL_CRYPT_SET_KEY
- { "UPDATE events SET flags=?, data=? WHERE id=?;"}, // SQL_CRYPT_ENCRYPT
- { "UPDATE settings SET type=?, value=? WHERE contact_id=? AND module=? AND setting=?;"}, // SQL_CRYPT_ENCRYPT2
-};
-
static char szCreateQuery[] =
"CREATE TABLE crypto (id INTEGER NOT NULL PRIMARY KEY, data ANY NOT NULL);\r\n"
"INSERT INTO crypto VALUES (1, 0), (2, 'AES (Rjindale)'), (3, (SELECT value FROM settings WHERE contact_id=0 AND module='CryptoEngine' AND setting='StoredKey'));\r\n"
@@ -34,15 +10,6 @@ void CDbxSQLite::InitEncryption()
int rc = sqlite3_exec(m_db, "SELECT COUNT(1) FROM crypto;", nullptr, nullptr, nullptr);
if (rc == SQLITE_ERROR) // table doesn't exist, fill it with existing data
sqlite3_exec(m_db, szCreateQuery, nullptr, nullptr, nullptr);
-
- for (auto &it : crypto_stmts)
- sqlite3_prepare_v3(m_db, it.szQuery, -1, SQLITE_PREPARE_PERSISTENT, &it.pQuery, nullptr);
-}
-
-void CDbxSQLite::UninintEncryption()
-{
- for (auto &it : crypto_stmts)
- sqlite3_finalize(it.pQuery);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -51,7 +18,7 @@ void CDbxSQLite::UninintEncryption()
STDMETHODIMP_(BOOL) CDbxSQLite::ReadCryptoKey(MBinBuffer &buf)
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = crypto_stmts[SQL_CRYPT_GET_KEY].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT data FROM crypto WHERE id=3;", qCryptGetKey);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
if (rc != SQLITE_ROW) {
@@ -71,7 +38,7 @@ STDMETHODIMP_(BOOL) CDbxSQLite::StoreCryptoKey()
m_crypto->getKey(pKey, iKeyLength);
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = crypto_stmts[SQL_CRYPT_SET_KEY].pQuery;
+ sqlite3_stmt *stmt = InitQuery("REPLACE INTO crypto VALUES(3, ?);", qCryptSetKey);
sqlite3_bind_blob(stmt, 1, pKey, (int)iKeyLength, nullptr);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -88,7 +55,7 @@ STDMETHODIMP_(BOOL) CDbxSQLite::StoreCryptoKey()
STDMETHODIMP_(BOOL) CDbxSQLite::ReadEncryption()
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = crypto_stmts[SQL_CRYPT_GET_MODE].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT data FROM crypto WHERE id=1;", qCryptGetMode);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
if (rc != SQLITE_ROW) {
@@ -107,7 +74,7 @@ STDMETHODIMP_(BOOL) CDbxSQLite::ReadEncryption()
STDMETHODIMP_(CRYPTO_PROVIDER*) CDbxSQLite::ReadProvider()
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = crypto_stmts[SQL_CRYPT_GET_PROVIDER].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT data FROM crypto WHERE id=2;", qCryptGetProvider);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
sqlite3_reset(stmt);
@@ -117,7 +84,7 @@ STDMETHODIMP_(CRYPTO_PROVIDER*) CDbxSQLite::ReadProvider()
STDMETHODIMP_(BOOL) CDbxSQLite::StoreProvider(CRYPTO_PROVIDER *pProvider)
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = crypto_stmts[SQL_CRYPT_SET_PROVIDER].pQuery;
+ sqlite3_stmt *stmt = InitQuery("REPLACE INTO crypto VALUES(2, ?);", qCryptSetProvider);
sqlite3_bind_text(stmt, 1, pProvider->pszName, (int)strlen(pProvider->pszName), 0);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -162,7 +129,7 @@ STDMETHODIMP_(BOOL) CDbxSQLite::EnableEncryption(BOOL bEncrypt)
dwFlags |= DBEF_ENCRYPTED;
}
- sqlite3_stmt *upd = crypto_stmts[SQL_CRYPT_ENCRYPT].pQuery;
+ sqlite3_stmt *upd = InitQuery("UPDATE events SET flags=?, data=? WHERE id=?;", qCryptEnc1);
sqlite3_bind_int(upd, 1, dwFlags);
sqlite3_bind_blob(upd, 2, pNewBlob, (int)nNewBlob, 0);
sqlite3_bind_int(upd, 3, id);
@@ -186,7 +153,7 @@ STDMETHODIMP_(BOOL) CDbxSQLite::EnableEncryption(BOOL bEncrypt)
if (!bEncrypt && IsSettingEncrypted(pszModule, pszSetting))
continue;
- sqlite3_stmt *upd = crypto_stmts[SQL_CRYPT_ENCRYPT2].pQuery;
+ sqlite3_stmt *upd = InitQuery("UPDATE settings SET type=?, value=? WHERE contact_id=? AND module=? AND setting=?;", qCryptEnc2);
sqlite3_bind_int(upd, 1, (bEncrypt) ? DBVT_ENCRYPTED : DBVT_UTF8);
size_t resultLen;
@@ -209,7 +176,7 @@ STDMETHODIMP_(BOOL) CDbxSQLite::EnableEncryption(BOOL bEncrypt)
}
// Finally update flag
- stmt = crypto_stmts[SQL_CRYPT_SET_MODE].pQuery;
+ stmt = InitQuery("REPLACE INTO crypto VALUES (1, ?);", qCryptSetKey);
sqlite3_bind_int(stmt, 1, bEncrypt);
rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
diff --git a/plugins/Dbx_sqlite/src/dbevents.cpp b/plugins/Dbx_sqlite/src/dbevents.cpp
index 8a64af8046..b277bbbfbc 100755
--- a/plugins/Dbx_sqlite/src/dbevents.cpp
+++ b/plugins/Dbx_sqlite/src/dbevents.cpp
@@ -1,66 +1,16 @@
#include "stdafx.h"
-enum {
- SQL_EVT_STMT_COUNT = 0,
- SQL_EVT_STMT_ADDEVENT,
- SQL_EVT_STMT_DELETE,
- SQL_EVT_STMT_EDIT,
- 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_FINDNEXT,
- SQL_EVT_STMT_FINDLAST,
- SQL_EVT_STMT_FINDPREV,
- SQL_EVT_STMT_FINDFIRSTUNREAD,
- SQL_EVT_STMT_GETIDBYSRVID,
- SQL_EVT_STMT_ADDEVENT_SRT,
- SQL_EVT_STMT_DELETE_SRT,
- SQL_EVT_STMT_META_SPLIT,
- SQL_EVT_STMT_META_MERGE_SELECT,
-};
-
//TODO: hide it inside cursor class
-static const char* normal_order_query =
- "SELECT id FROM events_srt WHERE contact_id = ? ORDER BY timestamp, id;";
-static const char* normal_order_pos_query =
- "SELECT id FROM events_srt WHERE contact_id = ? AND id >= ? ORDER BY timestamp, id;";
+static const char normal_order_query[] = "SELECT id FROM events_srt WHERE contact_id = ? ORDER BY timestamp, id;";
+static const char normal_order_pos_query[] = "SELECT id FROM events_srt WHERE contact_id = ? AND id >= ? ORDER BY timestamp, id;";
-static const char* reverse_order_query =
- "SELECT id FROM events_srt WHERE contact_id = ? ORDER BY timestamp desc, id DESC;";
-static const char* reverse_order_pos_query =
- "SELECT id FROM events_srt WHERE contact_id = ? AND id <= ? ORDER BY timestamp desc, id DESC;";
+static const char reverse_order_query[] = "SELECT id FROM events_srt WHERE contact_id = ? ORDER BY timestamp desc, id DESC;";
+static const char reverse_order_pos_query[] = "SELECT id FROM events_srt WHERE contact_id = ? AND id <= ? ORDER BY timestamp desc, id DESC;";
-static CQuery evt_stmts[] =
-{
- { "SELECT COUNT(1) FROM events_srt WHERE contact_id = ? LIMIT 1;" }, // SQL_EVT_STMT_COUNT
- { "INSERT INTO events(contact_id, module, timestamp, type, flags, data, server_id) VALUES (?, ?, ?, ?, ?, ?, ?);" }, // SQL_EVT_STMT_ADDEVENT
- { "DELETE FROM events WHERE id = ?;" }, // SQL_EVT_STMT_DELETE
- { "UPDATE events SET module = ?, timestamp = ?, type = ?, flags = ?, data = ? WHERE id = ?;" }, // SQL_EVT_STMT_EDIT
- { "SELECT LENGTH(data) FROM events WHERE id = ? LIMIT 1;" }, // SQL_EVT_STMT_BLOBSIZE
- { "SELECT module, timestamp, type, flags, length(data), data FROM events WHERE id = ? LIMIT 1;" }, // SQL_EVT_STMT_GET
- { "SELECT flags FROM events WHERE id = ? LIMIT 1;" }, // SQL_EVT_STMT_GETFLAGS
- { "UPDATE events SET flags = ? WHERE id = ?;" }, // SQL_EVT_STMT_SETFLAGS
- { "SELECT contact_id FROM events WHERE id = ? LIMIT 1;" }, // SQL_EVT_STMT_GETCONTACT
- { normal_order_query }, // SQL_EVT_STMT_FINDFIRST
- { "SELECT id FROM events_srt WHERE contact_id = ? AND id > ? ORDER BY timestamp, id;" }, // SQL_EVT_STMT_FINDNEXT
- { reverse_order_query }, // SQL_EVT_STMT_FINDLAST
- { "SELECT id FROM events_srt WHERE contact_id = ? AND id < ? ORDER BY timestamp desc, id DESC;" }, // SQL_EVT_STMT_FINDPREV
- { "SELECT id, timestamp FROM events WHERE contact_id = ? AND (flags & ?) = 0 ORDER BY timestamp, id LIMIT 1;" }, // SQL_EVT_STMT_FINDFIRSTUNREAD
- { "SELECT id, timestamp FROM events WHERE module = ? AND server_id = ? LIMIT 1;" }, // SQL_EVT_STMT_GETIDBYSRVID
- { "INSERT INTO events_srt(id, contact_id, timestamp) VALUES (?, ?, ?);" }, // SQL_EVT_STMT_ADDEVENT_SRT
- { "DELETE FROM events_srt WHERE id = ?;" }, // SQL_EVT_STMT_DELETE_SRT
- { "DELETE FROM events_srt WHERE contact_id = ?;" }, // SQL_EVT_STMT_META_SPLIT
- { "SELECT id, timestamp FROM events WHERE contact_id = ?;" }, // SQL_EVT_STMT_META_MERGE_SELECT
-};
+static const char add_event_sort_query[] = "INSERT INTO events_srt(id, contact_id, timestamp) VALUES (?, ?, ?);";
void CDbxSQLite::InitEvents()
{
- for (auto &it : evt_stmts)
- sqlite3_prepare_v3(m_db, it.szQuery, -1, SQLITE_PREPARE_PERSISTENT, &it.pQuery, nullptr);
-
sqlite3_stmt *stmt = nullptr;
sqlite3_prepare_v2(m_db, "SELECT DISTINCT module FROM events;", -1, &stmt, nullptr);
int rc = 0;
@@ -78,9 +28,6 @@ void CDbxSQLite::UninitEvents()
for (auto &module : m_modules)
mir_free(module);
m_modules.destroy();
-
- for (auto &it : evt_stmts)
- sqlite3_finalize(it.pQuery);
}
LONG CDbxSQLite::GetEventCount(MCONTACT hContact)
@@ -90,7 +37,7 @@ LONG CDbxSQLite::GetEventCount(MCONTACT hContact)
return cc->m_count;
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_COUNT].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT COUNT(1) FROM events_srt WHERE contact_id = ? LIMIT 1;", qEvCount);
sqlite3_bind_int64(stmt, 1, hContact);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -154,7 +101,7 @@ MEVENT CDbxSQLite::AddEvent(MCONTACT hContact, const DBEVENTINFO *dbei)
}
mir_cslockfull lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_ADDEVENT].pQuery;
+ sqlite3_stmt *stmt = InitQuery("INSERT INTO events(contact_id, module, timestamp, type, flags, data, server_id) VALUES (?, ?, ?, ?, ?, ?, ?);", qEvAdd);
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_text(stmt, 2, tmp.szModule, (int)mir_strlen(tmp.szModule), nullptr);
sqlite3_bind_int64(stmt, 3, tmp.timestamp);
@@ -168,7 +115,7 @@ MEVENT CDbxSQLite::AddEvent(MCONTACT hContact, const DBEVENTINFO *dbei)
MEVENT hDbEvent = sqlite3_last_insert_rowid(m_db);
- stmt = evt_stmts[SQL_EVT_STMT_ADDEVENT_SRT].pQuery;
+ stmt = InitQuery(add_event_sort_query, qEvAddSrt);
sqlite3_bind_int64(stmt, 1, hDbEvent);
sqlite3_bind_int64(stmt, 2, cc->contactID);
sqlite3_bind_int64(stmt, 3, tmp.timestamp);
@@ -178,7 +125,7 @@ MEVENT CDbxSQLite::AddEvent(MCONTACT hContact, const DBEVENTINFO *dbei)
cc->AddEvent(hDbEvent, tmp.timestamp, !tmp.markedRead());
if (ccSub != nullptr) {
- stmt = evt_stmts[SQL_EVT_STMT_ADDEVENT_SRT].pQuery;
+ stmt = InitQuery(add_event_sort_query, qEvAddSrt);
sqlite3_bind_int64(stmt, 1, hDbEvent);
sqlite3_bind_int64(stmt, 2, ccSub->contactID);
sqlite3_bind_int64(stmt, 3, tmp.timestamp);
@@ -213,7 +160,7 @@ BOOL CDbxSQLite::DeleteEvent(MEVENT hDbEvent)
return 1;
mir_cslockfull lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_DELETE].pQuery;
+ sqlite3_stmt *stmt = InitQuery("DELETE FROM events WHERE id = ?;", qEvDel);
sqlite3_bind_int64(stmt, 1, hDbEvent);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -221,7 +168,7 @@ BOOL CDbxSQLite::DeleteEvent(MEVENT hDbEvent)
if (rc != SQLITE_DONE)
return 1;
- stmt = evt_stmts[SQL_EVT_STMT_DELETE_SRT].pQuery;
+ stmt = InitQuery("DELETE FROM events_srt WHERE id = ?;", qEvDelSrt);
sqlite3_bind_int64(stmt, 1, hDbEvent);
rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -265,7 +212,7 @@ BOOL CDbxSQLite::EditEvent(MCONTACT hContact, MEVENT hDbEvent, const DBEVENTINFO
}
mir_cslockfull lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_EDIT].pQuery;
+ sqlite3_stmt *stmt = InitQuery("UPDATE events SET module = ?, timestamp = ?, type = ?, flags = ?, data = ? WHERE id = ?;", qEvEdit);
sqlite3_bind_text(stmt, 1, tmp.szModule, (int)mir_strlen(tmp.szModule), nullptr);
sqlite3_bind_int64(stmt, 2, tmp.timestamp);
sqlite3_bind_int(stmt, 3, tmp.eventType);
@@ -297,7 +244,7 @@ LONG CDbxSQLite::GetBlobSize(MEVENT hDbEvent)
return -1;
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_BLOBSIZE].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT LENGTH(data) FROM events WHERE id = ? LIMIT 1;", qEvBlobSize);
sqlite3_bind_int(stmt, 1, hDbEvent);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -325,7 +272,7 @@ BOOL CDbxSQLite::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei)
}
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_GET].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT module, timestamp, type, flags, length(data), data FROM events WHERE id = ? LIMIT 1;", qEvGet);
sqlite3_bind_int64(stmt, 1, hDbEvent);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -380,7 +327,7 @@ BOOL CDbxSQLite::MarkEventRead(MCONTACT hContact, MEVENT hDbEvent)
DWORD flags = 0;
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_GETFLAGS].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT flags FROM events WHERE id = ? LIMIT 1;", qEvGetFlags);
sqlite3_bind_int64(stmt, 1, hDbEvent);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -398,7 +345,7 @@ BOOL CDbxSQLite::MarkEventRead(MCONTACT hContact, MEVENT hDbEvent)
flags |= DBEF_READ;
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_SETFLAGS].pQuery;
+ sqlite3_stmt *stmt = InitQuery("UPDATE events SET flags = ? WHERE id = ?;", qEvSetFlags);
sqlite3_bind_int(stmt, 1, flags);
sqlite3_bind_int64(stmt, 2, hDbEvent);
int rc = sqlite3_step(stmt);
@@ -423,7 +370,7 @@ MCONTACT CDbxSQLite::GetEventContact(MEVENT hDbEvent)
return INVALID_CONTACT_ID;
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_GETCONTACT].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT contact_id FROM events WHERE id = ? LIMIT 1;", qEvGetContact);
sqlite3_bind_int64(stmt, 1, hDbEvent);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -474,7 +421,7 @@ MEVENT CDbxSQLite::FindFirstUnreadEvent(MCONTACT hContact)
return cc->m_unread;
}
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_FINDFIRSTUNREAD].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT id, timestamp FROM events WHERE contact_id = ? AND (flags & ?) = 0 ORDER BY timestamp, id LIMIT 1;", qEvFindUnread);
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_int(stmt, 2, DBEF_READ | DBEF_SENT);
int rc = sqlite3_step(stmt);
@@ -504,7 +451,7 @@ MEVENT CDbxSQLite::FindFirstEvent(MCONTACT hContact)
sqlite3_reset(fwd.cur);
fwd.hContact = hContact;
- fwd.cur = evt_stmts[SQL_EVT_STMT_FINDFIRST].pQuery;
+ fwd.cur = InitQuery(normal_order_query, qEvFindFirst);
sqlite3_bind_int64(fwd.cur, 1, hContact);
int rc = sqlite3_step(fwd.cur);
@@ -530,7 +477,7 @@ MEVENT CDbxSQLite::FindNextEvent(MCONTACT hContact, MEVENT hDbEvent)
sqlite3_reset(fwd.cur);
fwd.hContact = hContact;
- fwd.cur = evt_stmts[SQL_EVT_STMT_FINDNEXT].pQuery;
+ fwd.cur = InitQuery("SELECT id FROM events_srt WHERE contact_id = ? AND id > ? ORDER BY timestamp, id;", qEvFindNext);
sqlite3_bind_int64(fwd.cur, 1, hContact);
sqlite3_bind_int64(fwd.cur, 2, hDbEvent);
}
@@ -560,7 +507,7 @@ MEVENT CDbxSQLite::FindLastEvent(MCONTACT hContact)
sqlite3_reset(back.cur);
back.hContact = hContact;
- back.cur = evt_stmts[SQL_EVT_STMT_FINDLAST].pQuery;
+ back.cur = InitQuery(reverse_order_query, qEvFindLast);
sqlite3_bind_int64(back.cur, 1, hContact);
int rc = sqlite3_step(back.cur);
logError(rc, __FILE__, __LINE__);
@@ -586,7 +533,7 @@ MEVENT CDbxSQLite::FindPrevEvent(MCONTACT hContact, MEVENT hDbEvent)
sqlite3_reset(back.cur);
back.hContact = hContact;
- back.cur = evt_stmts[SQL_EVT_STMT_FINDPREV].pQuery;
+ back.cur = InitQuery("SELECT id FROM events_srt WHERE contact_id = ? AND id < ? ORDER BY timestamp desc, id DESC;", qEvFindPrev);
sqlite3_bind_int64(back.cur, 1, hContact);
sqlite3_bind_int64(back.cur, 2, hDbEvent);
}
@@ -608,12 +555,12 @@ BOOL CDbxSQLite::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSu
{
//TODO: test this
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_META_MERGE_SELECT].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT id, timestamp FROM events WHERE contact_id = ?;", qEvMetaMerge);
sqlite3_bind_int64(stmt, 1, ccSub->contactID);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
while (rc == SQLITE_ROW) {
- sqlite3_stmt *stmt2 = evt_stmts[SQL_EVT_STMT_ADDEVENT_SRT].pQuery;
+ sqlite3_stmt *stmt2 = InitQuery(add_event_sort_query, qEvAddSrt);
sqlite3_bind_int64(stmt2, 1, sqlite3_column_int64(stmt, 0));
sqlite3_bind_int64(stmt2, 2, ccMeta->contactID);
sqlite3_bind_int64(stmt2, 3, sqlite3_column_int64(stmt, 1));
@@ -632,7 +579,7 @@ BOOL CDbxSQLite::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSu
BOOL CDbxSQLite::MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *)
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_META_SPLIT].pQuery;
+ sqlite3_stmt *stmt = InitQuery("DELETE FROM events_srt WHERE contact_id = ?;", qEvMetaSplit);
sqlite3_bind_int64(stmt, 1, ccMeta->contactID);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
@@ -653,7 +600,7 @@ MEVENT CDbxSQLite::GetEventById(LPCSTR szModule, LPCSTR szId)
return 0;
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = evt_stmts[SQL_EVT_STMT_GETIDBYSRVID].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT id, timestamp FROM events WHERE module = ? AND server_id = ? LIMIT 1;", qEvGetById);
sqlite3_bind_text(stmt, 1, szModule, (int)mir_strlen(szModule), nullptr);
sqlite3_bind_text(stmt, 2, szId, (int)mir_strlen(szId), nullptr);
int rc = sqlite3_step(stmt);
diff --git a/plugins/Dbx_sqlite/src/dbintf.cpp b/plugins/Dbx_sqlite/src/dbintf.cpp
index 6fd1c9b6a1..1ae2834f1e 100755
--- a/plugins/Dbx_sqlite/src/dbintf.cpp
+++ b/plugins/Dbx_sqlite/src/dbintf.cpp
@@ -12,16 +12,15 @@ CDbxSQLite::CDbxSQLite(const wchar_t *pwszFileName, bool bReadOnly, bool bShared
CDbxSQLite::~CDbxSQLite()
{
- int rc = sqlite3_exec(m_db, "commit;", nullptr, nullptr, nullptr);
- logError(rc, __FILE__, __LINE__);
+ if (m_bTranStarted) {
+ int rc = sqlite3_exec(m_db, "commit;", nullptr, nullptr, nullptr);
+ logError(rc, __FILE__, __LINE__);
+ }
UninitEvents();
- UninitContacts();
- UninitSettings();
- UninintEncryption();
if (m_db) {
- rc = sqlite3_close(m_db);
+ int rc = sqlite3_close(m_db);
logError(rc, __FILE__, __LINE__);
m_db = nullptr;
@@ -43,7 +42,7 @@ int CDbxSQLite::Create()
rc = sqlite3_exec(m_db, "CREATE TABLE contacts (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT);", nullptr, nullptr, nullptr);
logError(rc, __FILE__, __LINE__);
- rc = sqlite3_exec(m_db, "CREATE TABLE crypto (id INTEGER NOT NULL PRIMARY KEY, data ANY NOT NULL);", nullptr, nullptr, nullptr);
+ rc = sqlite3_exec(m_db, "CREATE TABLE crypto (id INTEGER NOT NULL PRIMARY KEY, data NOT NULL);", nullptr, nullptr, nullptr);
logError(rc, __FILE__, __LINE__);
rc = sqlite3_exec(m_db, "CREATE TABLE events (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, contact_id INTEGER NOT NULL, module TEXT NOT NULL,"
@@ -60,7 +59,7 @@ int CDbxSQLite::Create()
rc = sqlite3_exec(m_db, "CREATE TABLE events_srt (id INTEGER NOT NULL, contact_id INTEGER NOT NULL, timestamp INTEGER, PRIMARY KEY(contact_id, timestamp, id));", nullptr, nullptr, nullptr);
logError(rc, __FILE__, __LINE__);
- rc = sqlite3_exec(m_db, "CREATE TABLE settings (contact_id INTEGER NOT NULL, module TEXT NOT NULL, setting TEXT NOT NULL, type INTEGER NOT NULL, value ANY,"
+ rc = sqlite3_exec(m_db, "CREATE TABLE settings (contact_id INTEGER NOT NULL, module TEXT NOT NULL, setting TEXT NOT NULL, type INTEGER NOT NULL, value NOT NULL,"
"PRIMARY KEY(contact_id, module, setting)) WITHOUT ROWID;", nullptr, nullptr, nullptr);
logError(rc, __FILE__, __LINE__);
@@ -146,6 +145,7 @@ int CDbxSQLite::Load()
if (InitCrypt())
return EGROKPRF_CANTREAD;
+ m_bTranStarted = true;
rc = sqlite3_exec(m_db, "begin transaction;", nullptr, nullptr, nullptr);
logError(rc, __FILE__, __LINE__);
return EGROKPRF_NOERROR;
diff --git a/plugins/Dbx_sqlite/src/dbintf.h b/plugins/Dbx_sqlite/src/dbintf.h
index a2a2fbcaf5..6e772eb6ef 100755
--- a/plugins/Dbx_sqlite/src/dbintf.h
+++ b/plugins/Dbx_sqlite/src/dbintf.h
@@ -4,6 +4,13 @@
#include <m_db_int.h>
+struct CQuery
+{
+ ~CQuery();
+
+ sqlite3_stmt *pQuery = nullptr;
+};
+
struct DBCachedContact : public DBCachedContactBase
{
int32_t m_count;
@@ -72,22 +79,29 @@ class CDbxSQLite : public MDatabaseCommon, public MZeroedObject
}
} m_impl;
- bool m_safetyMode, m_bReadOnly, m_bShared;
+ bool m_safetyMode, m_bReadOnly, m_bShared, m_bTranStarted;
+ // contacts
void InitContacts();
- void UninitContacts();
+ CQuery qCntCount, qCntAdd, qCntDel, qCntDelSettings, qCntDelEvents, qCntDelEventSrt;
+ // encryption
+ void InitEncryption();
+ CQuery qCryptGetMode, qCryptSetMode, qCryptGetProvider, qCryptSetProvider, qCryptGetKey, qCryptSetKey, qCryptEnc1, qCryptEnc2;
+
+ // events
LIST<char> m_modules;
void InitEvents();
void UninitEvents();
+ CQuery qEvCount, qEvAdd, qEvDel, qEvEdit, qEvBlobSize, qEvGet, qEvGetFlags, qEvSetFlags, qEvGetContact;
+ CQuery qEvFindFirst, qEvFindNext, qEvFindLast, qEvFindPrev, qEvFindUnread, qEvGetById, qEvAddSrt, qEvDelSrt, qEvMetaSplit, qEvMetaMerge;
+ // settings
void InitSettings();
- void UninitSettings();
-
- void InitEncryption();
- void UninintEncryption();
+ CQuery qSettModules, qSettWrite, qSettDel, qSettEnum, qSettChanges;
void DBFlush(bool bForce = false);
+ sqlite3_stmt* InitQuery(const char *szQuery, CQuery &stmt);
public:
CDbxSQLite(const wchar_t *pwszFileName, bool bReadOnly, bool bShared);
diff --git a/plugins/Dbx_sqlite/src/dbsettings.cpp b/plugins/Dbx_sqlite/src/dbsettings.cpp
index bc00dbb918..65fcd75aae 100755
--- a/plugins/Dbx_sqlite/src/dbsettings.cpp
+++ b/plugins/Dbx_sqlite/src/dbsettings.cpp
@@ -1,29 +1,7 @@
#include "stdafx.h"
-enum {
- SQL_SET_STMT_ENUM = 0,
- SQL_SET_STMT_GET,
- SQL_SET_STMT_REPLACE,
- SQL_SET_STMT_DELETE,
- SQL_SET_STMT_ENUMMODULE,
- SQL_SET_STMT_CHANGES
-};
-
-static CQuery settings_stmts[] =
-{
- { "SELECT DISTINCT module FROM settings;" },
- { "SELECT type, value FROM settings WHERE contact_id = ? AND module = ? AND setting = ? LIMIT 1;" },
- { "REPLACE INTO settings(contact_id, module, setting, type, value) VALUES (?, ?, ?, ?, ?);" },
- { "DELETE FROM settings WHERE contact_id = ? AND module = ? AND setting = ?;" },
- { "SELECT setting FROM settings WHERE contact_id = ? AND module = ?;" },
- { "SELECT CHANGES() FROM settings;" },
-};
-
void CDbxSQLite::InitSettings()
{
- for (auto &it : settings_stmts)
- sqlite3_prepare_v3(m_db, it.szQuery, -1, SQLITE_PREPARE_PERSISTENT, &it.pQuery, nullptr);
-
sqlite3_stmt *stmt = nullptr;
sqlite3_prepare_v2(m_db, "SELECT type, value, contact_id, module, setting FROM settings;", -1, &stmt, nullptr);
while (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -82,11 +60,6 @@ void CDbxSQLite::InitSettings()
FillContactSettings();
}
-void CDbxSQLite::UninitSettings()
-{
- for (auto &it : settings_stmts)
- sqlite3_finalize(it.pQuery);
-}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -94,7 +67,7 @@ BOOL CDbxSQLite::EnumModuleNames(DBMODULEENUMPROC pFunc, void *param)
{
LIST<char> modules(100);
{
- sqlite3_stmt *stmt = settings_stmts[SQL_SET_STMT_ENUM].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT DISTINCT module FROM settings;", qSettModules);
int rc = 0;
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
const char *value = (const char *)sqlite3_column_text(stmt, 0);
@@ -116,7 +89,7 @@ BOOL CDbxSQLite::EnumModuleNames(DBMODULEENUMPROC pFunc, void *param)
BOOL CDbxSQLite::WriteContactSettingWorker(MCONTACT hContact, DBCONTACTWRITESETTING &dbcws)
{
- sqlite3_stmt *stmt = settings_stmts[SQL_SET_STMT_REPLACE].pQuery;
+ sqlite3_stmt *stmt = InitQuery("REPLACE INTO settings(contact_id, module, setting, type, value) VALUES (?, ?, ?, ?, ?);", qSettWrite);
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_text(stmt, 2, dbcws.szModule, (int)mir_strlen(dbcws.szModule), nullptr);
sqlite3_bind_text(stmt, 3, dbcws.szSetting, (int)mir_strlen(dbcws.szSetting), nullptr);
@@ -167,14 +140,15 @@ BOOL CDbxSQLite::DeleteContactSetting(MCONTACT hContact, LPCSTR szModule, LPCSTR
char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, mir_strlen(szModule), mir_strlen(szSetting));
if (szCachedSettingName[-1] == 0) { // it's not a resident variable
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = settings_stmts[SQL_SET_STMT_DELETE].pQuery;
+ sqlite3_stmt *stmt = InitQuery("DELETE FROM settings WHERE contact_id = ? AND module = ? AND setting = ?;", qSettDel);
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_text(stmt, 2, szModule, (int)mir_strlen(szModule), nullptr);
sqlite3_bind_text(stmt, 3, szSetting, (int)mir_strlen(szSetting), nullptr);
int rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
sqlite3_reset(stmt);
- stmt = settings_stmts[SQL_SET_STMT_CHANGES].pQuery;
+
+ stmt = InitQuery("SELECT CHANGES() FROM settings;", qSettChanges);
rc = sqlite3_step(stmt);
logError(rc, __FILE__, __LINE__);
int deleted = sqlite3_column_int(stmt, 0);
@@ -212,7 +186,7 @@ BOOL CDbxSQLite::EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnu
LIST<char> settings(100);
{
mir_cslock lock(m_csDbAccess);
- sqlite3_stmt *stmt = settings_stmts[SQL_SET_STMT_ENUMMODULE].pQuery;
+ sqlite3_stmt *stmt = InitQuery("SELECT setting FROM settings WHERE contact_id = ? AND module = ?;", qSettEnum);
sqlite3_bind_int64(stmt, 1, hContact);
sqlite3_bind_text(stmt, 2, szModule, (int)mir_strlen(szModule), nullptr);
int rc = 0;
diff --git a/plugins/Dbx_sqlite/src/stdafx.h b/plugins/Dbx_sqlite/src/stdafx.h
index 6d8fc14a1d..9b8cc30a59 100644
--- a/plugins/Dbx_sqlite/src/stdafx.h
+++ b/plugins/Dbx_sqlite/src/stdafx.h
@@ -21,12 +21,6 @@
#include "resource.h"
#include "version.h"
-struct CQuery
-{
- const char *szQuery;
- sqlite3_stmt *pQuery;
-};
-
void logError(int rc, const char *szFile, int line);
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/Dbx_sqlite/src/utils.cpp b/plugins/Dbx_sqlite/src/utils.cpp
index 174fe9d394..89f03b6d93 100644
--- a/plugins/Dbx_sqlite/src/utils.cpp
+++ b/plugins/Dbx_sqlite/src/utils.cpp
@@ -12,3 +12,19 @@ void logError(int rc, const char *szFile, int line)
_ASSERT(rc == 0);
Netlib_Logf(0, "SQLITE error %d (%s, %d)", rc, szFile, line);
}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+sqlite3_stmt* CDbxSQLite::InitQuery(const char *szQuery, CQuery &stmt)
+{
+ if (stmt.pQuery == nullptr)
+ sqlite3_prepare_v3(m_db, szQuery, -1, SQLITE_PREPARE_PERSISTENT, &stmt.pQuery, nullptr);
+
+ return stmt.pQuery;
+}
+
+CQuery::~CQuery()
+{
+ if (pQuery)
+ sqlite3_finalize(pQuery);
+}