diff options
author | George Hazan <ghazan@miranda.im> | 2021-04-03 16:46:09 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2021-04-03 16:46:09 +0300 |
commit | dd212611826b7c44e8a3c6cd2209b46d7cd03177 (patch) | |
tree | cb7c81b58576b18af8eeb7f0537aab89e6348524 /plugins/Dbx_sqlite/src | |
parent | 9c11d6918afda6c9b326a794d25f65496ced081a (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-x | plugins/Dbx_sqlite/src/dbcontacts.cpp | 40 | ||||
-rw-r--r-- | plugins/Dbx_sqlite/src/dbcrypt.cpp | 49 | ||||
-rwxr-xr-x | plugins/Dbx_sqlite/src/dbevents.cpp | 105 | ||||
-rwxr-xr-x | plugins/Dbx_sqlite/src/dbintf.cpp | 16 | ||||
-rwxr-xr-x | plugins/Dbx_sqlite/src/dbintf.h | 26 | ||||
-rwxr-xr-x | plugins/Dbx_sqlite/src/dbsettings.cpp | 38 | ||||
-rw-r--r-- | plugins/Dbx_sqlite/src/stdafx.h | 6 | ||||
-rw-r--r-- | plugins/Dbx_sqlite/src/utils.cpp | 16 |
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); +} |