Update on status, quoting below from different messages.

On 2021.01.05 08:22, Thomas Baumgart wrote:
On Dienstag, 5. Januar 2021 01:58:33 CET Jack wrote:
....
This happens in qMakePreparedStmtId(). Since the stmtId in the failing case is empty, it must have been cleared or never set. The member variable is set when a call to QPSQLResult::prepare() returns true. If it returns false, the stmtId is cleared.
So this does seem to be the case. More below, but yes, the prepare is failing, but I still can't figure out why, despite lots of stepping with gdb.

....
So it seems to me, that exec is called in the wrong spot. To track this down (After all F1 identifies 241 iterations) I would derive a new result object from QPSQLResult or QSqlResult and override prepare() and exec() to keep track of the calls and their return code. Then use this object to add specific debugging code/output.
That many iterations was only due to multiple attempts within the same session. I had been misreadeing your suggestion, as far as I can tell, the basic code paths are traversed several times successfully before something going wrong, so perhaps adding debugging code with some sort of conditional execution would be better - but I'm still at a bit of a loss to see where to add stuff.

I think I have done something similar for MySQL to track down a DB problem in the past. Yes, it's in
  kmymoney/kmymoney/plugins/sql/kmmsqlquery.[h,cpp]
I was on the 5.1 branch, and wondered why I wasn't finding this - but finally realized I needed to be in master branch.

and can be turned on using ENABLE_SQLTRACER. You may use it to add a KMMSqlResult object. The #define at the end of kmmsqlquery.h and the #undef at the beginning of kmmsqlquery.cpp do the trick of using the identical (KMyMoney) source code and switch the stuff with cmake or ccmake (ENABLE_SQLTRACER).
I also turned on QT_DEBUG_SQL and recomipled qtsql, which gave me a little further debugging output. I may now almost understand how this works, but haven't yet figured out how to expand on it.

[from later email]
But the whole thing works for sqlite and MySql/Mariadb, so I'm assuming the problem is likely in postgres specifics of qsql.
or in the way we use it. I still have the feeling that one of the calls to prepare() fails and we don't take notice and then calling exec() causes the problem. Not sure though. Have not looked at our code lately in that area.
Yes, the prepare is what fails, even though it is preparing the exact same statement as a few times earlier in the process. My efforts now are trying to figure out why the prepare fails. Eventually we should probably put a try/catch around the prepare's as well as the exec's.

I think the only reason that number is so high is that I made a whole lot of attempts within that ddd/gdb session. I just started a new session, and the first iteration I saw was _A, so I might try putting a watch on that value, if it is something gdb can do.
Yes, GDB should be able to do that.
I haven't figured out where to do that - it seems that particular value is part of a result, which is created for each new query. Anyway, the relevant part of the output is below, with some comments in []

-------------------
[this is starting about line 333 of .../plugins/sql/mymoneystorage.cpp, calling d->writeOnlineJobs()]

Created 79
Executed query (0ms, 1 results, 1 affected): "SELECT count(*) FROM kmmOnlineJobs"
79 executed "SELECT count(*) FROM kmmOnlineJobs"
Executed query (0ms, -1 results, 0 affected): "SELECT count(*) FROM kmmSepaOrders"
79 executed "SELECT count(*) FROM kmmSepaOrders"
Executed query (0ms, -1 results, 0 affected): "SELECT count(*) FROM kmmNationalAccountNumber"
79 executed "SELECT count(*) FROM kmmNationalAccountNumber"
Destroyed 79

[and finally calling d->writeFileInfo(), which calls deleteKeyValuePairs]
Created 80

QSqlQuery::prepare: DELETE FROM kmmKeyValuePairs WHERE kvpType = :kvpType AND kvpId = :kvpId; Error in function void MyMoneyStorageSqlPrivate::deleteKeyValuePairs(const QString&, const QVariantList&) : preparing statement to delete kvp for STORAGE
Driver = QPSQL, Host = localhost, User = jack, Database = kmm
Driver Error:
Database Error No -1:
Text:
Error type 0
Executed: DELETE FROM kmmKeyValuePairs WHERE kvpType = ? AND kvpId = ?;
Query error No 0: ERROR: current transaction is aborted, commands ignored until end of transaction block
(25P02) QPSQL: Unable to prepare statement
Error type 2
void MyMoneyStorageSql::cancelCommitUnit(const QString&) - void MyMoneyStorageSqlPrivate::deleteKeyValuePairs(const QString&, const QVariantList&) s/be bool MyMoneyStorageSql::writeFile()
Destroyed 80
-------------------
Considering there is no code between "QSqlQuery query(*q);" and "if (!query.prepare("DELETE FROM kmmKeyValuePairs WHERE kvpType = :kvpType AND kvpId = :kvpId;"))" I don't know where or why the transaction gets aborted. I've traced this into the bowels of qtsql ..../src/plugins/sqldrivers/psql/qsql_psql.cpp, but I still can't figure out exactly what is failing. However, at about the point of the failure, there is a local result which is optimized out, so I think my next step is to recompile qtsql with less optimization.

Jack

Reply via email to