Mysql++ wirft BadQuery ohne error
-
Hallo,
ich habe bei meinem ersten C++-Mysql-Projekt ein sch... Problem:
Ein einfaches "select * from user where uid = 'admin';" schlägt fehl unf wirft ein BadQuery-Objekt. BadQuery::Error ist dabei aber leer und Query::error() gibt auch nichts zurück. Ich vermute, dass etwas mit der Connection nicht stimmt, da die exakt gleiche Query zu einem anderen Zeitpunkt sauber ausgeführt wird, aber ich finde keine möglichkeit zur Fehleranalyse. Connection::conected() gibt bei mir IMMER false...Hat einer nen Tipp?
Vielen Dank!
Peanut
-
kannst du mal ein wenig code zeigen?? Eventuell kann ich dir dann helfen...
-
Auch der Connect liefert eine Errormeldung.
Diese abfragen bzw. macht man in Code sowieso nur weiter wenn vorher kein Fehler gekommen ist.
Also Handle checken ob gültig. Code für MYSQL gibt in der FAQ.
Bitte das nächste mal vorher nachschauen
-
Der Connect ist schon lange durch und auf der Verbindung sind zum Problemzeitpunkt schon einige Querys erfolgreich durchgelaufen!
Ok, ein Stück Code:
bool UserDB::store( UserDBEntry& user ){ Query query( db->con()->query() ); Result result; if ( user.hasChangedValue() ){ query << "SELECT * FROM user WHERE uid = \"" << user.getUID() << "\""; std::string querytext=query.preview(); ///store for exception try { result = query.store(); std::cerr << "UserDB-Queryi-Succses: " << querytext << std::endl; } catch (BadQuery er) { std::cerr << "UserDB-Query-Error: " << querytext << std::endl; throw Error("Database problem with: "+querytext+"\n->"+er.error); } catch (BadConversion er) { throw Error("Database Type-Problem: "+ er.data +"-"+ er.type_name); } catch (...){ throw Error("Database has a problem to execute: "+querytext); } /// hier kommt noch ein switch ( result.size() ) /// case 0: "insert into user..." /// case 1: "update user set..." /// default: "throw error("DB inkonsistent");" }
Die DB-Klasse enthält eine map<string DBID, Connection conn> und liefert bei db->conn() die Connection. Wenn ich die Connection schliesse bekomme ich allerdings die Aussagekräftige Fehlermeldung: Database gone away.
Es handelt sich um eine CGI-App. Das Problem entsteht nur beim ausloggen! Hier ein auszug aus dem Errorlog:
=== Start ===
WebUI constructor
DB constructor
User constructor
mod: login.so
WebUI destructor
User destructor
=== Ende ===
=>Keine Session-ID, keine Logindaten > Loginform
=== Start ===
WebUI constructor
DB constructor
User constructor
mod: login.so
User constructor
User destructor
UserDB-Queryi-Succses: SELECT * FROM user WHERE uid = "mwolff"
WebUI destructor
User destructor
=== Ende ===
=>Session-ID ungültig, Logindate vorhanden, Session-ID dem User zugeordnet, reload
=== Start ===
WebUI constructor
DB constructor
User constructor
mod: none.so
WebUI destructor
User destructor
=== Ende ===
=>Session-ID gültig > Usermenu
=== Start ===
WebUI constructor
DB constructor
User constructor
mod: none.so
WebUI destructor
User destructor
UserDB-Query-Error: SELECT * FROM user WHERE uid = "mwolff"
Es ist ein Fehler aufgetreten:
Database problem with: SELECT * FROM user WHERE uid = "mwolff"
->
=> reload, exception ausgelöst
=== Start ===
WebUI constructor
DB constructor
User constructor
mod: login.so
WebUI destructor
User destructor
=== Ende ===
=>Keine Session-ID, keine Logindaten > Loginform
-
nur eine einfache frage.. wird bestimmt von dir abgefangen sein, aber:
existiert der user?
wenn nicht, kommt vielleicht wirklich nix zurück bei dieser abfrage?
-
Der als Parameter übergebene UserDBEntry-user existiert da sonst user.getUID() Fehlschlagen oder zumindest nicht dir richtige UID liefern würde. In der DB besteht der Eintrag auch und sollte daher nur upgedatet werden. Selbst wenn kein Eintrag in der DB währe sollte es ja nicht zu einer BadQuery kommen, oder???
Nach start wird der User mit folgenden Code angelegt:
User* UserDB::restore( std::string _sid ){ Query query = db->con()->query(); query << "SELECT * FROM user WHERE sid = \"" << _sid << "\""; std::string querytext=query.preview(); ///store for exception Result result; try { result = query.store(); } catch (...){ throw Error("Database has a problem to execute: "+querytext); } switch ( result.size() ){ case 0:{ UserDBEntry dbEntry; /// no session return dbEntry.create(); break; } case 1:{ Row row=*result.begin(); UserDBEntry dbEntry( (std::string)row[0], (std::string)row[1], (std::string)row[2], (std::string)row[4], (std::string)row[3] ); loadSession( dbEntry ); return dbEntry.create(); break; } default:{ throw Error("Database inkonsistent, double entry for sid "+_sid ); break; } } }
Man beachte das die selbe Verbindung genutzt wird! Und das erstellen des Users tut ja einwandfrei!
edit: Formatierungsfehler behoben
[ Dieser Beitrag wurde am 12.06.2003 um 10:53 Uhr von Peanut editiert. ]
-
Die letzten Regungen vor der Exeception:
(gdb) 0x0806106e in operator-<const SQLParseElement*, const SQLParseElement*, std::vector<SQLParseElement, std::allocator<SQLParseElement> > > (__lhs=@0xbfbff3c0, __rhs=@0xbfbff3c4) at /usr/local/lib/gcc-lib/i386-portbld-freebsd4.7/3.2.1/include/g++-v3/bits/stl_iterator.h:726 726 { return __lhs.base() - __rhs.base(); } (gdb) 0x080619b9 in __gnu_cxx::__normal_iterator<SQLParseElement const*, std::vector<SQLParseElement, std::allocator<SQLParseElement> > >::base() const ( this=0xbfbff3c4) at /usr/local/lib/gcc-lib/i386-portbld-freebsd4.7/3.2.1/include/g++-v3/bits/stl_iterator.h:633 633 base() const { return _M_current; } (gdb) 0x0806107e in operator-<const SQLParseElement*, const SQLParseElement*, std::vector<SQLParseElement, std::allocator<SQLParseElement> > > (__lhs=@0xbfbff3c0, __rhs=@0xbfbff3c4) at /usr/local/lib/gcc-lib/i386-portbld-freebsd4.7/3.2.1/include/g++-v3/bits/stl_iterator.h:726 726 { return __lhs.base() - __rhs.base(); } (gdb) 0x080600fd in std::vector<SQLParseElement, std::allocator<SQLParseElement> >::size() const (this=0xbfbff5e8) at /usr/local/lib/gcc-lib/i386-portbld-freebsd4.7/3.2.1/include/g++-v3/bits/stl_vector.h:261 261 { return size_type(end() - begin()); } (gdb) MysqlQuery::store(SQLQueryParms&, query_reset) (this=0xbfbff500, p=@0xbfbff60c, r=RESET_QUERY) at /usr/local/include/mysql/query2.hh:39 39 return mysql->store(str(p,r)); (gdb) Breakpoint 2, MysqlConnection::store(std::string const&) (this=0xbfbff500, str=@0xbfbff60c) at /usr/local/include/mysql/connection1.hh:92 92 Result store(const std::string &str) {return store(str, throw_exceptions);} //:
-
So, einen Workaround habe ich jetzt, aber ich weiss noch immer nicht wo mein Problem liegt!
Was kann denn mit einer Connection noch passieren? Entweder sie ist da und alles tut, oder sie ist nicht da und ich bekomme ein "Database gone" aber was soll das? Tut nicht, Connection close und open und es tut
bool UserDB::store( UserDBEntry& user ){ if ( user.hasChangedValue() ){ user.setValueUnchanged(); Query query( db->con()->query() ); query << "SELECT * FROM user WHERE uid = \"" << user.getUID() << "\""; std::string querytext=query.preview(); ///store for exception Result result; try { result = query.store(); std::cerr << "UserDB-Query-Succses: " << querytext << std::endl; } catch (BadQuery er) { std::cerr << "UserDB-Query-Error: " << querytext << std::endl; std::cerr << "reconnect(): " << true << db->reconnect() << std::endl; Query query( db->con()->query() ); query << "SELECT * FROM user WHERE uid = \"" << user.getUID() << "\""; try { result = query.store(); } catch (...){ std::cerr << "UserDB-Query-Error again!" << std::endl; throw Error("Database problem with: "+querytext+"\n->"+er.error); } } catch (BadConversion er) { throw Error("Database Type-Problem: "+ er.data +"-"+ er.type_name); } catch (...){ throw Error("Database has a problem to execute: "+querytext); } } return true; }
und
bool DB::reconnect(){ connection->close(); Config conf("DB_"+dbid); Connection* conn = new Connection(use_exceptions); try { conn->connect(conf["db"].c_str(), conf["host"].c_str(), conf["user"].c_str(), conf["pass"].c_str()); conn->select_db(conf["db"].c_str()); connection=conn; return true; } catch (BadQuery er) { conn->close(); delete conn; DB::UseCount.erase(dbid); DB::ConnectionMap.erase(dbid); return false; } catch(...){ return false; } }
-
Sollte ich mein Projekt besser mir der C-API realisieren? Die scheint mir wesentlich transparenter!
-
Funktioniert der SELECT nicht oder was ?
Wenn man 2 SELECT mit dem selben Connect macht ohne vorher die DB zu schließen muss man das vorherige Result löschen.
-
HowToDO?
Result hat keine Methode close(), clear() o.ä.
Connection.close(); Connection.open( bla, bla ) will ich grade vermeiden!