Seite 1 von 1
[gelöst] QSqlQuery.clear() muss immer ausgeführt werden
Verfasst: 15. April 2010 18:22
von suamikim
Hallo zusammen,
ich arbeite in meinem Programm mit einer SQLite-DB, welche ich beim beenden des Programms immer lösche.
Die DB-Zugriffe erfolgen größtenteils über das QSqlQuery und dessen exec-Methode.
Wenn ich nach jedem exec und der entsprechenden Verarbeitung der Daten die clear()-Methode ausführe ist alles in Ordnung.
Sobald ich clear() aber nicht aufrufe kann ich beim beenden des Programms die Datenbank nicht löschen weil sie anscheinend noch schreibgeschützt ist obowhl ich die Verbindung zuvor ordnungsgemäß schließe:
Code: Alles auswählen
QString qStrDbFilename;
QString qStrDbConName;
{
QSqlDatabase db = QSqlDatabase::database();
qStrDbConName = db.connectionName();
qStrDbFilename = db.databaseName();
db.close();
}
QSqlDatabase::removeDatabase(qStrDbConName);
Gibt es irgendeine Möglichkeit alle "offenen" Query's beim schließen der Verbindung (also in obigem Code) zu beenden damit ich nicht bei jedem arbeiten mit einem Query aufs clear() aufpassen muss?
Die Dokumentation zum clear sagt eigentlich folgendes:
Clears the result set and releases any resources held by the query. Sets the query state to inactive. You should rarely if ever need to call this function.
Es sollte also fast nie bis nie nötig sein, diese Funktion aufzurufen...
danke, mfg
Re: SQLite: QSqlQuery.clear() muss immer ausgeführt werden
Verfasst: 15. April 2010 19:01
von franzf
suamikim hat geschrieben:ich arbeite in meinem Programm mit einer SQLite-DB, welche ich beim beenden des Programms immer lösche.
Erstens ist SQLite keine Serverbasierte DB. SQLite schreibt alles in Dateien. Ein QFile::remove(dbFile); entfernt auch alle Daten

Zweitens - viel wichtiger:
http://www.sqlite.org/inmemorydb.html
Code: Alles auswählen
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
Und du musst gar nicht mehr selber Hand anlegen. Es existiert kein db-file, liegt alles nur im RAM.
Kann es sein dass dein Fehler daher kommt, dass irgendwo ein QSqlDatabase-Objekt als Member gespeichert ist? QSqlDatabase zählt Referenzen. Wenn also irgendwo noch ein solches Objekt rumliegt, lässt sich die Verbindung nicht entfernen. Deshalb am besten nie QSqlDatabase-Objekte speichern, du kriegst das im Kontext ratzfatz mit QSqlDatabase::database(dbName);
Re: SQLite: QSqlQuery.clear() muss immer ausgeführt werden
Verfasst: 15. April 2010 20:47
von Troll.Soft
franzf hat geschrieben:QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:")
optimal !
diese Möglichkeit wollte ich auch noch suchen. Nun finde ich sie aus Versehen
Was der Franz noch erwähnte habe ich anhand böser Abstürze auch erlebt. Seitdem läuft bei mir nur noch eine Instanz.
tschüß
Troll.Soft
Verfasst: 15. April 2010 22:51
von suamikim
Erstens ist SQLite keine Serverbasierte DB. SQLite schreibt alles in Dateien. Ein QFile::remove(dbFile); entfernt auch alle Daten
Schon klar, dass SQLite eine Datei-basierte DB ist. Unter anderem hab ich sie ja deswegen ausgewählt
Die Geschichte mit der In-Memory-DB ist zwar interessant hilft in meinem Fall aber auch nicht weiter.
Mein Programm macht folgendes:
Ich kann im Programm auswählen, ob ich mit einem lokal gespeichertem File oder einem auf einem FTP-Server arbeiten möchte.
Da man die DB mit SQLite nicht verschlüsseln kann und die Daten somit quasi im Klartext herumliegen hab ich in meiner SW eine eigene kleine Datei-Verschlüsselung eingebaut. Nichts großartiges aber für meine Zwecke ausreichend.
Die Vorgehensweise ist im Prinzip nun also folgende:
Programm starten -> Verschlüsselte Datei entschlüsseln -> normale SQLite-DB-Datei liegt am Rechner -> Programm arbeitet mit Daten -> Programm schließen -> Datei wieder verschlüsseln (ergibt eine neue, verschlüsselte Datei) -> Unverschlüsselte Datei löschen
Und genau der letzte Punkt funktioniert in meinem Fall nicht, da dass von dir erwähnte QFile::remove(...) fehl-schlägt da die Datei anscheinend nach dem schließen noch schreibgeschützt ist bzw. der Zugriff darauf nicht freigegeben wurde.
Ein QSqlDatabase-Objekt liegt auch nirgends herum. Wie du bereits vorgeschlagen hast arbeite ich eigentlich nur mit QSqlDatabase::database()...
Verfasst: 16. April 2010 09:10
von Troll.Soft
suamikim hat geschrieben:Und genau der letzte Punkt funktioniert in meinem Fall nicht, da dass von dir erwähnte QFile::remove(...) fehl-schlägt da die Datei anscheinend nach dem schließen noch schreibgeschützt ist bzw. der Zugriff darauf nicht freigegeben wurde.
Nochmal, exakt dieses Problem hatte ich auch. Die Lösung war auf alle, wirklich alle eigenen QSqlQuery zu verzichten und nur die .exec("select ...") von QSqlDatabase zu benutzen. Liefert eine Referenz auf einen Query zurück. Danach ließ sich die DB löschen.
Es würde natürlich reichen, alle Referenzen zu löschen, wenn man QSqlQuery verwendet, aber die Suche war mir zu mühsam

tschüß
Troll.Soft
Verfasst: 16. April 2010 09:23
von franzf
Irgendwo wird dann noch indirekt ein QSqlDatabase-Objekt gespeichert. Z.B in nem Model.
Also alles löschen, was mit DB zu tun haben könnte, dann kannst du deine Verbindung entfernen.
Verfasst: 16. April 2010 10:02
von suamikim
Ok, war tatsächlich mein Fehler. Sorry.
Hatte kein QSqlDatabase-Objekt herumliegen, dafür aber bei jeder Abfrage einen neuen Pointer auf ein QSqlQuery-Objekt erzeugt, den ich danach nicht gelöscht habe...
Benutze nun auch das exec(...) von QSqlDatabase::database() wodurch ich mich nicht mehr ums aufräumen der erzeugten Objekte kümmern muss und auch das löschen des DB-Files beim schließen ohne Probleme funktioniert.
Danke, mfg
mik