Bug 410994 - Losing transactions after 8000+ DB to KmyFile
Summary: Losing transactions after 8000+ DB to KmyFile
Status: RESOLVED FIXED
Alias: None
Product: kmymoney
Classification: Applications
Component: database (show other bugs)
Version: 4.8.3
Platform: Other Microsoft Windows
: NOR normal
Target Milestone: ---
Assignee: KMyMoney Devel Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-08-16 19:17 UTC by robsonsilva
Modified: 2019-12-13 10:15 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In: 4.8.5


Attachments
KMymoney SQLite Database with 15169 transactions (323.80 KB, application/x-7z-compressed)
2019-08-17 05:45 UTC, Ralf Habacker
Details
Sql lite db sample (531.74 KB, application/x-7z-compressed)
2019-08-19 13:07 UTC, robsonsilva
Details
Screenshot showing one of the accounts (73.79 KB, image/png)
2019-08-19 17:03 UTC, Thomas Baumgart
Details
Steps (947.83 KB, application/x-7z-compressed)
2019-08-19 19:12 UTC, robsonsilva
Details
UsingJustDB (49.12 KB, application/x-7z-compressed)
2019-08-20 21:54 UTC, robsonsilva
Details
GettingRidOfInvalidFirst (38.91 KB, application/x-7z-compressed)
2019-08-20 21:54 UTC, robsonsilva
Details

Note You need to log in before you can comment on or make changes to this bug.
Description robsonsilva 2019-08-16 19:17:40 UTC
SUMMARY
Losing transactions after 8000+

STEPS TO REPRODUCE
1. Given KMY with 9000 transactions in Mysql OR sql lite
2. Save as KMY data file format

OBSERVED RESULT
- Transactions are lost after 8000+

EXPECTED RESULT
- Transactions should not be lost

SOFTWARE/OS VERSIONS
Windows: Windows 10
Comment 1 Ralf Habacker 2019-08-17 05:45:47 UTC
Created attachment 122194 [details]
KMymoney SQLite Database with 15169 transactions

I could not reproduce this problem with the attached SQLite database containing 15169 transactions. After saving as *.kmy or as *.xml, all 15169 transactions were included.

The problem must have a cause outside KMyMoney e.g. faulty network connection or corrupt SQLite database.
Comment 2 robsonsilva 2019-08-19 13:06:23 UTC
SUMMARY
Hello, guys, I've run anonymizer over my sample data, could you test using it?
Losing transactions after 8000+

STEPS TO REPRODUCE
1. Given KMY with 9000 transactions in Mysql OR sql lite
2. Save as KMY data file format

OBSERVED RESULT
- Transactions are lost after 8000+

EXPECTED RESULT
- Transactions should not be lost

SOFTWARE/OS VERSIONS
Windows: Windows 10
Comment 3 robsonsilva 2019-08-19 13:07:05 UTC
Created attachment 122242 [details]
Sql lite db sample
Comment 4 Ralf Habacker 2019-08-19 13:51:28 UTC
(In reply to robsonsilva from comment #2)
> Hello, guys, I've run anonymizer over my sample data, could you test using
> it?
> Losing transactions after 8000+

The provided db sample contains 8491 transactions.
 sqlite3 ~/Downloads/test.anon.sqlite "select count(*) from kmmTransactions"
8491

After exporting to an xml file the xml file shows that 8486 transaction were exported. 

grep "<TRANSACTIONS" test.xml
 <TRANSACTIONS count="8486">

Are you pointing to this difference or to something else ?
Comment 5 robsonsilva 2019-08-19 14:13:15 UTC
For e.g On ledger screen:

If you check last transaction date (sqlite file) and then last transaction date after save as (kmy file) you will see these differences:

Account ID, before, after save as kmy:
A000331, 16-aug-2019, 08-jul-2019
A000329, 10-aug-2019, 06-jul-2019
A000344, 09-jul-2019, 25-jun-2019
Comment 6 Thomas Baumgart 2019-08-19 14:15:49 UTC
(In reply to Ralf Habacker from comment #4)

> Are you pointing to this difference or to something else ?

This difference is perfectly OK since the higher number also includes the scheduled transactions.

   select count(*) from kmmTransactions where txType = 'N'

shows exactly 8486 transactions and 

   select count(*) from kmmTransactions where txType = 'S'

shows the remaining 5.
Comment 7 robsonsilva 2019-08-19 14:28:40 UTC
After the 'save As' if you run a select to find transactions that just exists on kmmTransactions and not in kmmSplits, you will see that some kmmTransactions don't have related kmmSplits anymore.

select * from kmmTransactions where id not in (select distinct transactionId from kmmSplits) /*I wrote by mind sorry for mispelling*/


For e.g On ledger screen:

If you check last transaction date (sqlite file) and then last transaction date after save as (kmy file) you will see these differences:

Account ID, before, after save as kmy:
A000331, 16-aug-2019, 08-jul-2019
A000329, 10-aug-2019, 06-jul-2019
A000344, 09-jul-2019, 25-jun-2019
Comment 8 Thomas Baumgart 2019-08-19 17:03:02 UTC
Created attachment 122245 [details]
Screenshot showing one of the accounts

(In reply to robsonsilva from comment #7)

> For e.g On ledger screen:
> 
> If you check last transaction date (sqlite file) and then last transaction
> date after save as (kmy file) you will see these differences:
> 
> Account ID, before, after save as kmy:
> A000331, 16-aug-2019, 08-jul-2019
> A000329, 10-aug-2019, 06-jul-2019
> A000344, 09-jul-2019, 25-jun-2019

I just did that and I cannot confirm the dates you report for the sqlite file. I do see exactly the ones that you report for the kmy file. A000331 attached as an example.
Comment 9 robsonsilva 2019-08-19 19:11:22 UTC
(In reply to Thomas Baumgart from comment #8)
> Created attachment 122245 [details]
> Screenshot showing one of the accounts
> 
> (In reply to robsonsilva from comment #7)
> 
> > For e.g On ledger screen:
> > 
> > If you check last transaction date (sqlite file) and then last transaction
> > date after save as (kmy file) you will see these differences:
> > 
> > Account ID, before, after save as kmy:
> > A000331, 16-aug-2019, 08-jul-2019
> > A000329, 10-aug-2019, 06-jul-2019
> > A000344, 09-jul-2019, 25-jun-2019
> 
> I just did that and I cannot confirm the dates you report for the sqlite
> file. I do see exactly the ones that you report for the kmy file. A000331
> attached as an example.

The problem is sqlfile is already at a weird state,I guess.
I've attached the steps starting from anonymizer.xml to sqlite to kmy file now...

I've attached xml file and screenshots of steps.


1 - User open anonymizer.xml file
2 - User check reports, ledger
3 - User save as sqlite, close KMY and open again (now sqlite file)
4 - Orphan splits are found in sqlite (dbBrowser)
	select * from kmmTransactions where id not in (select distinct transactionId from kmmSplits)
5 - User cannot see latest transaction on reports, but
	he can see on ledger yet.. it seems kmmslipts are about to be lost (probably in some cache table?)
6 - User save as kmy file and Close KMY
7 - User Open kmy file and go to ledger
8 - Transactions missing
Comment 10 robsonsilva 2019-08-19 19:12:58 UTC
Created attachment 122247 [details]
Steps
Comment 11 robsonsilva 2019-08-19 20:20:25 UTC
about step 5(In reply to Thomas Baumgart from comment #8)
> Created attachment 122245 [details]
> Screenshot showing one of the accounts
> 
> (In reply to robsonsilva from comment #7)
> 
> > For e.g On ledger screen:
> > 
> > If you check last transaction date (sqlite file) and then last transaction
> > date after save as (kmy file) you will see these differences:
> > 
> > Account ID, before, after save as kmy:
> > A000331, 16-aug-2019, 08-jul-2019
> > A000329, 10-aug-2019, 06-jul-2019
> > A000344, 09-jul-2019, 25-jun-2019
> 
> I just did that and I cannot confirm the dates you report for the sqlite
> file. I do see exactly the ones that you report for the kmy file. A000331
> attached as an example.


The problem is sqlfile is already at a weird state,I guess.
I've attached the steps starting from anonymizer.xml to sqlite to kmy file now...

I've attached xml file and screenshots of steps.


1 - User open anonymizer.xml file
2 - User check reports, ledger
3 - User save as sqlite, close KMY and open again (now sqlite file)
4 - Orphan splits are found in sqlite (dbBrowser)
	select * from kmmTransactions where id not in (select distinct transactionId from kmmSplits)
5 - User cannot see latest transaction on reports, but
	NOTE: there is no but on step 3 I forget to close and reopen, so, database file wasn't fully reload)
6 - User save as kmy file and Close KMY
7 - User Open kmy file and go to ledger
8 - Transactions missing
Comment 12 Ralf Habacker 2019-08-19 20:32:54 UTC
So you are saying that your primary file is a kmy or xml file and after exporting to sqlite the sqlite database is broken ? 

I did the opposite and took the "sql lite db sample" sqlite database as primary source. I added some debug code to 
void MyMoneyStorageXML::writeTransaction(QDomElement& transaction, const MyMoneyTransaction& tx)
{
  if (tx.memo() == "T000000000000008308")
      qDebug() << tx.memo();
  tx.writeXML(*m_doc, transaction);
}

did set a breakpoint at the qDebug() output and exported the sqlite database to an xml file.
I saw that transaction 'T000000000000008308' has 2 splits while the next account related transaction 'T000000000000008311' did not have any splits although the loaded sql database showed that it should have. I used the following sql command to get the splits: 

select kmmSplits.splitId, kmmSplits.accountId, kmmSplits.postDate, kmmTransactions.id from kmmSplits, kmmTransactions where kmmSplits.transactionId = kmmTransactions.id

0|A000331|2019-07-08|T000000000000008308
1|A000291|2019-07-08|T000000000000008308
.. 
0|A000331|2019-07-10|T000000000000008311
1|A000284|2019-07-10|T000000000000008311

It looks to me that exporting to an kml or xml file from a sqlite database is also broken independently from an import into a sqlite database.
Comment 13 robsonsilva 2019-08-20 06:52:40 UTC
Yes, when I first had the problem I was just using database.
In ledger, transactions were there, then in reports transactions/other types as well, I didn't see last transactions.
Then I went to save as, and some transactions didn't go.
Comment 14 Ralf Habacker 2019-08-20 11:34:27 UTC
(In reply to Ralf Habacker from comment #12)
> 0|A000331|2019-07-08|T000000000000008308
> 1|A000291|2019-07-08|T000000000000008308
> .. 
> 0|A000331|2019-07-10|T000000000000008311
> 1|A000284|2019-07-10|T000000000000008311
> 
> It looks to me that exporting to an kml or xml file from a sqlite database
> is also broken independently from an import into a sqlite database.

The export fails because it expects to have a linear split order without any missing entries, but the splits returned from the query on kmmSplits do not include splits for transaction T000000000000008309 as shown below: 

0|A000331|2019-07-08|T000000000000008308
1|A000291|2019-07-08|T000000000000008308
0|A000344|2019-07-09|T000000000000008310
1|A000330|2019-07-09|T000000000000008310
0|A000331|2019-07-10|T000000000000008311
1|A000284|2019-07-10|T000000000000008311

Therefore the code iterates to the end of all splits (because it do not find the requested transaction number) and cannot process any further splits.

While this problem is solvable (skip any transaction whose transaction number is lower than the transaction number of the currently processed split and then notify the user that these transactions could not be exported) this does not change the basic problem that the sqlite database is inconsistent and we need to see where it happens.
Comment 15 robsonsilva 2019-08-20 13:06:38 UTC
(In reply to Ralf Habacker from comment #14)
I opened file anonymizer.anon.xml and I've found many nodes like that "<SPLITS/>" my guess is that some problem happened on transactions importer or saving transactions where SPLITS got null, and skipping is happening for kmyfile and xml file but not for db exporter.

Maybe this could be part of database integrity check on KMY?
Comment 16 Jack 2019-08-20 14:09:38 UTC
This seems like it is going around in circles.  I think it is appropriate to go back to the real core problem.  If you were using a sqlite database, and found you had transactions which were seen in the ledger, but not in reports, that is what needs to be diagnosed.  Exporting to other formats may fail to produce a complete, consistent file, but that is because there is already a problem with the data, not because of a problem with the process of exporting to a file, other than that it fails to notice the bad data and notify of the problem.

Using the sqlite database when you first noticed the problem, if you save again as a database, and reopen the newly saved sqlite file, does anything change, or does it show EXACTLY the same problem?
Comment 17 Ralf Habacker 2019-08-20 16:16:05 UTC
Git commit 804a08d78aa5d62815d9f3d68fa5c77dd5e16c4f by Ralf Habacker.
Committed on 20/08/2019 at 16:15.
Pushed by habacker into branch '4.8'.

Add consistency check for number of splits

M  +4    -0    kmymoney/mymoney/mymoneyfile.cpp

https://commits.kde.org/kmymoney/804a08d78aa5d62815d9f3d68fa5c77dd5e16c4f
Comment 18 Ralf Habacker 2019-08-20 17:45:28 UTC
Git commit 297a776c68c64665c4a8a1dc939002e2adf72694 by Ralf Habacker.
Committed on 20/08/2019 at 17:28.
Pushed by habacker into branch '4.8'.

Reduce the number of invalid split counts to less than one

Thomas Baumgart pointed out that there can be transactions with
only one split.

M  +2    -2    kmymoney/mymoney/mymoneyfile.cpp

https://commits.kde.org/kmymoney/297a776c68c64665c4a8a1dc939002e2adf72694
Comment 19 robsonsilva 2019-08-20 21:52:56 UTC
(In reply to Jack from comment #16)
> This seems like it is going around in circles.  I think it is appropriate to
> go back to the real core problem.  If you were using a sqlite database, and
> found you had transactions which were seen in the ledger, but not in
> reports, that is what needs to be diagnosed.  Exporting to other formats may
> fail to produce a complete, consistent file, but that is because there is
> already a problem with the data, not because of a problem with the process
> of exporting to a file, other than that it fails to notice the bad data and
> notify of the problem.
> 
> Using the sqlite database when you first noticed the problem, if you save
> again as a database, and reopen the newly saved sqlite file, does anything
> change, or does it show EXACTLY the same problem?

Yes you are right, I got a backup with the first occurrence, there I found 2 transactions without splits.
When I spoted the problem in KMY I was generating reports, so from there I generated KMY/XML data type files, these types can skip missing transactions/splits. As a consequence I could see ledger and reports working. However, when I tried to go back to sql the mess were there and became worse.

I added 2 attachments:
- UsingJustDB: Where I reproduced the problem described above.
- GettingRidOfInvalidFirst: Where first I deleted transactions without splits and verify KMY working fine for same scenario. :)

* consistency check for number of splits was a great idea ! 

* tks guys.
Comment 20 robsonsilva 2019-08-20 21:54:29 UTC
Created attachment 122266 [details]
UsingJustDB
Comment 21 robsonsilva 2019-08-20 21:54:46 UTC
Created attachment 122267 [details]
GettingRidOfInvalidFirst
Comment 22 robsonsilva 2019-08-21 17:54:15 UTC
Add consistency check for number of splits, will guarantee database integrity for this scenario.
Comment 23 Ralf Habacker 2019-09-28 19:29:28 UTC
Git commit fa7a2616c7903f6f7fddd0700e1d390945b1a521 by Ralf Habacker.
Committed on 26/09/2019 at 18:54.
Pushed by habacker into branch '4.8'.

Fix sql statement case

M  +15   -15   kmymoney/mymoney/storage/mymoneystoragesql.cpp

https://commits.kde.org/kmymoney/fa7a2616c7903f6f7fddd0700e1d390945b1a521
Comment 24 Ralf Habacker 2019-09-28 19:29:28 UTC
Git commit 781c18c3356d043da25039d50b41a658de95cac2 by Ralf Habacker.
Committed on 26/09/2019 at 18:54.
Pushed by habacker into branch '4.8'.

Fix fetchTransactions for sql databases

Base implementation by Thomas Baumgart, adapted to 4.8 branch
by Ralf Habacker.

Implementation verified with mymoneydatabasemgrtest.
FIXED-IN:4.8.5

M  +15   -0    kmymoney/mymoney/storage/mymoneydbdef.h
M  +101  -77   kmymoney/mymoney/storage/mymoneystoragesql.cpp

https://commits.kde.org/kmymoney/781c18c3356d043da25039d50b41a658de95cac2
Comment 25 Ralf Habacker 2019-09-29 18:42:05 UTC
Git commit f77639cd24b0689959e88a0f3dc127f5f09aba9e by Ralf Habacker.
Committed on 29/09/2019 at 12:39.
Pushed by habacker into branch '5.0'.

Fix fetchTransactions for sql databases

Base implementation by Thomas Baumgart from loval feature branch,
adapted to 5.x branch by Ralf Habacker.

Implementation verified with mymoneydatabasemgrtest.
FIXED-IN:5.0.7

M  +15   -0    kmymoney/plugins/sql/mymoneydbdef.h
M  +101  -78   kmymoney/plugins/sql/mymoneystoragesql.cpp

https://commits.kde.org/kmymoney/f77639cd24b0689959e88a0f3dc127f5f09aba9e
Comment 26 Ralf Habacker 2019-09-29 18:42:05 UTC
Git commit 1216c3c5866dd9bf639216f96726c90ff0931cb5 by Ralf Habacker.
Committed on 29/09/2019 at 12:39.
Pushed by habacker into branch '5.0'.

Fix sql statement case

Conflicts:
	kmymoney/mymoney/sql/mymoneystoragesql.cpp

M  +15   -15   kmymoney/plugins/sql/mymoneystoragesql.cpp

https://commits.kde.org/kmymoney/1216c3c5866dd9bf639216f96726c90ff0931cb5
Comment 27 Ralf Habacker 2019-10-01 17:36:07 UTC
(In reply to Ralf Habacker from comment #25)
> Git commit f77639cd24b0689959e88a0f3dc127f5f09aba9e by Ralf Habacker.
> Committed on 29/09/2019 at 12:39.
> Pushed by habacker into branch '5.0'.
> 
> Fix fetchTransactions for sql databases
> 
> Base implementation by Thomas Baumgart from loval feature branch,
> adapted to 5.x branch by Ralf Habacker.
> 
This patch was reversed due to compilation errors. Since Thomas is working on a complete replacement of the SQL implementation and this patch corresponds to an earlier version of a part of it, it will probably be fixed with version 5.1.0 at the earliest.
Comment 28 Ralf Habacker 2019-12-13 10:15:23 UTC
commit has been reverted from 5.0 branch