diff --git a/persistancelayer.cpp b/persistancelayer.cpp index b1b5ec228d7e11bff8bbd17538e28caca2000294..9940e8378cfe6df9513c062ea3cc5486ce145778 100755 --- a/persistancelayer.cpp +++ b/persistancelayer.cpp @@ -50,6 +50,8 @@ PersistanceLayer *PersistanceLayer::instance() void PersistanceLayer::initShema() { + initQueries(); + mDb.transaction(); QSqlQuery pragmaquery; pragmaquery.prepare( QStringLiteral( "PRAGMA synchronous = OFF" ) ); @@ -57,10 +59,6 @@ void PersistanceLayer::initShema() qDebug() << pragmaquery.lastError(); } - // pragmaquery.prepare("PRAGMA locking_mode = EXCLUSIVE"); - // if(!pragmaquery.exec()){ - // qDebug() << pragmaquery.lastError(); - // } pragmaquery.prepare( QStringLiteral( "PRAGMA JOURNAL_MODE=MEMORY" ) ); if ( !pragmaquery.exec() ) { @@ -73,8 +71,18 @@ void PersistanceLayer::initShema() qDebug() << pragmaquery.lastError(); } - transaction(); + pragmaquery.prepare( QStringLiteral( "PRAGMA PAGE_SIZE=4096" ) ); + + if ( !pragmaquery.exec() ) { + qDebug() << pragmaquery.lastError(); + } + + /* pragmaquery.prepare( "PRAGMA locking_mode = EXCLUSIVE" ); + if ( !pragmaquery.exec() ) { + qDebug() << pragmaquery.lastError(); + } + */ QSqlQuery query; query.prepare( QStringLiteral( "CREATE TABLE IF NOT EXISTS user_data " "(id integer primary key," @@ -170,7 +178,7 @@ void PersistanceLayer::initShema() } */ - commit(); + mDb.commit(); query.prepare( QStringLiteral( "SELECT db_ver FROM app_info WHERE id=0" ) ); int dbVer = -1; @@ -187,10 +195,12 @@ void PersistanceLayer::initShema() } } + query.finish(); + if ( !dbVer ) { upgradeSchema(); } else if ( dbVer == -1 ) { - transaction(); + mDb.transaction(); query.prepare( QStringLiteral( "CREATE TABLE IF NOT EXISTS app_info" "(id varchar(30) primary key," "db_ver integer," @@ -200,15 +210,18 @@ void PersistanceLayer::initShema() qWarning() << query.lastError(); } - commit(); QString dbVersion = QString::number( DBVERSION ); query.prepare( QStringLiteral( "INSERT INTO app_info (db_ver) VALUES(" ) + dbVersion + ")" ); if ( !query.exec() ) { qWarning() << query.lastError(); } + + mDb.commit(); } + mDb.transaction(); + query.prepare( QStringLiteral( "CREATE TABLE IF NOT EXISTS app_settings" "(id integer primary key," "serverid integer," @@ -219,7 +232,7 @@ void PersistanceLayer::initShema() qWarning() << query.lastError(); } - + mDb.commit(); query.prepare( QStringLiteral( "SELECT id FROM custom_emojis" ) ); @@ -234,6 +247,8 @@ void PersistanceLayer::initShema() break; } + query.finish(); + if ( size <= 0 ) { QFile dump( QStringLiteral( ":/sql/emojis.sql" ) ); @@ -241,7 +256,7 @@ void PersistanceLayer::initShema() qWarning() << "error loading dump"; qWarning() << dump.errorString(); } else { - transaction(); + mDb.transaction(); QTextStream in( &dump ); QString dumpString; dumpString.reserve( 200 ); @@ -259,11 +274,12 @@ void PersistanceLayer::initShema() } dump.close(); - commit(); + mDb.commit(); } } } + mDb.commit(); } void PersistanceLayer::upgradeSchema() @@ -283,6 +299,8 @@ void PersistanceLayer::upgradeSchema() dbVersion = query.value( dbVerIndex ).toInt(); } + query.finish(); + if ( dbVersion < DBVERSION ) { QFile sqlFile; int currentTarget = 0; @@ -310,11 +328,13 @@ void PersistanceLayer::upgradeSchema() sqlFile.setFileName( QStringLiteral( ":/sql/migrations/5.sql" ) ); } + + if ( !sqlFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) { qWarning() << "error loading dump"; qWarning() << sqlFile.errorString(); } else { - transaction(); + mDb.transaction(); QTextStream in( &sqlFile ); QString line; @@ -331,7 +351,7 @@ void PersistanceLayer::upgradeSchema() } } - commit(); + mDb.commit(); } upgradeSchema(); @@ -343,6 +363,7 @@ void PersistanceLayer::wipeDb() { mDb.close(); + mDbReady = false; QString directory = QStandardPaths::writableLocation( QStandardPaths::AppLocalDataLocation ); QString filePath = directory + QStringLiteral( "/data.sqlite" ); QFile file( filePath ); @@ -351,6 +372,13 @@ void PersistanceLayer::wipeDb() qWarning() << file.errorString(); } else { qDebug() << "db wiped"; + QDir fileDownloadsDir( QStandardPaths::writableLocation( QStandardPaths::TempLocation ) + QStringLiteral( "/rocketChat" ) ); + + if ( fileDownloadsDir.removeRecursively() ) { + qDebug() << "Downloads wiped"; + } else { + qWarning() << "can't wipe downloads"; + } } init(); @@ -358,36 +386,45 @@ void PersistanceLayer::wipeDb() void PersistanceLayer::transaction( ) { - // mMutex.lock(); + commitMutex.lock(); - if ( mCommitCounter == 0 ) { + if ( mTransactionCounter == 0 ) { if ( !mDb.transaction() ) { qWarning() << mDb.lastError(); } } - mCommitCounter++; - // mMutex.unlock(); + mTransactionCounter++; + commitMutex.unlock(); +} + +void PersistanceLayer::askForcommit() +{ + commitMutex.lock(); + + // mCommitCounter++; + + commitMutex.unlock(); + commit( ); } void PersistanceLayer::commit( ) { - // mMutex.lock(); + commitMutex.lock(); - /* if ( mCommitCounter ) { - mCommitCounter--; - } - */ - if ( mCommitCounter ) { - if ( !mDb.commit() ) { - qWarning() << mDb.lastError(); - } + //if ( mCommitCounter && mCommitCounter == mTransactionCounter ) { + qDebug() << "commit !"; + if ( !mDb.commit() ) { + qWarning() << mDb.lastError(); + } else { mCommitCounter = 0; - + mTransactionCounter = 0; } - // mMutex.unlock(); + //} + + commitMutex.unlock(); } @@ -396,69 +433,57 @@ void PersistanceLayer::setUserName( const QString &pUsername ) { transaction(); - QSqlQuery setName; - setName.prepare( QStringLiteral( "UPDATE user_data " - "SET username=:username WHERE id=:id" ) ); - setName.bindValue( QStringLiteral( ":id" ), 0 ); - setName.bindValue( QStringLiteral( ":username" ), pUsername ); - - if ( !setName.exec() ) { - qWarning() << setName.lastError(); + + querySetUsername.bindValue( QStringLiteral( ":id" ), 0 ); + querySetUsername.bindValue( QStringLiteral( ":username" ), pUsername ); + + if ( !querySetUsername.exec() ) { + qWarning() << querySetUsername.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::setPassword( const QString &pPassword ) { transaction(); - QSqlQuery setPass; - setPass.prepare( QStringLiteral( "UPDATE user_data " - "SET password=:password WHERE id=:id" ) ); - setPass.bindValue( QStringLiteral( ":password" ), pPassword ); - setPass.bindValue( QStringLiteral( ":id" ), 0 ); - - if ( !setPass.exec() ) { - qWarning() << setPass.lastError(); + querySetPassword.bindValue( QStringLiteral( ":password" ), pPassword ); + querySetPassword.bindValue( QStringLiteral( ":id" ), 0 ); + + if ( !querySetPassword.exec() ) { + qWarning() << querySetPassword.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::setToken( const QString &pToken, uint pExpire ) { transaction(); - QSqlQuery setToken; - - setToken.prepare( QStringLiteral( "UPDATE user_data " - "SET token=:token, token_expire=:token_expire WHERE id=:id" ) ); - setToken.bindValue( QStringLiteral( ":token" ), pToken ); - setToken.bindValue( QStringLiteral( ":id" ), 0 ); - setToken.bindValue( QStringLiteral( ":token_expire" ), pExpire ); + querySetToken.bindValue( QStringLiteral( ":token" ), pToken ); + querySetToken.bindValue( QStringLiteral( ":id" ), 0 ); + querySetToken.bindValue( QStringLiteral( ":token_expire" ), pExpire ); - if ( !setToken.exec() ) { - qWarning() << setToken.lastError(); + if ( !querySetToken.exec() ) { + qWarning() << querySetToken.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::setUserData( const QString &pUser, const QString &pPass ) { transaction(); - QSqlQuery setUser; + querySetUser.bindValue( ":id", 0 ); + querySetUser.bindValue( ":password", pPass ); + querySetUser.bindValue( ":username", pUser ); - setUser.prepare( QStringLiteral( "REPLACE INTO user_data " - "(id,password,username) VALUES(:id,:password,:username)" ) ); - setUser.bindValue( ":password", pPass ); - setUser.bindValue( ":id", 0 ); - setUser.bindValue( ":username", pUser ); - - if ( !setUser.exec() ) { - qWarning() << setUser.lastError(); + if ( !querySetUser.exec() ) { + qWarning() << querySetUser.lastError(); + qWarning() << querySetUser.lastQuery(); } - commit(); + askForcommit(); } QString PersistanceLayer::addFileToTemp( const QString &pUrl, const QString &pPath ) @@ -721,75 +746,67 @@ void PersistanceLayer::createFolder( const QString &pPath ) void PersistanceLayer::setUserId( const QString &pUserId ) { transaction(); - QSqlQuery setUserId; - setUserId.prepare( QStringLiteral( "UPDATE user_data SET user_id=:userId WHERE id=:id" ) ); - setUserId.bindValue( QStringLiteral( ":id" ), 0 ); - setUserId.bindValue( QStringLiteral( ":userId" ), pUserId ); + querySetUserId.bindValue( QStringLiteral( ":id" ), 0 ); + querySetUserId.bindValue( QStringLiteral( ":userId" ), pUserId ); - if ( !setUserId.exec() ) { - qWarning() << setUserId.lastError(); + if ( !querySetUserId.exec() ) { + qWarning() << querySetUserId.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::setCurrentChannel( const QString &pChannelId, const QString &pChannelName ) { transaction(); - QSqlQuery setChannel; - setChannel.prepare( QStringLiteral( "REPLACE INTO current_room" - "(id,rid,name) VALUES(:id,:rid,:name)" ) ); - setChannel.bindValue( QStringLiteral( ":id" ), 0 ); - setChannel.bindValue( QStringLiteral( ":rid" ), pChannelId ); - setChannel.bindValue( QStringLiteral( ":name" ), pChannelName ); - - if ( !setChannel.exec() ) { - qWarning() << setChannel.lastError(); + + querySetChannel.bindValue( QStringLiteral( ":id" ), 0 ); + querySetChannel.bindValue( QStringLiteral( ":rid" ), pChannelId ); + querySetChannel.bindValue( QStringLiteral( ":name" ), pChannelName ); + + if ( !querySetChannel.exec() ) { + qWarning() << querySetChannel.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::setSetting( const QString &pProperty, const QString &pValue ) { transaction(); - QSqlQuery setChannel; - setChannel.prepare( QStringLiteral( "REPLACE INTO app_settings" - "(property,value) VALUES(:property,:value)" ) ); - setChannel.bindValue( QStringLiteral( ":property" ), pProperty ); - setChannel.bindValue( QStringLiteral( ":value" ), pValue ); - - if ( !setChannel.exec() ) { - qWarning() << setChannel.lastError(); + + querySetSetting.bindValue( QStringLiteral( ":property" ), pProperty ); + querySetSetting.bindValue( QStringLiteral( ":value" ), pValue ); + + if ( !querySetSetting.exec() ) { + qWarning() << querySetSetting.lastQuery(); + qWarning() << querySetSetting.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::addChannel( const QString &pId, const QString &pName, const QString &pType, bool pJoined, bool pReadOnly, const QString &pMuted, bool pArchived, bool pBlocked, const QString &pUsername, const QString &pChatPartnerId ) { transaction(); - QSqlQuery setChannel; - setChannel.prepare( QStringLiteral( "REPLACE INTO rooms " - "(id,name,type,joined,read_only,muted,archived,blocked,username,chat_partner_id) VALUES(:id,:name,:type,:joined,:read_only,:muted,:archived,:blocked,:username,:chat_partner_id)" ) ); - setChannel.bindValue( QStringLiteral( ":id" ), pId ); - setChannel.bindValue( QStringLiteral( ":name" ), pName ); - setChannel.bindValue( QStringLiteral( ":joined" ), pJoined ); - setChannel.bindValue( QStringLiteral( ":type" ), pType ); - setChannel.bindValue( QStringLiteral( ":read_only" ), pReadOnly ); - setChannel.bindValue( QStringLiteral( ":muted" ), pMuted ); - setChannel.bindValue( QStringLiteral( ":archived" ), pArchived ); - setChannel.bindValue( QStringLiteral( ":blocked" ), pBlocked ); - setChannel.bindValue( QStringLiteral( ":username" ), pUsername ); - setChannel.bindValue( QStringLiteral( ":chat_partner_id" ), pChatPartnerId ); - - - if ( !setChannel.exec() ) { - qWarning() << setChannel.lastError(); + queryAddChannel.bindValue( QStringLiteral( ":id" ), pId ); + queryAddChannel.bindValue( QStringLiteral( ":name" ), pName ); + queryAddChannel.bindValue( QStringLiteral( ":joined" ), pJoined ); + queryAddChannel.bindValue( QStringLiteral( ":type" ), pType ); + queryAddChannel.bindValue( QStringLiteral( ":read_only" ), pReadOnly ); + queryAddChannel.bindValue( QStringLiteral( ":muted" ), pMuted ); + queryAddChannel.bindValue( QStringLiteral( ":archived" ), pArchived ); + queryAddChannel.bindValue( QStringLiteral( ":blocked" ), pBlocked ); + queryAddChannel.bindValue( QStringLiteral( ":username" ), pUsername ); + queryAddChannel.bindValue( QStringLiteral( ":chat_partner_id" ), pChatPartnerId ); + + + if ( !queryAddChannel.exec() ) { + qWarning() << queryAddChannel.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::addChannel( const QString &pId, const QString &pName, const QString &pType, bool pJoined, const QString &pUsername, const QString &pMchatPartnerId ) @@ -803,18 +820,15 @@ void PersistanceLayer::addChannel( const QString &pId, const QString &pName, con void PersistanceLayer::deleteChannel( const QString &pId ) { - QSqlQuery deleteQuery; - deleteQuery.prepare( QStringLiteral( "DELETE FROM rooms WHERE id=:id" ) ); - deleteQuery.bindValue( QStringLiteral( ":id" ), pId ); + queryDeleteChannel.bindValue( QStringLiteral( ":id" ), pId ); - if ( !deleteQuery.exec() ) { - qWarning() << deleteQuery.lastError(); + if ( !queryDeleteChannel.exec() ) { + qWarning() << queryDeleteChannel.lastError(); } else { - deleteQuery.prepare( QStringLiteral( "DELETE FROM messages WHERE rid=:id" ) ); - deleteQuery.bindValue( QStringLiteral( ":id" ), pId ); + queryDeleteMessagesFromChannel.bindValue( QStringLiteral( ":id" ), pId ); - if ( !deleteQuery.exec() ) { - qWarning() << deleteQuery.lastError(); + if ( !queryDeleteMessagesFromChannel.exec() ) { + qWarning() << queryDeleteMessagesFromChannel.lastError(); } } } @@ -822,24 +836,21 @@ void PersistanceLayer::deleteChannel( const QString &pId ) void PersistanceLayer::addMessage( const QString &pId, const QString &pRid, const QString &pAuthor, qint64 pTs, const QString &pJson, const QString &pUserId ) { transaction(); - QSqlQuery addMessage( mDb ); - addMessage.prepare( QStringLiteral( "REPLACE INTO messages " - "(id,rid,author,ts,json,read, user_id) VALUES (:id,:rid,:author,:ts,:json,0,:user_id)" ) ); - addMessage.bindValue( QStringLiteral( ":id" ), pId ); - addMessage.bindValue( QStringLiteral( ":rid" ), pRid ); - addMessage.bindValue( QStringLiteral( ":author" ), pAuthor ); - addMessage.bindValue( QStringLiteral( ":ts" ), pTs ); - addMessage.bindValue( QStringLiteral( ":json" ), pJson ); - addMessage.bindValue( QStringLiteral( ":user_id" ), pUserId ); - - if ( !addMessage.exec() ) { + queryAddMessage.bindValue( QStringLiteral( ":id" ), pId ); + queryAddMessage.bindValue( QStringLiteral( ":rid" ), pRid ); + queryAddMessage.bindValue( QStringLiteral( ":author" ), pAuthor ); + queryAddMessage.bindValue( QStringLiteral( ":ts" ), pTs ); + queryAddMessage.bindValue( QStringLiteral( ":json" ), pJson ); + queryAddMessage.bindValue( QStringLiteral( ":user_id" ), pUserId ); + + if ( !queryAddMessage.exec() ) { qWarning() << "id: " << pId << " rid: " << pRid << " author: " << pAuthor << " ts: " << pTs << " json: " << pJson << "userId: " << pUserId; - qWarning() << addMessage.lastQuery(); - qWarning() << addMessage.executedQuery(); - qWarning() << addMessage.lastError(); + qWarning() << queryAddMessage.lastQuery(); + qWarning() << queryAddMessage.executedQuery(); + qWarning() << queryAddMessage.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::addFileCacheEntry( const QString &pUrl, const QString &pPath ) @@ -849,18 +860,16 @@ void PersistanceLayer::addFileCacheEntry( const QString &pUrl, const QString &pP qDebug() << pPath; QDateTime dateTime = QDateTime::currentDateTime(); - QSqlQuery addCacheEntry; - addCacheEntry.prepare( QStringLiteral( "REPLACE INTO file_cache (url,path,ts)" - " VALUES (:url,:path,:ts)" ) ); - addCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl ); - addCacheEntry.bindValue( QStringLiteral( ":path" ), pPath ); - addCacheEntry.bindValue( QStringLiteral( ":ts" ), dateTime.toTime_t() ); - - if ( !addCacheEntry.exec() ) { - qWarning() << addCacheEntry.lastError(); + + queryAddCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl ); + queryAddCacheEntry.bindValue( QStringLiteral( ":path" ), pPath ); + queryAddCacheEntry.bindValue( QStringLiteral( ":ts" ), dateTime.toTime_t() ); + + if ( !queryAddCacheEntry.exec() ) { + qWarning() << queryAddCacheEntry.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory ) @@ -875,52 +884,45 @@ void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath void PersistanceLayer::addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory, const QString &pUnicode, int pOrder ) { transaction(); - QSqlQuery addCustomEmojiQuery; - addCustomEmojiQuery.prepare( QStringLiteral( "REPLACE INTO custom_emojis (id,file,html,unicode,category,sort_order)" - " VALUES (:id,:file,:html,:unicode,:category,:sort_order)" ) ); - addCustomEmojiQuery.bindValue( QStringLiteral( ":id" ), pTag ); - addCustomEmojiQuery.bindValue( QStringLiteral( ":file" ), pPath ); - addCustomEmojiQuery.bindValue( QStringLiteral( ":html" ), pHtml ); - addCustomEmojiQuery.bindValue( QStringLiteral( ":unicode" ), pUnicode ); - addCustomEmojiQuery.bindValue( QStringLiteral( ":category" ), pCategory ); - addCustomEmojiQuery.bindValue( QStringLiteral( ":sort_order" ), pOrder ); - - if ( !addCustomEmojiQuery.exec() ) { - qWarning() << addCustomEmojiQuery.lastError(); + queryAddEmoji.bindValue( QStringLiteral( ":id" ), pTag ); + queryAddEmoji.bindValue( QStringLiteral( ":file" ), pPath ); + queryAddEmoji.bindValue( QStringLiteral( ":html" ), pHtml ); + queryAddEmoji.bindValue( QStringLiteral( ":unicode" ), pUnicode ); + queryAddEmoji.bindValue( QStringLiteral( ":category" ), pCategory ); + queryAddEmoji.bindValue( QStringLiteral( ":sort_order" ), pOrder ); + + if ( !queryAddEmoji.exec() ) { + qWarning() << queryAddEmoji.lastError(); } - commit(); + askForcommit(); } void PersistanceLayer::addUserToBlockList( const QString &pUserId, const QString &pUsername ) { transaction(); - QSqlQuery addUserQuery; - addUserQuery.prepare( QStringLiteral( "INSERT INO blocked_users(id, author) VALUES(:id,:author)" ) ); - addUserQuery.bindValue( ":id", pUserId ); - addUserQuery.bindValue( ":author", pUsername ); + queryAddUser.bindValue( ":id", pUserId ); + queryAddUser.bindValue( ":author", pUsername ); - if ( !addUserQuery.exec() ) { - qWarning() << addUserQuery.lastError(); + if ( !queryAddUser.exec() ) { + qWarning() << queryAddUser.lastError(); } - commit(); + askForcommit(); } QHash<QString, QString> PersistanceLayer::getMessageByid( const QString &pId ) { - QSqlQuery message; - message.prepare( QStringLiteral( "SELECT * FROM messages LEFT JOIN blocked_users ON (messages.user_id=blocked_users.user_id) WHERE blocked_users.user_id IS NULL AND id=:id" ) ); - message.bindValue( QStringLiteral( ":id" ), pId ); + queryGetMessageByRid.bindValue( QStringLiteral( ":id" ), pId ); QHash<QString, QString> row; - if ( !message.exec() ) { - qWarning() << message.lastError(); + if ( !queryGetMessageByRid.exec() ) { + qWarning() << queryGetMessageByRid.lastError(); } else { - QSqlRecord rec = message.record(); + QSqlRecord rec = queryGetMessageByRid.record(); int idCol = rec.indexOf( QStringLiteral( "id" ) ); int ridCol = rec.indexOf( QStringLiteral( "rid" ) ); int authorCol = rec.indexOf( QStringLiteral( "author" ) ); @@ -928,36 +930,35 @@ QHash<QString, QString> PersistanceLayer::getMessageByid( const QString &pId ) int messageCol = rec.indexOf( QStringLiteral( "message" ) ); int typeCol = rec.indexOf( QStringLiteral( "type" ) ); - while ( message.next() ) { - row[QStringLiteral( "id" )] = message.value( idCol ).toString(); - row[QStringLiteral( "rid" )] = message.value( ridCol ).toString(); - row[QStringLiteral( "author" )] = message.value( authorCol ).toString(); - row[QStringLiteral( "message" )] = message.value( messageCol ).toString(); - row[QStringLiteral( "ts" )] = message.value( tsCol ).toString(); - row[QStringLiteral( "type" )] = message.value( typeCol ).toString(); + while ( queryGetMessageByRid.next() ) { + row[QStringLiteral( "id" )] = queryGetMessageByRid.value( idCol ).toString(); + row[QStringLiteral( "rid" )] = queryGetMessageByRid.value( ridCol ).toString(); + row[QStringLiteral( "author" )] = queryGetMessageByRid.value( authorCol ).toString(); + row[QStringLiteral( "message" )] = queryGetMessageByRid.value( messageCol ).toString(); + row[QStringLiteral( "ts" )] = queryGetMessageByRid.value( tsCol ).toString(); + row[QStringLiteral( "type" )] = queryGetMessageByRid.value( typeCol ).toString(); } } + queryGetMessageByRid.finish(); return row; } QString PersistanceLayer::getUserName() { - QSqlQuery getName; - getName.prepare( QStringLiteral( "SELECT username FROM user_data WHERE id=0" ) ); QString name = ""; - if ( !getName.exec() ) { - qWarning() << getName.lastError(); + if ( !queryGetName.exec() ) { + qWarning() << queryGetName.lastError(); } else { - QSqlRecord rec = getName.record(); + QSqlRecord rec = queryGetName.record(); int nameCol = rec.indexOf( QStringLiteral( "username" ) ); - while ( getName.next() ) { - name = getName.value( nameCol ).toString(); + while ( queryGetName.next() ) { + name = queryGetName.value( nameCol ).toString(); } } @@ -966,111 +967,105 @@ QString PersistanceLayer::getUserName() std::tuple<QString, QString> PersistanceLayer::getCurrentChannel() { - QSqlQuery getChannel; - getChannel.prepare( QStringLiteral( "SELECT * FROM current_room WHERE id=0" ) ); QString id; QString name; - if ( !getChannel.exec() ) { - qWarning() << getChannel.lastError(); + if ( !queryGetCurrentChannel.exec() ) { + qWarning() << queryGetCurrentChannel.lastError(); } else { - while ( getChannel.next() ) { - id = getChannel.value( QStringLiteral( "rid" ) ).toString(); - name = getChannel.value( QStringLiteral( "name" ) ).toString(); + while ( queryGetCurrentChannel.next() ) { + id = queryGetCurrentChannel.value( QStringLiteral( "rid" ) ).toString(); + name = queryGetCurrentChannel.value( QStringLiteral( "name" ) ).toString(); } } + queryGetCurrentChannel.finish(); return std::tuple<QString, QString>( id, name ); } QString PersistanceLayer::getPassword() { - QSqlQuery getPass; - getPass.prepare( QStringLiteral( "SELECT password FROM user_data WHERE id=0" ) ); QString pass = ""; - if ( !getPass.exec() ) { - qWarning() << getPass.lastError(); + if ( !queryGetPass.exec() ) { + qWarning() << queryGetPass.lastError(); } else { - QSqlRecord rec = getPass.record(); + QSqlRecord rec = queryGetPass.record(); int nameCol = rec.indexOf( QStringLiteral( "password" ) ); - while ( getPass.next() ) { - pass = getPass.value( nameCol ).toString(); + while ( queryGetPass.next() ) { + pass = queryGetPass.value( nameCol ).toString(); } } + queryGetPass.finish(); return pass; } QPair<QString, uint> PersistanceLayer::getToken() { - QSqlQuery getToken; - getToken.prepare( QStringLiteral( "SELECT token, token_expire FROM user_data WHERE id=0" ) ); // getToken.bindValue( ":id", 0 ); QPair<QString, uint> token; - if ( !getToken.exec() ) { - qWarning() << getToken.lastError(); + if ( !queryGetToken.exec() ) { + qDebug() << queryGetToken.lastError(); } else { - QSqlRecord rec = getToken.record(); + QSqlRecord rec = queryGetToken.record(); int tokenCol = rec.indexOf( QStringLiteral( "token" ) ); int expireCol = rec.indexOf( QStringLiteral( "token_expire" ) ); - while ( getToken.next() ) { - token.first = getToken.value( tokenCol ).toString(); - token.second = getToken.value( expireCol ).toUInt(); + while ( queryGetToken.next() ) { + token.first = queryGetToken.value( tokenCol ).toString(); + token.second = queryGetToken.value( expireCol ).toUInt(); } } + queryGetToken.finish(); return token; } QString PersistanceLayer::getUserId() { - QSqlQuery getUserId; - getUserId.prepare( "SELECT id,user_id FROM user_data WHERE id=0" ); //getUserId.addBindValue( ":id", 0 ); QString userId; - if ( !getUserId.exec() ) { - qWarning() << "userid error" << getUserId.lastError(); + if ( !queryGetUserId.exec() ) { + qWarning() << "userid error" << queryGetUserId.lastError(); } else { - QSqlRecord rec = getUserId.record(); + QSqlRecord rec = queryGetUserId.record(); int userIdCol = rec.indexOf( QStringLiteral( "user_id" ) ); - while ( getUserId.next() ) { - userId = getUserId.value( userIdCol ).toString(); + while ( queryGetUserId.next() ) { + userId = queryGetUserId.value( userIdCol ).toString(); } } + queryGetUserId.finish(); return userId; } QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid ) { - QSqlQuery messages; - messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid ORDER BY ts DESC LIMIT 20" ) ); - messages.bindValue( QStringLiteral( ":rid" ), pRid ); + queryGetMessagesByRid.bindValue( QStringLiteral( ":rid" ), pRid ); QList<QJsonObject> rows; rows.reserve( 50 ); - if ( !messages.exec() ) { + if ( !queryGetMessagesByRid.exec() ) { qWarning() << QStringLiteral( "request room with rid: " ) << pRid; - qWarning() << messages.lastError(); + qWarning() << queryGetMessagesByRid.lastError(); } else { - QSqlRecord rec = messages.record(); + QSqlRecord rec = queryGetMessagesByRid.record(); int jsonCol = rec.indexOf( QStringLiteral( "json" ) ); int readCol = rec.indexOf( QStringLiteral( "read" ) ); - while ( messages.next() ) { + while ( queryGetMessagesByRid.next() ) { //QHash<QString,QJsonObject> entry; - QString json = messages.value( jsonCol ).toString(); - bool read = messages.value( readCol ).toBool(); + QString json = queryGetMessagesByRid.value( jsonCol ).toString(); + bool read = queryGetMessagesByRid.value( readCol ).toBool(); QJsonDocument doc = QJsonDocument::fromJson( json.toUtf8() ); QJsonObject object = doc.object(); object[QStringLiteral( "read" )] = read; @@ -1081,33 +1076,32 @@ QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid ) } } + queryGetMessagesByRid.finish(); return rows; } QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid, qint64 pFrom, qint64 pTo ) { - QSqlQuery messages; - messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from AND ts>=:to ORDER BY ts DESC LIMIT 50" ) ); - messages.bindValue( QStringLiteral( ":rid" ), pRid ); - messages.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom / 1000 ) ); - messages.bindValue( QStringLiteral( ":to" ), static_cast<qint64>( pTo / 1000 ) ); + queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":rid" ), pRid ); + queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom / 1000 ) ); + queryGetMessageByRidAndRange.bindValue( QStringLiteral( ":to" ), static_cast<qint64>( pTo / 1000 ) ); QList<QJsonObject> rows; rows.reserve( 50 ); - if ( !messages.exec() ) { + if ( !queryGetMessageByRidAndRange.exec() ) { qWarning() << "request room with rid: " << pRid; - qWarning() << messages.lastError(); + qWarning() << queryGetMessageByRidAndRange.lastError(); } else { - QSqlRecord rec = messages.record(); + QSqlRecord rec = queryGetMessageByRidAndRange.record(); int jsonCol = rec.indexOf( QStringLiteral( "json" ) ); int readCol = rec.indexOf( QStringLiteral( "read" ) ); - while ( messages.next() ) { - QString json = messages.value( jsonCol ).toString(); - bool read = messages.value( readCol ).toBool(); + while ( queryGetMessageByRidAndRange.next() ) { + QString json = queryGetMessageByRidAndRange.value( jsonCol ).toString(); + bool read = queryGetMessageByRidAndRange.value( readCol ).toBool(); QJsonDocument doc = QJsonDocument::fromJson( json.toUtf8() ); QJsonObject object = doc.object(); object[QStringLiteral( "read" )] = read; @@ -1118,34 +1112,33 @@ QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid, qint } } + queryGetMessageByRidAndRange.finish(); return rows; } QList<QJsonObject > PersistanceLayer::getMessagesByRid( const QString &pRid, qint64 pFrom, int pLimit ) { - QSqlQuery messages; - messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from ORDER BY ts DESC LIMIT :limit" ) ); - messages.bindValue( QStringLiteral( ":rid" ), pRid ); - messages.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom ) ); - messages.bindValue( QStringLiteral( ":limit" ), pLimit ); + queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":rid" ), pRid ); + queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom ) ); + queryGetMessagesByRidLimit.bindValue( QStringLiteral( ":limit" ), pLimit ); QList<QJsonObject > rows; rows.reserve( 50 ); - if ( !messages.exec() ) { + if ( !queryGetMessagesByRidLimit.exec() ) { qWarning() << "request room with rid: " << pRid; - qWarning() << messages.lastError(); + qWarning() << queryGetMessagesByRidLimit.lastError(); } else { - QSqlRecord rec = messages.record(); + QSqlRecord rec = queryGetMessagesByRidLimit.record(); int jsonCol = rec.indexOf( QStringLiteral( "json" ) ); int readCol = rec.indexOf( QStringLiteral( "read" ) ); - while ( messages.next() ) { + while ( queryGetMessagesByRidLimit.next() ) { // QHash<QString,QJsonObject> entry; - QString json = messages.value( jsonCol ).toString(); - bool read = messages.value( readCol ).toBool(); + QString json = queryGetMessagesByRidLimit.value( jsonCol ).toString(); + bool read = queryGetMessagesByRidLimit.value( readCol ).toBool(); QJsonDocument doc = QJsonDocument::fromJson( json.toUtf8() ); QJsonObject object = doc.object(); @@ -1161,46 +1154,44 @@ QList<QJsonObject > PersistanceLayer::getMessagesByRid( const QString &pRid, qin } } + queryGetMessagesByRidLimit.finish(); return rows; } QList<QPair<QString, QString >> PersistanceLayer::getListOfBlockedUsers() { - QSqlQuery usersQuery; - usersQuery.prepare( QStringLiteral( "SELECT * FROM blocked_users" ) ); QList<QPair<QString, QString >> retList; - if ( !usersQuery.exec() ) { + if ( !queryGetBlockedUsers.exec() ) { qWarning() << "getList of blocked users "; - qWarning() << usersQuery.lastError(); + qWarning() << queryGetBlockedUsers.lastError(); } else { - QSqlRecord rec = usersQuery.record(); + QSqlRecord rec = queryGetBlockedUsers.record(); int idCol = rec.indexOf( "id" ); int nameCol = rec.indexOf( "author" ); - while ( usersQuery.next() ) { + while ( queryGetBlockedUsers.next() ) { QPair<QString, QString> pair; - pair.first = usersQuery.value( idCol ).String; - pair.second = usersQuery.value( nameCol ).String; + pair.first = queryGetBlockedUsers.value( idCol ).String; + pair.second = queryGetBlockedUsers.value( nameCol ).String; retList.append( pair ); } } + queryGetBlockedUsers.finish(); return retList; } QList<QVariantHash> PersistanceLayer::getChannels( ) { - QSqlQuery rooms; - rooms.prepare( QStringLiteral( "SELECT * FROM rooms LEFT JOIN (SELECT DISTINCT rid FROM messages ORDER BY ts DESC) AS sub ON rooms.id = sub.rid " ) ); QList<QVariantHash> roomsList; roomsList.reserve( 100 ); - if ( !rooms.exec() ) { - qWarning() << rooms.lastError(); + if ( !queryGetChannels.exec() ) { + qWarning() << queryGetChannels.lastError(); } else { - QSqlRecord rec = rooms.record(); + QSqlRecord rec = queryGetChannels.record(); int idCol = rec.indexOf( QStringLiteral( "id" ) ); int nameCol = rec.indexOf( QStringLiteral( "name" ) ); int joinedCol = rec.indexOf( QStringLiteral( "joined" ) ); @@ -1213,40 +1204,39 @@ QList<QVariantHash> PersistanceLayer::getChannels( ) int chatPartnerIdCol = rec.indexOf( QStringLiteral( "chat_partner_id" ) ); - while ( rooms.next() ) { + while ( queryGetChannels.next() ) { QVariantHash roomsHash; - QString muted = rooms.value( mutedCol ).toString(); - roomsHash[QStringLiteral( "id" )] = rooms.value( idCol ).toString(); - roomsHash[QStringLiteral( "name" )] = rooms.value( nameCol ).toString(); - roomsHash[QStringLiteral( "joined" )] = rooms.value( joinedCol ).toBool(); - roomsHash[QStringLiteral( "type" )] = rooms.value( typeCol ).toString(); - roomsHash[QStringLiteral( "readOnly" )] = rooms.value( readOnlyCol ).toBool(); + QString muted = queryGetChannels.value( mutedCol ).toString(); + roomsHash[QStringLiteral( "id" )] = queryGetChannels.value( idCol ).toString(); + roomsHash[QStringLiteral( "name" )] = queryGetChannels.value( nameCol ).toString(); + roomsHash[QStringLiteral( "joined" )] = queryGetChannels.value( joinedCol ).toBool(); + roomsHash[QStringLiteral( "type" )] = queryGetChannels.value( typeCol ).toString(); + roomsHash[QStringLiteral( "readOnly" )] = queryGetChannels.value( readOnlyCol ).toBool(); roomsHash[QStringLiteral( "muted" )] = muted; roomsHash[QStringLiteral( "list" )] = muted.split( ',' ); - roomsHash[QStringLiteral( "archived" )] = rooms.value( archivedCol ).toBool(); - roomsHash[QStringLiteral( "blocked" )] = rooms.value( blocked ).toBool(); - roomsHash[QStringLiteral( "username" )] = rooms.value( usernameCol ).toString(); - roomsHash[QStringLiteral( "chatPartnerId" )] = rooms.value( chatPartnerIdCol ).toString(); + roomsHash[QStringLiteral( "archived" )] = queryGetChannels.value( archivedCol ).toBool(); + roomsHash[QStringLiteral( "blocked" )] = queryGetChannels.value( blocked ).toBool(); + roomsHash[QStringLiteral( "username" )] = queryGetChannels.value( usernameCol ).toString(); + roomsHash[QStringLiteral( "chatPartnerId" )] = queryGetChannels.value( chatPartnerIdCol ).toString(); roomsList.append( roomsHash ); } } + queryGetChannels.finish(); return roomsList; } QList< QHash<QString, QString > > PersistanceLayer::getCustomEmojis() { - QSqlQuery emojiQuery; - emojiQuery.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis ORDER BY sort_order ASC" ) ); QList<QHash<QString, QString> > returnList; returnList.reserve( 3000 ); - if ( !emojiQuery.exec() ) { - qWarning() << emojiQuery.lastError(); + if ( !queryGetEmojies.exec() ) { + qWarning() << queryGetEmojies.lastError(); } else { - QSqlRecord rec = emojiQuery.record(); + QSqlRecord rec = queryGetEmojies.record(); int idCol = rec.indexOf( QStringLiteral( "id" ) ); int fileCol = rec.indexOf( QStringLiteral( "file" ) ); @@ -1255,38 +1245,37 @@ QList< QHash<QString, QString > > PersistanceLayer::getCustomEmojis() int unicodeCol = rec.indexOf( QStringLiteral( "unicode" ) ); int orderCol = rec.indexOf( QStringLiteral( "sort_order" ) ); - while ( emojiQuery.next() ) { + while ( queryGetEmojies.next() ) { QHash<QString, QString> entry; - entry[QStringLiteral( "id" )] = emojiQuery.value( idCol ).toString(); - entry[QStringLiteral( "file" )] = emojiQuery.value( fileCol ).toString(); - entry[QStringLiteral( "html" )] = emojiQuery.value( htmlCol ).toString(); - entry[QStringLiteral( "category" )] = emojiQuery.value( catCol ).toString(); - entry[QStringLiteral( "unicode" )] = emojiQuery.value( unicodeCol ).toString(); - entry[QStringLiteral( "sort_order" )] = emojiQuery.value( orderCol ).toString(); + entry[QStringLiteral( "id" )] = queryGetEmojies.value( idCol ).toString(); + entry[QStringLiteral( "file" )] = queryGetEmojies.value( fileCol ).toString(); + entry[QStringLiteral( "html" )] = queryGetEmojies.value( htmlCol ).toString(); + entry[QStringLiteral( "category" )] = queryGetEmojies.value( catCol ).toString(); + entry[QStringLiteral( "unicode" )] = queryGetEmojies.value( unicodeCol ).toString(); + entry[QStringLiteral( "sort_order" )] = queryGetEmojies.value( orderCol ).toString(); returnList.append( entry ); } } + queryGetEmojies.finish(); return returnList; } QString PersistanceLayer::getFileCacheEntry( const QString &pUrl ) { - QSqlQuery cacheEntry; - cacheEntry.prepare( QStringLiteral( "SELECT path FROM file_cache WHERE url=:url" ) ); - cacheEntry.bindValue( QStringLiteral( ":url" ), pUrl ); + queryGetFileCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl ); QString returnString = ""; - if ( !cacheEntry.exec() ) { - qWarning() << cacheEntry.lastError(); + if ( !queryGetFileCacheEntry.exec() ) { + qWarning() << queryGetFileCacheEntry.lastError(); } else { - QSqlRecord rec = cacheEntry.record(); + QSqlRecord rec = queryGetFileCacheEntry.record(); int pathCol = rec.indexOf( QStringLiteral( "path" ) ); - while ( cacheEntry.next() ) { - returnString = cacheEntry.value( pathCol ).toString(); + while ( queryGetFileCacheEntry.next() ) { + returnString = queryGetFileCacheEntry.value( pathCol ).toString(); } if ( returnString != "" ) { @@ -1299,28 +1288,28 @@ QString PersistanceLayer::getFileCacheEntry( const QString &pUrl ) } } + queryGetFileCacheEntry.finish(); return returnString; } QString PersistanceLayer::getSetting( const QString &pProperty ) { - QSqlQuery settingsEntry; - settingsEntry.prepare( QStringLiteral( "SELECT property,value FROM app_settings WHERE property=:property" ) ); - settingsEntry.bindValue( QStringLiteral( ":property" ), pProperty ); + queryGetSetting.bindValue( QStringLiteral( ":property" ), pProperty ); QString returnString = ""; - if ( !settingsEntry.exec() ) { - qWarning() << settingsEntry.lastError(); + if ( !queryGetSetting.exec() ) { + qWarning() << queryGetSetting.lastError(); } else { - QSqlRecord rec = settingsEntry.record(); + QSqlRecord rec = queryGetSetting.record(); int valueClol = rec.indexOf( QStringLiteral( "value" ) ); - while ( settingsEntry.next() ) { - returnString = settingsEntry.value( valueClol ).toString(); + while ( queryGetSetting.next() ) { + returnString = queryGetSetting.value( valueClol ).toString(); } } + queryGetSetting.finish(); return returnString; } @@ -1345,15 +1334,13 @@ void PersistanceLayer::removeFileCacheEntry( const QString &pUrl, const QString } } - QSqlQuery cacheEntry; - cacheEntry.prepare( QStringLiteral( "DELETE FROM file_cache WHERE url=:url" ) ); - cacheEntry.bindValue( QStringLiteral( ":url" ), pUrl ); + queryRemoveFileCacheEntry.bindValue( QStringLiteral( ":url" ), pUrl ); - if ( !cacheEntry.exec() ) { - qWarning() << cacheEntry.lastError(); + if ( !queryRemoveFileCacheEntry.exec() ) { + qWarning() << queryRemoveFileCacheEntry.lastError(); } - commit(); + askForcommit(); } @@ -1451,12 +1438,12 @@ void PersistanceLayer::init() throw std::runtime_error( mDb.lastError().text().toStdString() + "file used:" + filePath.toStdString() ); } - commitTimer.setInterval( 3000 ); - commitTimer.start(); + // commitTimer.setInterval( 10000 ); connect( &commitTimer, &QTimer::timeout, [&]() { commit(); commitTimer.start(); } ); + // commitTimer.start(); mDbReady = true; initShema(); emit( ready() ); @@ -1467,7 +1454,52 @@ void PersistanceLayer::init() } } +void PersistanceLayer::initQueries() +{ + querySetUsername.prepare( QStringLiteral( "UPDATE user_data " + "SET username=:username WHERE id=:id" ) ); + querySetPassword.prepare( QStringLiteral( "UPDATE user_data " + "SET password=:password WHERE id=:id" ) ); + querySetToken.prepare( QStringLiteral( "UPDATE user_data " + "SET token=:token, token_expire=:token_expire WHERE id=:id" ) ); + querySetUser.prepare( QStringLiteral( "REPLACE INTO user_data " + "(id,password,username) VALUES(:id,:password,:username)" ) ); + querySetUserId.prepare( QStringLiteral( "UPDATE user_data SET user_id=:userId WHERE id=:id" ) ); + + querySetChannel.prepare( QStringLiteral( "REPLACE INTO current_room" + " (id,rid,name) VALUES(:id,:rid,:name)" ) ); + querySetSetting.prepare( QStringLiteral( "REPLACE INTO app_settings" + " (property,value) VALUES(:property,:value)" ) ); + queryAddChannel.prepare( QStringLiteral( "REPLACE INTO rooms " + "(id,name,type,joined,read_only,muted,archived,blocked,username,chat_partner_id) VALUES(:id,:name,:type,:joined,:read_only,:muted,:archived,:blocked,:username,:chat_partner_id)" ) ); + queryDeleteChannel.prepare( QStringLiteral( "DELETE FROM rooms WHERE id=:id" ) ); + queryDeleteMessagesFromChannel.prepare( QStringLiteral( "DELETE FROM messages WHERE rid=:id" ) ); + queryAddMessage.prepare( QStringLiteral( "REPLACE INTO messages " + "(id,rid,author,ts,json,read, user_id) VALUES (:id,:rid,:author,:ts,:json,0,:user_id)" ) ); + queryAddCacheEntry.prepare( QStringLiteral( "REPLACE INTO file_cache (url,path,ts)" + " VALUES (:url,:path,:ts)" ) ); + queryAddEmoji.prepare( QStringLiteral( "REPLACE INTO custom_emojis (id,file,html,unicode,category,sort_order)" + " VALUES (:id,:file,:html,:unicode,:category,:sort_order)" ) ); + queryAddUser.prepare( QStringLiteral( "INSERT INO blocked_users(id, author) VALUES(:id,:author)" ) ); + queryGetMessageByRid.prepare( QStringLiteral( "SELECT * FROM messages LEFT JOIN blocked_users ON (messages.user_id=blocked_users.user_id) WHERE blocked_users.user_id IS NULL AND id=:id" ) ); + queryGetName.prepare( QStringLiteral( "SELECT username FROM user_data WHERE id=0" ) ); + queryGetCurrentChannel.prepare( QStringLiteral( "SELECT * FROM current_room WHERE id=0" ) ); + queryGetPass.prepare( QStringLiteral( "SELECT password FROM user_data WHERE id=0" ) ); + queryGetToken.prepare( QStringLiteral( "SELECT token, token_expire FROM user_data WHERE id=0" ) ); + queryGetUserId.prepare( "SELECT id,user_id FROM user_data WHERE id=0" ); + queryGetMessagesByRid.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid ORDER BY ts DESC LIMIT 20" ) ); + queryGetMessageByRidAndRange.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from AND ts>=:to ORDER BY ts DESC LIMIT 50" ) ); + queryGetMessagesByRidLimit.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from ORDER BY ts DESC LIMIT :limit" ) ); + queryGetBlockedUsers.prepare( QStringLiteral( "SELECT * FROM blocked_users" ) ); + queryGetChannels.prepare( QStringLiteral( "SELECT * FROM rooms LEFT JOIN (SELECT DISTINCT rid FROM messages ORDER BY ts DESC) AS sub ON rooms.id = sub.rid " ) ); + queryGetEmojies.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis ORDER BY sort_order ASC" ) ); + queryGetFileCacheEntry.prepare( QStringLiteral( "SELECT path FROM file_cache WHERE url=:url" ) ); + queryGetSetting.prepare( QStringLiteral( "SELECT property,value FROM app_settings WHERE property=:property" ) ); + queryRemoveFileCacheEntry.prepare( QStringLiteral( "DELETE FROM file_cache WHERE url=:url" ) ); + +} + void PersistanceLayer::close() { - delete persistanceLayer; + persistanceLayer->deleteLater(); } diff --git a/persistancelayer.h b/persistancelayer.h index f1b918607db4d6dd0c99bce8e1854a72e580151b..bf107ed8be791c90c41a4dee3c8a318e7d188b7c 100755 --- a/persistancelayer.h +++ b/persistancelayer.h @@ -5,6 +5,7 @@ #include <QObject> #include <QMetaObject> #include <QtSql/QSqlDatabase> +#include <QtSql/QSqlQuery> #include <QFile> #include <QMimeDatabase> #include <QMimeType> @@ -48,6 +49,7 @@ class PersistanceLayer : public QObject void addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory, const QString &pUnicode ); void addCustomEmoji( const QString &pTag, const QString &pPath, const QString &pHtml, const QString &pCategory, const QString &pUnicode, int pOrder ); void addUserToBlockList( const QString &pUserId, const QString &pUsername ); + void close(); public: @@ -83,7 +85,7 @@ class PersistanceLayer : public QObject void removeFileCacheEntry( const QString &pUrl, const QString &pPath ); void transaction( void ); - void commit( void ); + void askForcommit( void ); void wipeDb( void ); bool transactionActive = false; @@ -91,19 +93,54 @@ class PersistanceLayer : public QObject ~PersistanceLayer(); void init(); - void close(); bool mDbReady = false; private: + void commit( void ); PersistanceLayer() {} QSqlDatabase mDb{ QSqlDatabase::addDatabase( "QSQLITE" )}; QMimeDatabase mMimeDb; QTimer commitTimer; + QMutex commitMutex; void initShema(); - + void initQueries(); void upgradeSchema(); int mCommitCounter = 0; + int mTransactionCounter = 0; + + + QSqlQuery querySetUsername; + QSqlQuery querySetPassword; + QSqlQuery querySetToken; + QSqlQuery querySetUser; + QSqlQuery querySetUserId; + QSqlQuery querySetChannel; + QSqlQuery querySetSetting; + QSqlQuery queryAddChannel; + QSqlQuery queryDeleteChannel; + QSqlQuery queryDeleteMessagesFromChannel; + QSqlQuery queryAddMessage; + QSqlQuery queryAddCacheEntry; + QSqlQuery queryAddEmoji; + QSqlQuery queryAddUser; + QSqlQuery queryGetMessageByRid; + QSqlQuery queryGetName; + QSqlQuery queryGetCurrentChannel; + QSqlQuery queryGetPass; + QSqlQuery queryGetToken; + QSqlQuery queryGetUserId; + QSqlQuery queryGetMessagesByRid; + QSqlQuery queryGetMessageByRidAndRange; + QSqlQuery queryGetMessagesByRidLimit; + QSqlQuery queryGetBlockedUsers; + QSqlQuery queryGetChannels; + QSqlQuery queryGetEmojies; + QSqlQuery queryGetFileCacheEntry; + QSqlQuery queryGetSetting; + QSqlQuery queryRemoveFileCacheEntry; + + signals: void userDataChanged(); diff --git a/rocketchat.cpp b/rocketchat.cpp index 1c11283d5e826486efc3789738365f7fae6fd44e..1c15565dc6b85a9629855c2a02bf8974f027cd5d 100755 --- a/rocketchat.cpp +++ b/rocketchat.cpp @@ -98,15 +98,17 @@ RocketChat::~RocketChat() mServerThread.quit(); } else { for ( auto element : mServerMap ) { - connect( element, &RocketChatServerData::destroyed, [ = ]() { + connect( element, &RocketChatServerData::destroyed, [ & ]() { destructCounter--; if ( !destructCounter ) { - mServerThread.quit(); + connect( PersistanceLayer::instance(), &PersistanceLayer::destroyed, [&]() { + mServerThread.quit(); + } ); + QMetaObject::invokeMethod( PersistanceLayer::instance(), "close" ); } } ); - - element->deleteLater(); + QMetaObject::invokeMethod( element, "deleteLater" ); } } @@ -883,7 +885,11 @@ void RocketChat::onApplicationStateChanged( const Qt::ApplicationState &pState ) } else { mInitialized = 1; } - } else if ( ( ( pState == Qt::ApplicationInactive ) || pState == Qt::ApplicationSuspended ) && mServerStatus ) { + + } + +#if defined(Q_OS_ANDROID)||defined(Q_OS_IOS) + else if ( ( ( pState == Qt::ApplicationInactive ) || pState == Qt::ApplicationSuspended ) && mServerStatus ) { qDebug() << "away"; if ( mNetworkConfiguration.isOnline() ) { @@ -894,6 +900,8 @@ void RocketChat::onApplicationStateChanged( const Qt::ApplicationState &pState ) } } } + +#endif } bool RocketChat::getDdpConnectionEstablished() const diff --git a/rocketchatserver.cpp b/rocketchatserver.cpp index 539f09fb070aef4f9709c4a7a987f14c64b8d434..a8051e3f2c84678e1a6c40cde1f8853fb15307d9 100755 --- a/rocketchatserver.cpp +++ b/rocketchatserver.cpp @@ -68,7 +68,7 @@ void RocketChatServerData::initConnections() } } - mStorage->commit(); + mStorage->askForcommit(); delete messages; @@ -80,6 +80,34 @@ void RocketChatServerData::initConnections() protocol = QStringLiteral( "http://" ); } + if ( mRestApi != nullptr ) { + mRestApi->deleteLater(); + } + + if ( mFileService != nullptr ) { + delete mFileService; + } + + if ( mEmojiService != nullptr ) { + delete mEmojiService; + } + + if ( mDdpApi != nullptr ) { + mDdpApi->deleteLater(); + } + + if ( mChannels != nullptr ) { + mChannels->deleteLater(); + } + + if ( mMessageService != nullptr ) { + mMessageService->deleteLater(); + } + + if ( mChannelService != nullptr ) { + mChannelService->deleteLater(); + } + setRestApi( new RestApi( this, protocol + mBaseUrl ) ); mFileService = new FileService( this ); mEmojiService = new EmojiService( this, mFileService, mStorage ); @@ -135,11 +163,11 @@ void RocketChatServerData::initConnections() if ( !tokenDb.first.isEmpty() && tokenDb.second > currentTime.toTime_t() ) { loginWithToken( userDb, tokenDb.first ); } else { - mStorage->wipeDb(); + wipeDbAndReconnect(); emit loggedOut( mServerId ); } } else if ( !lastServer.isEmpty() ) { - mStorage->wipeDb(); + wipeDbAndReconnect(); emit loggedOut( mServerId ); } @@ -582,6 +610,13 @@ void RocketChatServerData::offlineLogin() } } +void RocketChatServerData::wipeDbAndReconnect() +{ + disconnectFromServer(); + mStorage->wipeDb(); + resume(); +} + QSharedPointer<RocketChatUser> RocketChatServerData::getOwnUser() const { return mOwnUser; @@ -605,66 +640,62 @@ QString RocketChatServerData::getBaseUrl() const void RocketChatServerData::login( const QString &pUsername, const QString &pPassword ) { - if ( pUsername != mStorage->getUserName() ) { - mStorage->wipeDb(); - } + QString pass; - QPair<QString, uint> tokenDb = mStorage->getToken(); - QString userDb = mStorage->getUserName(); - QDateTime currentTime = QDateTime::currentDateTime(); - - if ( !tokenDb.first.isEmpty() && tokenDb.second > currentTime.toTime_t() ) { - loginWithToken( userDb, tokenDb.first ); - } else { - QString passDb = mStorage->getPassword(); - QString pass; - QString username = pUsername; - - if ( passDb.length() ) { - username = userDb; - pass = passDb; - } else { - QByteArray hashArray = QCryptographicHash::hash( pPassword.toUtf8(), QCryptographicHash::Sha256 ); - pass = hashArray.toHex(); - } + QByteArray hashArray = QCryptographicHash::hash( pPassword.toUtf8(), QCryptographicHash::Sha256 ); + pass = hashArray.toHex(); - loginWithHash( username, pass ); - } + loginWithHash( pUsername, pass ); } void RocketChatServerData::loginWithHash( const QString &pUsername, const QString &pPswHash ) { qDebug() << "login with hash"; - auto self = this; + RestRequestCallback meCallBackSuccess = [ = ]( QNetworkReply *, QJsonObject data, RestApi * ) { + if ( data.contains( QStringLiteral( "username" ) ) ) { + mUsername = data[QStringLiteral( "username" )].toString(); + mStorage->transaction(); + mStorage->setUserData( mUsername, "" ); + mStorage->setToken( mResumeToken, mTokenExpire ); + mStorage->setUserId( mUserId ); + mStorage->askForcommit(); + onResume(); + onDDPAuthenticated(); + } + + }; auto request = QSharedPointer<DDPLoginRequest>::create( pUsername, pPswHash ); - DdpCallback success = [ self, pUsername, pPswHash, request ]( QJsonObject pResponse, MeteorDDP * ) { + DdpCallback success = [ = ]( QJsonObject pResponse, MeteorDDP * ) { qDebug() << "authenticated"; if ( pResponse.contains( QStringLiteral( "result" ) ) ) { QJsonObject result = pResponse[QStringLiteral( "result" )].toObject(); if ( result.contains( QStringLiteral( "token" ) ) && result.contains( QStringLiteral( "id" ) ) ) { - self->mConnectionState = ConnectionState::ONLINE; - self->mResumeToken = result[QStringLiteral( "token" )].toString(); + mConnectionState = ConnectionState::ONLINE; + mResumeToken = result[QStringLiteral( "token" )].toString(); QJsonObject expireObject = result[QStringLiteral( "tokenExpires" )].toObject(); double expireDouble = expireObject[QStringLiteral( "$date" )].toDouble(); - self->mTokenExpire = static_cast<uint>( expireDouble / 1000 ); + mTokenExpire = static_cast<uint>( expireDouble / 1000 ); QString userId = result[QStringLiteral( "id" )].toString(); - self->setUserId( userId ); - self->mStorage->transaction(); - self->mStorage->setUserData( pUsername, pPswHash ); - self->mStorage->setToken( self->mResumeToken, self->mTokenExpire ); - self->mStorage->setUserId( userId ); - self->mRestApi->setToken( self->mResumeToken ); - self->mRestApi->setUserId( userId ); - self->mStorage->commit(); - self->mDdpApi->setToken( self->mResumeToken ); - self->mDdpApi->unsetResponseBinding( request->getFrame() ); - self->onDDPAuthenticated(); - emit( self->onHashLoggedIn( self->mServerId ) ); + + setUserId( userId ); + mStorage->transaction(); + mStorage->setUserData( pUsername, pPswHash ); + + mRestApi->setToken( mResumeToken ); + mRestApi->setUserId( userId ); + mStorage->askForcommit(); + mDdpApi->setToken( mResumeToken ); + mDdpApi->unsetResponseBinding( request->getFrame() ); + + RestApiRequest meRequest + = RestApiRequest( new restMeRequest( meCallBackSuccess ) ); + + mRestApi->sendRequest( meRequest ); } } }; @@ -842,7 +873,7 @@ void RocketChatServerData::loginWithOpenIDToken( const QString &pToken, const QS self->mStorage->setUserData( self->mUsername, "" ); self->mStorage->setToken( self->mResumeToken, self->mTokenExpire ); self->mStorage->setUserId( self->mUserId ); - self->mStorage->commit(); + self->mStorage->askForcommit(); self->onResume(); self->onDDPAuthenticated(); } @@ -1687,7 +1718,7 @@ void RocketChatServerData::getCustomEmojis() Q_ASSERT( result ); } - mStorage->commit(); + mStorage->askForcommit(); } if ( !mCustomEmojisReady ) { diff --git a/rocketchatserver.h b/rocketchatserver.h index 92fa22c2ac3e28595f8a52ff744be2eac119d6b9..e9b210db03978e328de6aa4c9243f38c11b06038 100755 --- a/rocketchatserver.h +++ b/rocketchatserver.h @@ -221,7 +221,7 @@ class RocketChatServerData : public MessageListener void getCustomEmojis(); RestApi *getRestApi() const; ChannelRepository *getChannels() const; - RocketChatChannelService *mChannelService; + RocketChatChannelService *mChannelService = nullptr; void handleChannelMessage( const QJsonObject &pMessage ); uint diffToLastDDPPing(); void sendUnsentMessages( void ); @@ -244,6 +244,8 @@ class RocketChatServerData : public MessageListener void offlineLogin(); + void wipeDbAndReconnect(); + protected: RocketChatServerData(); @@ -278,11 +280,11 @@ class RocketChatServerData : public MessageListener QMap<QString, FileUploader *> mFileUploads; QString mCurrentChannel; QMutex mUnsentMutex; - UserModel *userModel; - LoginMethodsModel *loginMethodsModel; - ChannelModel *channelsModel; - ChannelModel *directModel; - ChannelModel *groupsModel; + UserModel *userModel = nullptr; + LoginMethodsModel *loginMethodsModel = nullptr; + ChannelModel *channelsModel = nullptr; + ChannelModel *directModel = nullptr; + ChannelModel *groupsModel = nullptr; std::function<void ( QMultiMap<QString, QSharedPointer<RocketChatMessage>> *messages )> historyLoaded; QString mPendingSwitchRoomRequest; QString mPendingSwitchRoomRequestType; diff --git a/segfaulthandler.cpp b/segfaulthandler.cpp index 8cd4f887f71a6785eda44374e2a08011d7d6b8e8..417ae93daaf94903b710e51920a0ad1653a0e4a0 100755 --- a/segfaulthandler.cpp +++ b/segfaulthandler.cpp @@ -70,7 +70,7 @@ void SegfaultHandler::segfaultHandlerMethod( int pSigno ) PersistanceLayer *storage = PersistanceLayer::instance(); storage->transaction(); storage->setSetting( "ERROR", errorString ); - storage->commit(); + storage->askForcommit(); #if defined(Q_OS_ANDROID) || defined(Q_OS_MACOS) || defined(Q_OS_LINUX) ||defined(Q_OS_IOS) qDebug() << "currThread:" << QThread::currentThreadId(); diff --git a/services/messageservice.cpp b/services/messageservice.cpp index 6d808d46be473896d0e05f72f5d37eafdde00ba6..f39a15e5e0e02f6e26182db2ae75fe73755bf22c 100644 --- a/services/messageservice.cpp +++ b/services/messageservice.cpp @@ -103,7 +103,7 @@ void MessageService::persistMessages( const MessageList &pMessage ) } }; - mPersistanceLayer->commit(); + mPersistanceLayer->askForcommit(); } QSharedPointer<RocketChatMessage> MessageService::parseMessage( const QJsonObject &pMessageData, diff --git a/services/rocketchatchannelservice.cpp b/services/rocketchatchannelservice.cpp index 923bd58120f3589f41186cfbe87675a652ba2d15..159575f0f5576b43ffa9e73f4e52bcfed31d9026 100755 --- a/services/rocketchatchannelservice.cpp +++ b/services/rocketchatchannelservice.cpp @@ -188,7 +188,7 @@ QVector<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processCha } } - mStorage->commit(); + mStorage->askForcommit(); return vec; @@ -472,7 +472,7 @@ void RocketChatChannelService::deleteChannel( const QString &pId ) mChannels->remove( pId ); mStorage->transaction(); mStorage->deleteChannel( pId ); - mStorage->commit(); + mStorage->askForcommit(); } }