sqlite3_step() gibt sqlite_nomem zurück
-
Ja C++ in Visual Studio 2010 auf Windows 7
Also ganz grob ist der Ablauf so:
sqlite3_open
f.open
sqlite3_prepare_v2
while(rückgabe von sqlite3_step == sqlite_row){
sqlite3_step
speichern der datenbankwerte
berechnungen
f << alle Daten rein in die Textdatei
}
sqlite3_finalize
sqlite3_close
-
Wir können hier jetzt herumraten bis du zufällig den Fehler findest. Oder du veröffentlichst einfach den Code.
-
Wenn's nicht zuviel ist...:)
-
Ich fürchte der Code ist nicht sehr übersichtlich, aber hier ist der betroffene Abschnitt:
if(sqlite3_open(dbName, &database) != SQLITE_OK)
cout << "Fehler beim Oeffnen der Datenbank" << endl;qry = "select distinct a.LI_LFD_NR, a.ORT_NR, b.FRT_FID, b.FRT_START, b.FGR_NR, c.frt_hzt_zeit from rec_frt b join lid_verlauf a on a.LI_NR=b.LI_NR and a.STR_LI_VAR = b.STR_LI_VAR left join rec_frt_hzt c on b.FRT_FID = c.FRT_FID and a.ORT_NR = c.ORT_NR;";
f.open("GTFS/stop_times.txt", ios::out);
if(! f.is_open())
cout << "Datei routes konnte nicht geschrieben werden" << endl;f << "trip_id,arrival_time,departure_time,stop_id,stop_sequence" << endl;
sqlite3_prepare_v2(database, ((char*)qry.c_str()), -1, &statement, 0);
result = sqlite3_step(statement);
do{
sequence = sqlite3_column_int(statement, 0);
ort = (char*)sqlite3_column_text(statement, 1);
fid = (char*)sqlite3_column_text(statement, 2);
ankunft = sqlite3_column_int(statement, 3);
fgr_nr= (char*)sqlite3_column_text(statement, 4);if(sqlite3_column_int(statement, 5) != NULL)
halt = sqlite3_column_int(statement, 5);
else
halt = 0;if(sequence == 1 && anfang == true){
abfahrt_sekunden = 0;
start = uhrzeit(ankunft);
abfahrt_sekunden = ankunft + halt;
abfahrt = uhrzeit(abfahrt_sekunden);
f << fid << "," << start << "," << abfahrt << "," << ort << "," << sequence << endl;
anfang = false;
}else{
qry1 = "";
result = sqlite3_step(statement);if(result == SQLITE_ROW){
fid1=(char*)sqlite3_column_text(statement, 2);if(fid1 == fid){
gruppe = (char*)sqlite3_column_text(statement, 4);
ziel =(char*)sqlite3_column_text(statement, 1);if(sqlite3_column_int(statement, 5) != NULL)
halt = sqlite3_column_int(statement, 5);
else
halt = 0;qry1 = "select sel_fzt from sel_fzt_feld where fgr_nr = " + gruppe + " and ort_nr = " + ort + " and sel_ziel = " + ziel + ";";
sqlite3_prepare_v2(database, ((char*)qry1.c_str()), -1, &statement1, 0);
result1 = sqlite3_step(statement1);
fahrzeit = 0;if(result1 == SQLITE_ROW)
if(sqlite3_column_int(statement1, 0) != NULL)
fahrzeit = sqlite3_column_int(statement1, 0);abfahrt_sekunden += fahrzeit;
zwischenstop = uhrzeit(abfahrt_sekunden);
abfahrt_sekunden += halt;
abfahrt = uhrzeit(abfahrt_sekunden);f << fid << "," << zwischenstop << "," << abfahrt << "," << ziel << "," << sequence+1 << endl;
anfang = true;
}
}
}}while(result == SQLITE_ROW);
sqlite3_finalize(statement);
sqlite3_close(database);f.close();
-
Und jetzt noch einmal in C++-Tags, damit man es lesen kann.
-
if(sqlite3_open(dbName, &database) != SQLITE_OK) cout << "Fehler beim Oeffnen der Datenbank" << endl; qry = "select distinct a.LI_LFD_NR, a.ORT_NR, b.FRT_FID, b.FRT_START, b.FGR_NR, c.frt_hzt_zeit from rec_frt b join lid_verlauf a on a.LI_NR=b.LI_NR and a.STR_LI_VAR = b.STR_LI_VAR left join rec_frt_hzt c on b.FRT_FID = c.FRT_FID and a.ORT_NR = c.ORT_NR;"; f.open("GTFS/stop_times.txt", ios::out); if(! f.is_open()) cout << "Datei routes konnte nicht geschrieben werden" << endl; f << "trip_id,arrival_time,departure_time,stop_id,stop_sequence" << endl; sqlite3_prepare_v2(database, ((char*)qry.c_str()), -1, &statement, 0); result = sqlite3_step(statement); do{ sequence = sqlite3_column_int(statement, 0); ort = (char*)sqlite3_column_text(statement, 1); fid = (char*)sqlite3_column_text(statement, 2); ankunft = sqlite3_column_int(statement, 3); fgr_nr= (char*)sqlite3_column_text(statement, 4); if(sqlite3_column_int(statement, 5) != NULL) halt = sqlite3_column_int(statement, 5); else halt = 0; if(sequence == 1 && anfang == true){ abfahrt_sekunden = 0; start = uhrzeit(ankunft); abfahrt_sekunden = ankunft + halt; abfahrt = uhrzeit(abfahrt_sekunden); f << fid << "," << start << "," << abfahrt << "," << ort << "," << sequence << endl; anfang = false; } else{ qry1 = ""; result = sqlite3_step(statement); if(result == SQLITE_ROW){ fid1=(char*)sqlite3_column_text(statement, 2); if(fid1 == fid){ gruppe = (char*)sqlite3_column_text(statement, 4); ziel =(char*)sqlite3_column_text(statement, 1); if(sqlite3_column_int(statement, 5) != NULL) halt = sqlite3_column_int(statement, 5); else halt = 0; qry1 = "select sel_fzt from sel_fzt_feld where fgr_nr = " + gruppe + " and ort_nr = " + ort + " and sel_ziel = " + ziel + ";"; sqlite3_prepare_v2(database, ((char*)qry1.c_str()), -1, &statement1, 0); result1 = sqlite3_step(statement1); fahrzeit = 0; if(result1 == SQLITE_ROW) if(sqlite3_column_int(statement1, 0) != NULL) fahrzeit = sqlite3_column_int(statement1, 0); abfahrt_sekunden += fahrzeit; zwischenstop = uhrzeit(abfahrt_sekunden); abfahrt_sekunden += halt; abfahrt = uhrzeit(abfahrt_sekunden); f << fid << "," << zwischenstop << "," << abfahrt << "," << ziel << "," << sequence+1 << endl; anfang = true; } } } }while(result == SQLITE_ROW); sqlite3_finalize(statement); sqlite3_close(database); f.close();
-
Du finalisierst statement1 nie, oder?
Ansonsten: Du sollst auch nicht immer das statement neu kompilieren.
Ohne jetzt den großen Plan zu haben muss das irgendwie so aussehen:void f(){ const char qry1[] = "select sel_fzt from sel_fzt_feld where fgr_nr = ?" "and ort_nr = ? and sel_ziel = ?"; // einmal compilen: sqlite3_prepare_v2(database, qry1, -1, &statement1, 0); //... while(bedingung){ int sqlite3_reset(statemen1); int sqlite3_bind_text(statement1, 0, gruppe.c_str(), nullptr); int sqlite3_bind_text(statement1, 1, ort.c_str(), nullptr); int sqlite3_bind_text(statement1, 2, ziel.c_str(), nullptr); sqlite3_step(statement); //... } //... }
-
Ähm...da war ein klitzekleiner copy&paste Fehler, ausserdem fängt die Nummerierung der Parameter bei 1 an:
void f(){ const char qry1[] = "select sel_fzt from sel_fzt_feld where fgr_nr = ?" "and ort_nr = ? and sel_ziel = ?"; // einmal compilen: sqlite3_prepare_v2(database, qry1, -1, &statement1, 0); //... while(bedingung){ sqlite3_reset(statemen1); sqlite3_bind_text(statement1, 1, gruppe.c_str(), nullptr); sqlite3_bind_text(statement1, 2, ort.c_str(), nullptr); sqlite3_bind_text(statement1, 3, ziel.c_str(), nullptr); sqlite3_step(statement); //... } //... }
-
Schon mal vielen Dank! Ich werd es mal ausprobieren
-
Ich während des WM-Spiels mal ein funktionierendes Beispiel erstellt:
#include <iostream> #include <string> #include <vector> #include <cassert> #include <sqlite3.h> struct person{ std::string name, vorname; }; std::ostream& operator<<(std::ostream& out, const person& p){ return out << p.name << ", " << p.vorname; } sqlite3* open(){ sqlite3 *p; int stat = sqlite3_open(":memory:", &p); assert(stat==SQLITE_OK); return p; } void create(sqlite3* db){ const char sql[] = "CREATE TABLE person(name TEXT, vorname TEXT)"; sqlite3_stmt *stmt; sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); sqlite3_step(stmt); sqlite3_finalize(stmt); } void insert(const std::vector<person>& v, sqlite3* db){ const char sql[] = "INSERT INTO person(name, vorname) VALUES ( ?, ? )"; sqlite3_stmt *stmt; sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); for(const auto& p : v){ sqlite3_bind_text(stmt, 1, p.name.c_str(), -1, nullptr); sqlite3_bind_text(stmt, 2, p.vorname.c_str(), -1, nullptr); sqlite3_step(stmt); sqlite3_reset(stmt); } sqlite3_finalize(stmt); } std::vector<person> get(const std::string& name, sqlite3* db){ const char sql[] = "SELECT name, vorname FROM person WHERE name = ? ORDER BY vorname ASC"; sqlite3_stmt *stmt; sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); sqlite3_bind_text(stmt, 1, name.c_str(), -1, nullptr); std::vector<person> result; while(sqlite3_step(stmt)==SQLITE_ROW){ person p{(char*)sqlite3_column_text(stmt, 0), (char*)sqlite3_column_text(stmt, 1)}; result.push_back(p); } sqlite3_finalize(stmt); return result; } int main() { auto db = open(); create(db); { std::vector<person> v = {{"Wurble", "Furble"}, {"Meier", "Rolf"}, {"Meier", "Ralf"}, {"Mueller", "Gabi"}, {"Meier", "Rudolf"}}; insert(v, db); } auto v = get("Meier", db); for(const auto& p : v) std::cout << p << '\n'; sqlite3_close(db); }
Die Funktion insert() ist ein Beispiel für bind in einer Schleife mit reset() und allem Pi-Pa-Po.
sqlite3_bind_*() ist übrigens auch ein Schutz vor SQL-Injections.
-
Wow vielen Dank! Du hast mir echt wahnsinnig weitergeholfen!
Jetzt kann ich auch alle Daten aus der DB auslesen ohne den Speicherfehler und meine Textdatei ist endlich vollständig
Mit dem Beispiel werd ich jetzt noch mal den Rest von meinem Kuddel-Muddel überarbeiten. Das importieren in die DB ist nämlich noch super lahm...
Vielen lieben Dank noch mal
-
Zwei Fragen:
- Wieso machst du ein
SELECT DISTINCT
statt einfach nurSELECT
? - Wieso holst du die Daten aus der
sel_fzt_feld
Tabelle nicht einfach über einen(LEFT) JOIN
dazu?
Mir ist schon klar dass du die nur bei jeder 2. Zeile brauchst. SQLite wird aber schlau genug sein dass keinen wesentlichen Unterschied in der Ausführungszeit der Query macht. Bzw. ich schätze es wird dadurch sogar schneller werden, da du dann nicht mehr für jede 2. Zeile ein eigenes Statement vorbereiten und ausführen musst.
- Wieso machst du ein
-
Das Select Distinct ist überflüssig geworden. Noch ein altes Überbleibsel. Danke für den Hinweis.
sel_fzt ist nicht nur abhängig von ort_nr und fgr_nr der aktuellen Zeile sondern auch von sel_ziel, dass erst in der nächsten Zeile steht. Wenn ich nen join mach kann ich sel_ziel aber nicht berücksichtigen oder? Dann mach ich den join doch nur anhand von ort_nr und fgr_nr oder hab ich da nen Denkfehler?
-
Oh Shit.
Du verwendest "lid_verlauf.ort_nr" einmal als "sel_fzt_feld.ort_nr" und einmal als "sel_fzt_feld.sel_ziel"?
Hab ich übersehen. Dann geht das natürlich wirklich nicht über nen einfachen JOIN.Und ich wüsste auch keine andere einfache Möglichkeit das zu joinen.
ps: Du hast da übrigens auch noch nen anderen Bug drin:
Du machst keinORDER BY
, verlässt dich aber trotzdem auf die Reihenfolge der Datensätze.