commit bd1d09ad762f8cf97511c5af952967e0f0caf07c Author: Koen Deforche Date: Wed Sep 22 22:05:10 2010 +0200 Fix loading with composite keys diff --git a/src/Wt/Dbo/Session b/src/Wt/Dbo/Session index cae0975..bd56cc1 100644 --- a/src/Wt/Dbo/Session +++ b/src/Wt/Dbo/Session @@ -22,6 +22,7 @@ namespace Wt { namespace Dbo { namespace Impl { extern WTDBO_API std::string quoteSchemaDot(const std::string& table); + template struct LoadHelper; } struct NullType { @@ -417,6 +418,11 @@ private: template ptr loadLazy(const typename dbo_traits::IdType& id); template ptr load(SqlStatement *statement, int& column); + template + ptr loadWithNaturalId(SqlStatement *statement, int& column); + template + ptr loadWithLongLongId(SqlStatement *statement, int& column); + void prune(MetaDboBase *obj); template void prune(MetaDbo *obj); @@ -468,6 +474,7 @@ private: friend class DropSchema; friend class ToAnysAction; friend class FromAnyAction; + template friend class Impl::LoadHelper; }; } diff --git a/src/Wt/Dbo/Session_impl.h b/src/Wt/Dbo/Session_impl.h index d9b8c44..ee9d727 100644 --- a/src/Wt/Dbo/Session_impl.h +++ b/src/Wt/Dbo/Session_impl.h @@ -15,6 +15,27 @@ namespace Wt { namespace Dbo { + namespace Impl { + template + struct LoadHelper + { + static ptr load(Session *session, SqlStatement *statement, + int& column) + { + return session->loadWithNaturalId(statement, column); + }; + }; + + template + struct LoadHelper + { + static ptr load(Session *session, SqlStatement *statement, + int& column) + { + return session->loadWithLongLongId(statement, column); + } + }; + } template void Session::mapClass(const char *tableName) @@ -78,17 +99,49 @@ Session::Mapping *Session::getMapping() const template ptr Session::load(SqlStatement *statement, int& column) { + return Impl::LoadHelper::IdType> + ::load(this, statement, column); +} + +template +ptr Session::loadWithNaturalId(SqlStatement *statement, int& column) +{ + Mapping *mapping = getMapping(); + + typedef typename dbo_traits::IdType IdType; + IdType id; + + /* Natural id is possibly multiple fields anywhere */ + + MetaDbo *dbo = new MetaDbo(dbo_traits::invalidId(), -1, + MetaDboBase::Persisted, *this, 0); + implLoad(*dbo, statement, column); + + typename Mapping::Registry::iterator i + = mapping->registry_.find(dbo->id()); + + if (i == mapping->registry_.end()) { + mapping->registry_[id] = dbo; + return ptr(dbo); + } else { + delete dbo; + return ptr(i->second); + } +} + +template +ptr Session::loadWithLongLongId(SqlStatement *statement, int& column) +{ Mapping *mapping = getMapping(); /* - * If mapping uses surrogate keys, then we can first read the id and decide - * if we already have it. + * If mapping uses surrogate keys, then we can first read the id and + * decide if we already have it. * - * If not, then we need to first read the object, get the id, and if we already - * had it, delete the redundant copy. + * If not, then we need to first read the object, get the id, and if + * we already had it, delete the redundant copy. */ - typedef typename dbo_traits::IdType IdType; - IdType id; + long long id; if (mapping->surrogateIdFieldName) { /* Auto-generated surrogate key is first field */ @@ -111,7 +164,6 @@ ptr Session::load(SqlStatement *statement, int& column) } } else { /* Natural id is possibly multiple fields anywhere */ - MetaDbo *dbo = new MetaDbo(dbo_traits::invalidId(), -1, MetaDboBase::Persisted, *this, 0); implLoad(*dbo, statement, column); diff --git a/test/dbo/DboTest.C b/test/dbo/DboTest.C index 1fc9045..d3ceedd 100644 --- a/test/dbo/DboTest.C +++ b/test/dbo/DboTest.C @@ -218,6 +218,12 @@ public: As asManyToOne; Cs csManyToMany; + D() { } + D(const Coordinate& anId, const std::string& aName) + : id(anId), + name(aName) + { } + template void persist(Action& a) { @@ -903,6 +909,12 @@ void DboTest::test12() { dbo::Transaction t(*session_); + session_->add(new D(Coordinate(5, 6), "yes")); + dbo::ptr d1 = session_->find(); + + BOOST_REQUIRE(d1->name == "yes"); + BOOST_REQUIRE(d1->id == Coordinate(5, 6)); + session_->add(new C("c1")); dbo::Query< dbo::ptr > query = session_->find();