QSqlDatabase::transaction()

Alles rund um die Programmierung mit Qt
Antworten
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

QSqlDatabase::transaction()

Beitrag von Marco812 »

Hi,

wie kann man eine Transaction bei Fehlern rückgängig machen?

Beispiel:

Code: Alles auswählen

QSqlDatabase db = QSqlDatabase::database();
db.transaction();

QSqlQuery q;
for (int i=0; i<5; i++)
{
   q.exec("DELETE FROM user WHERE user_id ="+ QString().setNum(i) +";");
}

q.clear();
if(!db.commit()){
   db.rollback();
}
Wenn es jetzt einen Fehler gibt, sollte db.commit() != true sein und db.rollback() ausgeführt werden, was aber nicht der Fall ist. Hat jemand eine Lösung bzw. Erklärung dafür?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Welche Datenbank? Werden von der Datenbank auch Transaktionen unterstützt?
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

Beitrag von Marco812 »

Das ist eine SQLite-Datenbank.

Transaktionen sollten unterstützt werden, da db.rollback() funktioniert, wenn ich absichtlich einen Fehler produziere und anschließend das rollback durchführe. Mir ist aber nicht klar, warum ich bei if(!db.commit()) den Wert TRUE erhalte, wenn zuvor eine oder mehrere fehlerhafte QSqlQuery's ausgeführt wurden.

Hat jemand eine Erklärung dafür?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Ich weis nicht, wie es bei SQLite ist, aber bei anderen Datenbanken kenn ich es so, das nach einem fehlgeschlagenen COMMIT kein ROLLBACK notwendig ist, da dies automatisch ausgeführt wird.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

hier steht bissl was
http://www.sqlite.org/lang_transaction.html
u.a. das hier:
But a transaction will also ROLLBACK if the database is closed or if an error occurs and the ROLLBACK conflict resolution algorithm is specified.
muss man nur noch wissen, ob qt von sich aus einen "conflict resolution algorithm" setzt.
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

Beitrag von Marco812 »

Also bei einem COMMIT wird nach einem Fehler nicht automatisch ein ROLLBACK durchgeführt.

Wie bereits erwähnt, das ROLLBACK funktioniert, sobald ich es nach einem Fehler per Hand ausführe.

Mir ist aber immer noch nicht klar warum nach einem Fehler in einer QSqlQuery COMMIT == TRUE ist. Wie kann ich außer mit COMMIT prüfen ob ein ROLLBACK notwendig ist?
Marco812
Beiträge: 139
Registriert: 22. November 2005 11:28

Beitrag von Marco812 »

Nach langem lesen in der Dokumentation habe ich folgendes versucht:

Code: Alles auswählen

	QSqlDatabase db = QSqlDatabase::database();
	QSqlQuery q(db);
	qDebug() << db.driver()->hasFeature(QSqlDriver::Transactions); //true
Demzufolge werden Transaktionen unterstützt. Worauf ich folgendes versucht habe:

Code: Alles auswählen

	qDebug() << db.driver()->beginTransaction(); //true
	qDebug() << q.exec("SELECT;"); //false
	qDebug() << db.driver()->commitTransaction();//true
und

Code: Alles auswählen

	qDebug() << q.exec("BEGIN TRANSACTION"); //true
	qDebug() << q.exec("SELECT;"); //false
	qDebug() << q.exec("COMMIT");//true
Ich verstehe nicht warum immer COMMIT == TRUE ergibt, obwohl ein Fehler erzeugt wurde, was durch q.lastError() auch bestätigt wird. Was mache ich falsch?

Kann mit jemand sagen wie ich ein "conflict resolution algorithm" setzen kann, was das überhaupt ist und ob es ggf. bereits von Qt gesetzt wird?
ms47
Beiträge: 35
Registriert: 22. Januar 2009 10:02

Beitrag von ms47 »

Marco812 hat geschrieben:Nach langem lesen in der Dokumentation habe ich folgendes versucht:

Code: Alles auswählen

	QSqlDatabase db = QSqlDatabase::database();
	QSqlQuery q(db);
	qDebug() << db.driver()->hasFeature(QSqlDriver::Transactions); //true
Demzufolge werden Transaktionen unterstützt. Worauf ich folgendes versucht habe:

Code: Alles auswählen

	qDebug() << db.driver()->beginTransaction(); //true
	qDebug() << q.exec("SELECT;"); //false
	qDebug() << db.driver()->commitTransaction();//true
und

Code: Alles auswählen

	qDebug() << q.exec("BEGIN TRANSACTION"); //true
	qDebug() << q.exec("SELECT;"); //false
	qDebug() << q.exec("COMMIT");//true
Ich verstehe nicht warum immer COMMIT == TRUE ergibt, obwohl ein Fehler erzeugt wurde, was durch q.lastError() auch bestätigt wird. Was mache ich falsch?

Kann mit jemand sagen wie ich ein "conflict resolution algorithm" setzen kann, was das überhaupt ist und ob es ggf. bereits von Qt gesetzt wird?
Hallo,

habe zurzeit das gleiche Problem und wollte mal fragen, ob du diesbezüglich weiter gekommen bist?

Danke und Gruß
Markus
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Wie lautet eigentlich die Fehlermeldung, die lastError() zurückliefert?
ms47
Beiträge: 35
Registriert: 22. Januar 2009 10:02

Beitrag von ms47 »

upsala hat geschrieben:Wie lautet eigentlich die Fehlermeldung, die lastError() zurückliefert?
Bei mir ist es:

Code: Alles auswählen

QSqlError(-1, "QPSQL: Unable to create query", "FEHLER:  Spalte »is_value« hat Typ boolean, aber der Ausdruck hat Typ integer
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Ok, commitTransaction liefert nur dann einen (Transaktionsfehler) wenn das Kommando selbst schief geht.

Aber: Wenn eine Query schon false liefert, sollte hier schon die Transaktion abgebrochen werden.

Auf der anderen Seite kann man event. aber hier ein wenig tricksen:
select //false
...
select 1 //jetzt ebenfalls false, da oben schon false
commit //
Antworten