From kde-commits Sat Jan 31 21:15:51 2015 From: =?utf-8?q?Christian_D=C3=A1vid?= Date: Sat, 31 Jan 2015 21:15:51 +0000 To: kde-commits Subject: [kmymoney] kmymoney/mymoney/storage: Corrected calculation of the next MyMoneyObject ids in SQL back Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=142273896323867 Git commit b36a26f9a2c2e683537e3e678a54caadc61a7171 by Christian D=C3=A1vid. Committed on 31/01/2015 at 20:43. Pushed by christiand into branch 'master'. Corrected calculation of the next MyMoneyObject ids in SQL backend The next MyMoneyObjects' ids were stored in the table kmmFileInfo. But this data got corrupted in the past several times. Now the highest id is calculated - so corruptions should not be possible anymore. The calculation process is lazy and is only executed when needed as it is quite expensive (uses regex on some RDBMSs). Unfortunatly the SQL backend triggers the calculation all the time at the moment - way more often than needed. Some writeFileInfo() and readFileInfo() calls must be removed to fix that (future work). Any calls to writeFileInfo() and readFileInfo() are removed - these methods cannot be called before the upgrade process is finished! Also the higest id numbers are not set during the upgrade process. BUG: 339103 FIXED-IN: 4.8 M +20 -20 kmymoney/mymoney/storage/mymoneydatabasemgr.cpp M +108 -234 kmymoney/mymoney/storage/mymoneystoragesql.cpp M +10 -6 kmymoney/mymoney/storage/mymoneystoragesql.h http://commits.kde.org/kmymoney/b36a26f9a2c2e683537e3e678a54caadc61a7171 diff --git a/kmymoney/mymoney/storage/mymoneydatabasemgr.cpp b/kmymoney/mym= oney/storage/mymoneydatabasemgr.cpp index e8d0259..391b138 100644 --- a/kmymoney/mymoney/storage/mymoneydatabasemgr.cpp +++ b/kmymoney/mymoney/storage/mymoneydatabasemgr.cpp @@ -2105,59 +2105,59 @@ void MyMoneyDatabaseMgr::loadOnlineJobs(const QMap<= QString, onlineJob >& online Q_UNUSED(onlineJobs); } = -unsigned long MyMoneyDatabaseMgr::accountId(void) const +unsigned long MyMoneyDatabaseMgr::accountId() const { - return m_sql->getNextAccountId(); + return m_sql->getNextAccountId()-1; } = -unsigned long MyMoneyDatabaseMgr::transactionId(void) const +unsigned long MyMoneyDatabaseMgr::transactionId() const { - return m_sql->getNextTransactionId(); + return m_sql->getNextTransactionId()-1; } = -unsigned long MyMoneyDatabaseMgr::payeeId(void) const +unsigned long MyMoneyDatabaseMgr::payeeId() const { - return m_sql->getNextPayeeId(); + return m_sql->getNextPayeeId()-1; } = -unsigned long MyMoneyDatabaseMgr::tagId(void) const +unsigned long MyMoneyDatabaseMgr::tagId() const { - return m_sql->getNextTagId(); + return m_sql->getNextTagId()-1; } = -unsigned long MyMoneyDatabaseMgr::institutionId(void) const +unsigned long MyMoneyDatabaseMgr::institutionId() const { - return m_sql->getNextInstitutionId(); + return m_sql->getNextInstitutionId()-1; } = -unsigned long MyMoneyDatabaseMgr::scheduleId(void) const +unsigned long MyMoneyDatabaseMgr::scheduleId() const { - return m_sql->getNextScheduleId(); + return m_sql->getNextScheduleId()-1; } = -unsigned long MyMoneyDatabaseMgr::securityId(void) const +unsigned long MyMoneyDatabaseMgr::securityId() const { - return m_sql->getNextSecurityId(); + return m_sql->getNextSecurityId()-1; } = -unsigned long MyMoneyDatabaseMgr::reportId(void) const +unsigned long MyMoneyDatabaseMgr::reportId() const { - return m_sql->getNextReportId(); + return m_sql->getNextReportId()-1; } = -unsigned long MyMoneyDatabaseMgr::budgetId(void) const +unsigned long MyMoneyDatabaseMgr::budgetId() const { - return m_sql->getNextBudgetId(); + return m_sql->getNextBudgetId()-1; } = long unsigned int MyMoneyDatabaseMgr::onlineJobId() const { - return m_sql->getNextOnlineJobId(); + return m_sql->getNextOnlineJobId()-1; } = long unsigned int MyMoneyDatabaseMgr::payeeIdentifierId() const { - return m_sql->getNextPayeeIdentifierId(); + return m_sql->getNextPayeeIdentifierId()-1; } = void MyMoneyDatabaseMgr::loadAccountId(const unsigned long id) diff --git a/kmymoney/mymoney/storage/mymoneystoragesql.cpp b/kmymoney/mymo= ney/storage/mymoneystoragesql.cpp index 572386b..8e59051 100644 --- a/kmymoney/mymoney/storage/mymoneystoragesql.cpp +++ b/kmymoney/mymoney/storage/mymoneystoragesql.cpp @@ -106,7 +106,18 @@ MyMoneyDbTransaction::~MyMoneyDbTransaction() = //************************ Constructor/Destructor ************************= ***** MyMoneyStorageSql::MyMoneyStorageSql(IMyMoneySerialize *storage, const KUr= l& url) - : QSqlDatabase(url.queryItem("driver")) + : QSqlDatabase(url.queryItem("driver")), + m_hiIdInstitutions(0), + m_hiIdPayees(0), + m_hiIdTags(0), + m_hiIdAccounts(0), + m_hiIdTransactions(0), + m_hiIdSchedules(0), + m_hiIdSecurities(0), + m_hiIdReports(0), + m_hiIdBudgets(0), + m_hiIdOnlineJobs(0), + m_hiIdPayeeIdentifier(0) { DBG("*** Entering MyMoneyStorageSql::MyMoneyStorageSql"); m_storage =3D storage; @@ -120,8 +131,6 @@ MyMoneyStorageSql::MyMoneyStorageSql(IMyMoneySerialize = *storage, const KUrl& url m_loadAll =3D false; m_override =3D false; m_preferred.setReportAllSplits(false); - - m_hiIdOnlineJobs =3D 0; } = int MyMoneyStorageSql::open(const KUrl& url, int openMode, bool clear) @@ -510,21 +519,6 @@ int MyMoneyStorageSql::upgradeToV1() } } m_transactionCountMap.clear(); - // there were considerable problems with record counts in V0, so rebuild= them - readFileInfo(); - m_institutions =3D getRecCount("kmmInstitutions"); - m_accounts =3D getRecCount("kmmAccounts"); - m_payees =3D getRecCount("kmmPayees"); - m_transactions =3D getRecCount("kmmTransactions WHERE txType =3D 'N'"); - m_splits =3D getRecCount("kmmSplits"); - m_securities =3D getRecCount("kmmSecurities"); - m_prices =3D getRecCount("kmmPrices"); - m_currencies =3D getRecCount("kmmCurrencies"); - m_schedules =3D getRecCount("kmmSchedules"); - m_reports =3D getRecCount("kmmReportConfig"); - m_kvps =3D getRecCount("kmmKeyValuePairs"); - m_budgets =3D getRecCount("kmmBudgetConfig"); - writeFileInfo(); return (0); } = @@ -609,9 +603,7 @@ int MyMoneyStorageSql::upgradeToV6() } } } - // kmmReportConfig - add a unique id as primary key - // read and write reports to get ids inserted - readFileInfo(); + // the alterTable function really doesn't work too well // with adding a new column which is also to be primary key // so add the column first @@ -632,15 +624,14 @@ int MyMoneyStorageSql::upgradeToV6() // add unique id to reports table if (!alterTable(m_db.m_tables["kmmReportConfig"], m_dbVersion)) return(1); - unsigned long long hiReportId =3D 0; + QMap::const_iterator it_r; for (it_r =3D reportList.constBegin(); it_r !=3D reportList.constEnd(); = ++it_r) { MyMoneyReport r =3D *it_r; - hiReportId =3D calcHighId(hiReportId, r.id()); q.prepare(m_db.m_tables["kmmReportConfig"].insertString()); writeReport(*it_r, q); } - m_hiIdReports =3D hiReportId; + m_storage->loadReportId(m_hiIdReports); endCommitUnit(Q_FUNC_INFO); return 0; @@ -670,9 +661,6 @@ int MyMoneyStorageSql::upgradeToV8() if (!alterTable(m_db.m_tables["kmmFileInfo"], m_dbVersion)) return (1); = - m_hiIdOnlineJobs =3D getRecCount("kmmOnlineJobs"); - m_hiIdPayeeIdentifier =3D getRecCount("kmmPayeeIdentifier"); - return 0; } = @@ -867,6 +855,7 @@ bool MyMoneyStorageSql::writeFile(void) =3D m_securities =3D m_prices =3D m_curren= cies =3D m_schedules =3D m_reports =3D m_kvps =3D m_budgets =3D 0; m_hiIdInstitutions =3D m_hiIdPayees =3D m_hiIdTags =3D m_hiIdAccounts = =3D m_hiIdTransactions =3D m_hiIdSchedules =3D m_hiIdSecuriti= es =3D m_hiIdReports =3D m_hiIdBudgets =3D 0; + m_onlineJobs =3D m_payeeIdentifier =3D 0; m_displayStatus =3D true; try { MyMoneyDbTransaction t(*this, Q_FUNC_INFO); @@ -1071,8 +1060,6 @@ void MyMoneyStorageSql::writeInstitutionList(const QL= ist& iL QVariantList telephoneList; QList > kvpPairsList; = - unsigned long hiId =3D m_hiIdInstitutions; - foreach (const MyMoneyInstitution& i, iList) { idList << i.id(); nameList << i.name(); @@ -1083,7 +1070,6 @@ void MyMoneyStorageSql::writeInstitutionList(const QL= ist& iL addressZipcodeList << i.postcode(); telephoneList << i.telephone(); kvpPairsList << i.pairs(); - hiId =3D calcHighId(hiId, i.id()); } = q.bindValue(":id", idList); @@ -1095,9 +1081,11 @@ void MyMoneyStorageSql::writeInstitutionList(const Q= List& iL q.bindValue(":addressZipcode", addressZipcodeList); q.bindValue(":telephone", telephoneList); = - if (!q.execBatch()) throw MYMONEYEXCEPTION(buildError(q, Q_FUNC_INFO, QS= tring("writing Institution"))); + if (!q.execBatch()) + throw MYMONEYEXCEPTION(buildError(q, Q_FUNC_INFO, QString("writing Ins= titution"))); writeKeyValuePairs("OFXSETTINGS", idList, kvpPairsList); - m_hiIdInstitutions =3D std::max(m_hiIdInstitutions, hiId); + // Set m_hiIdInstitutions to 0 to force recalculation the next time it i= s requested + m_hiIdInstitutions =3D 0; } = // **** Payees **** @@ -1330,11 +1318,18 @@ void MyMoneyStorageSql::writePayee(const MyMoneyPay= ee& p, QSqlQuery& q, bool isU QString matchKeys; MyMoneyPayee::payeeMatchType type =3D p.matchData(ignoreCase, matchKeys); q.bindValue(":matchData", static_cast(type)); - if (ignoreCase) q.bindValue(":matchIgnoreCase", "Y"); - else q.bindValue(":matchIgnoreCase", "N"); + + if (ignoreCase) + q.bindValue(":matchIgnoreCase", "Y"); + else + q.bindValue(":matchIgnoreCase", "N"); + q.bindValue(":matchKeys", matchKeys); - if (!q.exec()) throw MYMONEYEXCEPTION(buildError(q, Q_FUNC_INFO, QString= ("writing Payee"))); // krazy:exclude=3Dcrashy - if (!isUserInfo) m_hiIdPayees =3D calcHighId(m_hiIdPayees, p.id()); + if (!q.exec()) + throw MYMONEYEXCEPTION(buildError(q, Q_FUNC_INFO, QString("writing Pay= ee"))); // krazy:exclude=3Dcrashy + + if (!isUserInfo) + m_hiIdPayees =3D 0; } = // **** Tags **** @@ -1419,7 +1414,7 @@ void MyMoneyStorageSql::writeTag(const MyMoneyTag& ta= , QSqlQuery& q) else q.bindValue(":closed", "N"); q.bindValue(":notes", ta.notes()); if (!q.exec()) throw MYMONEYEXCEPTION(buildError(q, Q_FUNC_INFO, QString= ("writing Tag"))); // krazy:exclude=3Dcrashy - m_hiIdTags =3D calcHighId(m_hiIdTags, ta.id()); + m_hiIdTags =3D 0; } = // **** Accounts **** @@ -1607,8 +1602,6 @@ void MyMoneyStorageSql::writeAccountList(const QList<= MyMoneyAccount>& accList, Q QList > pairs; QList > onlineBankingPairs; = - unsigned long hiId =3D m_hiIdAccounts; - foreach (const MyMoneyAccount& a, accList) { idList << a.id(); institutionIdList << a.institutionId(); @@ -1648,8 +1641,6 @@ void MyMoneyStorageSql::writeAccountList(const QList<= MyMoneyAccount>& accList, Q } transactionCountList << quint64(m_transactionCountMap[a.id()]); = - hiId =3D calcHighId(hiId, a.id()); - //MMAccount inherits from KVPContainer AND has a KVPContainer member //so handle both pairs << a.pairs(); @@ -1673,12 +1664,13 @@ void MyMoneyStorageSql::writeAccountList(const QLis= t& accList, Q q.bindValue(":balanceFormatted", balanceFormattedList); q.bindValue(":transactionCount", transactionCountList); = - if (!q.execBatch()) throw MYMONEYEXCEPTION(buildError(q, Q_FUNC_INFO, QS= tring("writing Account"))); + if (!q.execBatch()) + throw MYMONEYEXCEPTION(buildError(q, Q_FUNC_INFO, QString("writing Acc= ount"))); = //Add in Key-Value Pairs for accounts. writeKeyValuePairs("ACCOUNT", idList, pairs); writeKeyValuePairs("ONLINEBANKING", idList, onlineBankingPairs); - m_hiIdAccounts =3D std::max(m_hiIdAccounts, hiId); + m_hiIdAccounts =3D 0; } = // **** Transactions and Splits **** @@ -1834,7 +1826,7 @@ void MyMoneyStorageSql::writeTransaction(const QStrin= g& txId, const MyMoneyTrans QList > pairs; pairs << tx.pairs(); writeKeyValuePairs("TRANSACTION", idList, pairs); - m_hiIdTransactions =3D calcHighId(m_hiIdTransactions, tx.id()); + m_hiIdTransactions =3D 0; } = void MyMoneyStorageSql::writeSplits(const QString& txId, const QString& ty= pe, const QList& splitList) @@ -2179,7 +2171,6 @@ void MyMoneyStorageSql::writeSchedule(const MyMoneySc= hedule& sch, QSqlQuery& q, //Add in Key-Value Pairs for transactions. //deleteKeyValuePairs("SCHEDULE", sch.id()); //writeKeyValuePairs("SCHEDULE", sch.id(), sch.pairs()); - m_hiIdSchedules =3D calcHighId(m_hiIdSchedules, sch.id()); } = // **** Securities **** @@ -2286,7 +2277,7 @@ void MyMoneyStorageSql::writeSecurity(const MyMoneySe= curity& security, QSqlQuery QList > pairs; pairs << security.pairs(); writeKeyValuePairs("SECURITY", idList, pairs); - m_hiIdSecurities =3D calcHighId(m_hiIdSecurities, security.id()); + m_hiIdSecurities =3D 0; } = // **** Prices **** @@ -2955,17 +2946,19 @@ void MyMoneyStorageSql::writeFileInfo() //startCommitUnit(Q_FUNC_INFO); //} = - q.bindValue(":hiInstitutionId", (unsigned long long) m_hiIdInstitutions); - q.bindValue(":hiPayeeId", (unsigned long long) m_hiIdPayees); - q.bindValue(":hiTagId", (unsigned long long) m_hiIdTags); - q.bindValue(":hiAccountId", (unsigned long long) m_hiIdAccounts); - q.bindValue(":hiTransactionId", (unsigned long long) m_hiIdTransactions); - q.bindValue(":hiScheduleId", (unsigned long long) m_hiIdSchedules); - q.bindValue(":hiSecurityId", (unsigned long long) m_hiIdSecurities); - q.bindValue(":hiReportId", (unsigned long long) m_hiIdReports); - q.bindValue(":hiBudgetId", (unsigned long long) m_hiIdBudgets); - q.bindValue(":hiOnlineJobId", (unsigned long long) m_hiIdOnlineJobs); - q.bindValue(":hiPayeeIdentifierId", (unsigned long long) m_hiIdPayeeIde= ntifier); + //! @todo The following bindings are for backwards compatibility only + //! remove backwards compatibility in a later version + q.bindValue(":hiInstitutionId", QVariant::fromValue(getNextInstitutionId= ())); + q.bindValue(":hiPayeeId", QVariant::fromValue(getNextPayeeId())); + q.bindValue(":hiTagId", QVariant::fromValue(getNextTagId())); + q.bindValue(":hiAccountId", QVariant::fromValue(getNextAccountId())); + q.bindValue(":hiTransactionId", QVariant::fromValue(getNextTransactionId= ())); + q.bindValue(":hiScheduleId", QVariant::fromValue(getNextScheduleId())); + q.bindValue(":hiSecurityId", QVariant::fromValue(getNextSecurityId())); + q.bindValue(":hiReportId", QVariant::fromValue(getNextReportId())); + q.bindValue(":hiBudgetId", QVariant::fromValue(getNextBudgetId())); + q.bindValue(":hiOnlineJobId", QVariant::fromValue(getNextOnlineJobId())); + q.bindValue(":hiPayeeIdentifierId", QVariant::fromValue(getNextPayeeIden= tifierId())); = q.bindValue(":encryptData", m_encryptData); q.bindValue(":updateInProgress", "N"); @@ -3066,8 +3059,7 @@ void MyMoneyStorageSql::readFileInfo(void) = q.prepare( "SELECT " - " created, lastModified, hiInstitutionId, hiPayeeId, hiTagId, hiAccou= ntId, hiTransactionId," - " hiScheduleId, hiSecurityId, hiReportId, hiBudgetId, hiOnlineJobId, = hiPayeeIdentifierId, " + " created, lastModified, " " encryptData, logonUser, logonAt, " " (SELECT count(*) FROM kmmInstitutions) AS institutions, " " (SELECT count(*) from kmmAccounts) AS accounts, " @@ -3097,18 +3089,6 @@ void MyMoneyStorageSql::readFileInfo(void) m_storage->setCreationDate(GETDATE(rec.indexOf("created"))); m_storage->setLastModificationDate(GETDATE(rec.indexOf("lastModified"))); = - m_hiIdInstitutions =3D (unsigned long) GETULL(rec.indexOf("hiInstitution= Id")); - m_hiIdPayees =3D (unsigned long) GETULL(rec.indexOf("hiPayeeId")); - m_hiIdTags =3D (unsigned long) GETULL(rec.indexOf("hiTagId")); - m_hiIdAccounts =3D (unsigned long) GETULL(rec.indexOf("hiAccountId")); - m_hiIdTransactions =3D (unsigned long) GETULL(rec.indexOf("hiTransaction= Id")); - m_hiIdSchedules =3D (unsigned long) GETULL(rec.indexOf("hiScheduleId")); - m_hiIdSecurities =3D (unsigned long) GETULL(rec.indexOf("hiSecurityId")); - m_hiIdReports =3D (unsigned long) GETULL(rec.indexOf("hiReportId")); - m_hiIdBudgets =3D (unsigned long) GETULL(rec.indexOf("hiBudgetId")); - m_hiIdOnlineJobs =3D (unsigned long) GETULL(rec.indexOf("hiOnlineJobId")= ); - m_hiIdPayeeIdentifier =3D (unsigned long) GETULL(rec.indexOf("hiPayeeIde= ntifierId")); - m_institutions =3D (unsigned long) GETULL(rec.indexOf("institutions")); m_accounts =3D (unsigned long) GETULL(rec.indexOf("accounts")); m_payees =3D (unsigned long) GETULL(rec.indexOf("payees")); @@ -3243,8 +3223,7 @@ void MyMoneyStorageSql::readPayees(const QList& pid) DBG("*** Entering MyMoneyStorageSql::readPayees(list)"); try { m_storage->loadPayees(fetchPayees(pid)); - readFileInfo(); - m_storage->loadPayeeId(m_hiIdPayees); + m_storage->loadPayeeId(getNextPayeeId()); } catch (const MyMoneyException &) { } // if (pid.isEmpty()) m_payeeListRead =3D true; @@ -3737,7 +3716,7 @@ void MyMoneyStorageSql::readTransactions(const QStrin= g& tidList, const QString& { try { m_storage->loadTransactions(fetchTransactions(tidList, dateClause)); - m_storage->loadTransactionId(m_hiIdTransactions); + m_storage->loadTransactionId(getNextTransactionId()); } catch (const MyMoneyException &) { throw; } @@ -3747,7 +3726,7 @@ void MyMoneyStorageSql::readTransactions(const MyMone= yTransactionFilter& filter) { try { m_storage->loadTransactions(fetchTransactions(filter)); - m_storage->loadTransactionId(m_hiIdTransactions); + m_storage->loadTransactionId(getNextTransactionId()); } catch (const MyMoneyException &) { throw; } @@ -4151,8 +4130,7 @@ void MyMoneyStorageSql::readSchedules(void) = try { m_storage->loadSchedules(fetchSchedules()); - readFileInfo(); - m_storage->loadScheduleId(m_hiIdSchedules); + m_storage->loadScheduleId(getNextScheduleId()); } catch (const MyMoneyException &) { throw; } @@ -4304,8 +4282,7 @@ void MyMoneyStorageSql::readSecurities(void) { try { m_storage->loadSecurities(fetchSecurities()); - readFileInfo(); - m_storage->loadSecurityId(m_hiIdSecurities); + m_storage->loadSecurityId(getNextSecurityId()); } catch (const MyMoneyException &) { throw; } @@ -4578,8 +4555,7 @@ void MyMoneyStorageSql::readReports(void) { try { m_storage->loadReports(fetchReports()); - readFileInfo(); - m_storage->loadReportId(m_hiIdReports); + m_storage->loadReportId(getNextReportId()); } catch (const MyMoneyException &) { throw; } @@ -4711,245 +4687,143 @@ const QHash My= MoneyStorageSql::readKeyValuePa return (retval); } = +template +long unsigned int MyMoneyStorageSql::getNextId(const QString& table, const= QString& id, const int prefixLength) const +{ + Q_CHECK_PTR(cache); + if (this->*cache =3D=3D 0) { + MyMoneyStorageSql* nonConstThis =3D const_cast(thi= s); + nonConstThis->*cache =3D 1 + nonConstThis->highestNumberFromIdString(t= able, id, prefixLength); + } + Q_ASSERT(this->*cache > 0); // everything else is never a valid id + return this->*cache; +} + long unsigned MyMoneyStorageSql::getNextBudgetId() const { - const_cast (this)->readFileInfo(); - return m_hiIdBudgets; + return getNextId<&MyMoneyStorageSql::m_hiIdBudgets>(QLatin1String("kmmBu= dgetConfig"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextAccountId() const { - const_cast (this)->readFileInfo(); - return m_hiIdAccounts; + return getNextId<&MyMoneyStorageSql::m_hiIdAccounts>(QLatin1String("kmmA= ccounts"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextInstitutionId() const { - const_cast (this)->readFileInfo(); - return m_hiIdInstitutions; + return getNextId<&MyMoneyStorageSql::m_hiIdInstitutions>(QLatin1String("= kmmInstitutions"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextPayeeId() const { - const_cast (this)->readFileInfo(); - return m_hiIdPayees; + return getNextId<&MyMoneyStorageSql::m_hiIdPayees>(QLatin1String("kmmPay= ees"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextTagId() const { - const_cast (this)->readFileInfo(); - return m_hiIdTags; + return getNextId<&MyMoneyStorageSql::m_hiIdTags>(QLatin1String("kmmTags"= ), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextReportId() const { - const_cast (this)->readFileInfo(); - return m_hiIdReports; + return getNextId<&MyMoneyStorageSql::m_hiIdReports>(QLatin1String("kmmRe= portConfig"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextScheduleId() const { - const_cast (this)->readFileInfo(); - return m_hiIdSchedules; + return getNextId<&MyMoneyStorageSql::m_hiIdSchedules>(QLatin1String("kmm= Schedules"), QLatin1String("id"), 3); } = long unsigned MyMoneyStorageSql::getNextSecurityId() const { - const_cast (this)->readFileInfo(); - return m_hiIdSecurities; + return getNextId<&MyMoneyStorageSql::m_hiIdSecurities>(QLatin1String("km= mSecurities"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextTransactionId() const { - const_cast (this)->readFileInfo(); - return m_hiIdTransactions; + return getNextId<&MyMoneyStorageSql::m_hiIdTransactions>(QLatin1String("= kmmTransactions"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextOnlineJobId() const { - const_cast (this)->readFileInfo(); - return m_hiIdOnlineJobs; + return getNextId<&MyMoneyStorageSql::m_hiIdOnlineJobs>(QLatin1String("km= mOnlineJobs"), QLatin1String("id"), 1); } = long unsigned MyMoneyStorageSql::getNextPayeeIdentifierId() const { - const_cast (this)->readFileInfo(); - return m_hiIdPayeeIdentifier; + return getNextId<&MyMoneyStorageSql::m_hiIdPayeeIdentifier>(QLatin1Strin= g("kmmPayeeIdentifier"), QLatin1String("id"), 5); } = long unsigned MyMoneyStorageSql::incrementBudgetId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiBudgetId FROM kmmFileInfo " + m_driver->forUpdateStr= ing()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiBudgetId =3D %1").arg(return= Value)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdBudgets =3D returnValue; - return returnValue; + m_hiIdBudgets =3D getNextBudgetId() + 1; + return (m_hiIdBudgets-1); } = +/** + * @warning This method uses getNextAccountId() internaly. The database is= not informed which can cause issues + * when the database is accessed concurrently. Then maybe a single id is u= sed twice but the RDBMS will detect the + * issue and KMyMoney crashes. This issue can only occour when two instanc= es of KMyMoney access the same database. + * But in this unlikley case MyMoneyStorageSql will have a lot more issues= , I think. + */ long unsigned MyMoneyStorageSql::incrementAccountId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiAccountId FROM kmmFileInfo " + m_driver->forUpdateSt= ring()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiAccountId =3D %1").arg(retur= nValue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdAccounts =3D returnValue; - return returnValue; + m_hiIdAccounts =3D getNextAccountId() + 1; + return (m_hiIdAccounts-1); } = long unsigned MyMoneyStorageSql::incrementInstitutionId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiInstitutionId FROM kmmFileInfo " + m_driver->forUpda= teString()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiInstitutionId =3D %1").arg(r= eturnValue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdInstitutions =3D returnValue; - return returnValue; + m_hiIdInstitutions =3D getNextInstitutionId() + 1; + return (m_hiIdInstitutions-1); } = long unsigned MyMoneyStorageSql::incrementPayeeId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiPayeeId FROM kmmFileInfo " + m_driver->forUpdateStri= ng()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiPayeeId =3D %1").arg(returnV= alue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdPayees =3D returnValue; - return returnValue; + m_hiIdPayees =3D getNextPayeeId() + 1; + return (m_hiIdPayees-1); } = long unsigned MyMoneyStorageSql::incrementTagId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiTagId FROM kmmFileInfo " + m_driver->forUpdateString= ()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiTagId =3D %1").arg(returnVal= ue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdTags =3D returnValue; - return returnValue; + m_hiIdTags =3D getNextTagId() + 1; + return (m_hiIdTags-1); } = long unsigned MyMoneyStorageSql::incrementReportId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiReportId FROM kmmFileInfo " + m_driver->forUpdateStr= ing()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiReportId =3D %1").arg(return= Value)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdReports =3D returnValue; - return returnValue; + m_hiIdReports =3D getNextReportId() + 1; + return (m_hiIdReports-1); } = long unsigned MyMoneyStorageSql::incrementScheduleId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiScheduleId FROM kmmFileInfo " + m_driver->forUpdateS= tring()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiScheduleId =3D %1").arg(retu= rnValue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdSchedules =3D returnValue; - return returnValue; + m_hiIdSchedules =3D getNextScheduleId() + 1; + return (m_hiIdSchedules-1); } = long unsigned MyMoneyStorageSql::incrementSecurityId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiSecurityId FROM kmmFileInfo " + m_driver->forUpdateS= tring()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiSecurityId =3D %1").arg(retu= rnValue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdSecurities =3D returnValue; - return returnValue; + m_hiIdSecurities =3D getNextSecurityId() + 1; + return (m_hiIdSecurities-1); } = long unsigned MyMoneyStorageSql::incrementTransactionId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiTransactionId FROM kmmFileInfo " + m_driver->forUpda= teString()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiTransactionId =3D %1").arg(r= eturnValue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdTransactions =3D returnValue; - return returnValue; + m_hiIdTransactions =3D getNextTransactionId() + 1; + return (m_hiIdTransactions-1); } = long unsigned int MyMoneyStorageSql::incrementOnlineJobId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiOnlineJobId FROM kmmFileInfo " + m_driver->forUpdate= String()); - q.exec(); // krazy:exclude=3Dcrashy - q.next(); - long unsigned returnValue =3D ((unsigned long) q.value(0).toULongLong())= + 1; - q.prepare(QString("UPDATE kmmFileInfo SET hiOnlineJobId =3D %1").arg(ret= urnValue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdOnlineJobs =3D returnValue; - return returnValue; + m_hiIdOnlineJobs =3D getNextOnlineJobId() + 1; + return (m_hiIdOnlineJobs-1); } = long unsigned int MyMoneyStorageSql::incrementPayeeIdentfierId() { - QSqlQuery q(*this); - - MyMoneyDbTransaction t(*this, Q_FUNC_INFO); - q.prepare("SELECT hiPayeeIdentifierId FROM kmmFileInfo " + m_driver->for= UpdateString()); - q.exec(); - q.next(); - long unsigned returnValue =3D (unsigned long) q.value(0).toULongLong(); - ++returnValue; - q.prepare(QString("UPDATE kmmFileInfo SET hiPayeeIdentifierId =3D %1").a= rg(returnValue)); - q.exec(); // krazy:exclude=3Dcrashy - m_hiIdPayeeIdentifier =3D returnValue; - return returnValue; + m_hiIdPayeeIdentifier =3D getNextPayeeIdentifierId() + 1; + return (m_hiIdPayeeIdentifier-1); } = void MyMoneyStorageSql::loadAccountId(const unsigned long& id) diff --git a/kmymoney/mymoney/storage/mymoneystoragesql.h b/kmymoney/mymone= y/storage/mymoneystoragesql.h index 96a37ce..6080868 100644 --- a/kmymoney/mymoney/storage/mymoneystoragesql.h +++ b/kmymoney/mymoney/storage/mymoneystoragesql.h @@ -172,10 +172,10 @@ public: bool writeFile(void); = /** - * MyMoneyStorageSql generalized error routine - * - * @return : error message to be displayed - * + * MyMoneyStorageSql generalized error routine + * + * @return : error message to be displayed + * */ const QString& lastError() const { return (m_error); @@ -185,7 +185,6 @@ public: * MyMoneyStorageSql get highest ID number from the database * * @return : highest ID number - * */ long unsigned highestNumberFromIdString(QString tableName, QString table= Field, int prefixLength); = @@ -195,6 +194,7 @@ public: * from the database is available in memory to enable it to be written. */ virtual void fillStorage(); + /** * The following functions correspond to the identically named (usually= ) functions * within the Storage Manager, and are called to update the database @@ -411,6 +411,9 @@ private: void readBudgets(void); /** @} */ = + template + long unsigned int getNextId(const QString& table, const QString& id, con= st int prefixLength) const; + void deleteTransaction(const QString& id); void deleteTagSplitsList(const QString& txId, const QList& splitIdL= ist); void deleteSchedule(const QString& id); @@ -507,7 +510,8 @@ private: long unsigned m_onlineJobs; long unsigned m_payeeIdentifier; = - // next id to use (for future archive) + // Cache for next id to use + // value 0 means data is not available and has to be loaded from the dat= abase long unsigned m_hiIdInstitutions; long unsigned m_hiIdPayees; long unsigned m_hiIdTags;