Transaction with unsuccessful commit can never be rollbacked. This migth cause some metaobjects get locked and as result hanging of any client (including itself) which tries to use that metaobjects. Example:
CREATE SEQUENCE myseq; CREATE TABLE mytbl (id INTEGER); CREATE OR ALTER TRIGGER mytrig_bi0 FOR mytbl active BEFORE INSERT POSITION 0 AS BEGIN NEW.id = NEXT VALUE FOR myseq; END
QSqlDatabase db = ... QString sql = "drop sequence myseq"; db.transaction(); QSqlQuery q(sql, db); qDebug() << q.lastError().text(); // no error! q.close(); db.commit(); qDebug() << q.lastError().text(); // error: unsuccessful metadata update... // trying to drop once more time db.transaction(); QSqlQuery q(sql, db); // blocked forever...
Edit file …/qtbase/src/sql/drivers/ibase/qsql_ibase.cpp
:
bool QIBaseDriver::commitTransaction() { Q_D(QIBaseDriver); if (!isOpen() || isOpenError()) return false; if (!d->trans) return false; isc_commit_transaction(d->status, &d->trans); // d->trans = 0; // return !d->isError(QT_TRANSLATE_NOOP("QIBaseDriver", "Unable to commit transaction"), // QSqlError::TransactionError); bool res = !d->isError(QT_TRANSLATE_NOOP("QIBaseDriver", "Unable to commit transaction"), QSqlError::TransactionError); if( !res ) isc_rollback_transaction(d->status, &d->trans); d->trans = 0; return res; }
Prefer explicit transation start and commit as shown above because it is not possible to avoid this problem executing queries with implicit transaction control.