List:German« Previous MessageNext Message »
From:Peanut Date:June 12 2003 12:49pm
Subject:Mysql++ wirft BadQuery ohne error
View as plain text  
Hallo,
ich habe bei meinem ersten C++-Mysql-Projekt ein 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 
und Connection::error() gibt nix.

Ok, dann mal 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 

 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);} //:

Einen Workaround habe ich jetzt, aber ich weiss noch immer nicht 
wo mein Problem liegt!

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;
  }
}

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???

Ich bin für JEDEN Hinweis Dankbar!!

Bis dann...
Peanut






Thread
Mysql++ wirft BadQuery ohne errorPeanut12 Jun