Help with Dbo
Added by Miguel Revilla over 14 years ago
Hi,
I'm a quite new Wt developer, but after using Qt for years I found myself at home when I discovered this framework. Presentations done, this is where I've been stuck for a couple of days:
I am using a sqlite3 db for a project I am just starting (will probably move to postgres later, but that's irrelevant now) and I've found myself lost when I try to add a new record to a table from a class that is not the WApplication derived class. If I try to use the database from a different class, I get a pretty segfault. Let's see the code:
In the main application class I create a db connection and a session:
Wt::Dbo::backend::Sqlite3 sqlite3("yajp.db") ;
session.setConnection(sqlite3) ;
session.mapClass("users") ;
session is declared as public in the the header file. Of course all needed includes and libraries are there, no complaints from the compiler/linker.
dbUser class is declared as this:
#ifndef DBUSER_H
#define DBUSER_H
#include <Dbo/Dbo>
#include <string>
class dbUser {
public:
std::string username ;
std::string password ;
std::string email ;
std::string firstname ;
std::string lastname ;
int country ;
template<class Action>
void persist(Action& a)
{
Wt::Dbo::field(a, username, "username") ;
Wt::Dbo::field(a, password, "password") ;
Wt::Dbo::field(a, email, "email") ;
Wt::Dbo::field(a, firstname, "firstname") ;
Wt::Dbo::field(a, lastname, "lastname") ;
Wt::Dbo::field(a, country, "country") ;
}
} ;
#endif // DBUSER_H
Well, now. If a try to add a new record to the db right after the session creation and class mapping, from that very WApplication class, everything goes smooth. But if, from a different class, I do this:
app = (yajpApp*)Wt::WApplication::instance() ;
Wt::Dbo::Session& session = app->session ;
Wt::Dbo::Transaction transaction(session) ;
dbUser *user = new dbUser() ;
user->username = Wt::WString("test").toUTF8() ;
user->password = Wt::WString("test").toUTF8() ;
user->email = Wt::WString("test@test.com").toUTF8() ;
user->firstname = Wt::WString("test").toUTF8() ;
user->lastname = Wt::WString("test").toUTF8() ;
user->country = 1 ;
Wt::Dbo::ptr<dbUser> userPtr = session.add(user) ;
transaction.commit() ;
Then I get a segfault on session.add(). transaction.commit() never happens. The debugger says this (with wt git, but same behaviour with 3.1.6):
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x00007ffff6d2f7bc in Wt::Dbo::Session::prepareStatements (this=0x6642f8, mapping=0x669210) at /usr/local/install/wt/src/Wt/Dbo/Session.C:252
#2 0x00007ffff6d32174 in Wt::Dbo::Session::initSchema (this=0x6642f8) at /usr/local/install/wt/src/Wt/Dbo/Session.C:201
#3 0x0000000000417ed6 in add<dbUser> (this=0x6642f8, obj=<value optimized out>) at /usr/local/include/Wt/Dbo/Session_impl.h:172
#4 Wt::Dbo::Session::add<dbUser> (this=0x6642f8, obj=<value optimized out>) at /usr/local/include/Wt/Dbo/Session_impl.h:191
#5 0x000000000041449e in homeWidget::registerUser (this=<value optimized out>) at homeWidget.cpp:302
#6 0x00007ffff7a332d1 in boost::signal1<void, Wt::WMouseEvent, boost::last_value<void>, int, std::less<int>, boost::function1<void, Wt::WMouseEvent> >::operator()(Wt::WMouseEvent) () from /usr/local/lib/libwt.so.26
#7 0x00007ffff7a33846 in Wt::EventSignal<Wt::WMouseEvent>::processDynamic(Wt::JavaScriptEvent const&) () from /usr/local/lib/libwt.so.26
#8 0x00007ffff7a894bf in Wt::WebSession::processSignal (this=<value optimized out>, s=0x681e30, se=<value optimized out>, request=<value optimized out>,
kind=<value optimized out>) at /usr/local/install/wt/src/web/WebSession.C:1748
#9 0x00007ffff7a8d343 in Wt::WebSession::notifySignal (this=0x661970, e=...) at /usr/local/install/wt/src/web/WebSession.C:1722
#10 0x00007ffff7a8e11a in Wt::WebSession::notify (this=0x661970, event=...) at /usr/local/install/wt/src/web/WebSession.C:1440
#11 0x00007ffff7a8f4ea in Wt::WebSession::handleRequest (this=0x661970, handler=...) at /usr/local/install/wt/src/web/WebSession.C:1028
#12 0x00007ffff7aa5acb in Wt::WebController::handleAsyncRequest (this=0x64d2d0, request=0x67f660) at /usr/local/install/wt/src/web/WebController.C:609
... and a few more lines that are probably irrelevant now.
But if I try to access session for other operations, such tableName(), it perfectly wors, so the object looks good.
I've checked everything lots of times and also got some help from the "planner" example where an almost identical approach can be found. But nothing, nada, niente. It always segfaults. Any clues?
Thanks a lot.
Replies (1)
RE: Help with Dbo - Added by Koen Deforche over 14 years ago
Hey,
Since you are the second person with a similar problem, I believe we may have actually made a mistake designing the API:
Session::setConnection(SqlConnection& connection)
should probably have had the signature:
Session::setConnection(SqlConnection *connection)
since this makes it more explicit that the connection object is passed by reference and should outlive the session object !
So you need to keep the connection around (store it also in your application instance).
Perhaps it is not too late to deprecate one API for the other ...
Regards,
koen