Project

General

Profile

Wt::Dbo -> "create table 'delete from xxx' and create table 'integer not null'"

Added by Christian Meyer over 1 year ago

I tried to build a templated Table to enable Polymorphism in Dbo
And it seems that with that I found 2 problems

  1. If Wt::Dbo::hasOne is used in a OneToOne Relation, my App crashes on a call to Session::tableCreationSql() which can of course be related to 2...

  2. Somehow the Tablename is mangled up somewhere along the way and while I am still trying to figure out whats happening, the tablecreateSql changed from create table \"delete from \"\" where \"id\" = ?\" to create table \"integer not null\"

If you have any Idea as to what is happening I would be really exited to read about it =)

Here is my code

Template Class

//t.h

template <class Base, class Derived>
class ConnectorTable
{
protected:
    Wt::Dbo::ptr<Base> basePtr;
    Wt::Dbo::ptr<Derived> derivedPtr;

public:
    static std::string fieldName()
    {
        return Wt::WString("derived_{1}_to_{2}")
                .arg(Base::refName())
                .arg(Derived::refName())
                .toUTF8();
    }

    ConnectorTable() { }
    ConnectorTable(Wt::Dbo::ptr<Base> bPtr, Wt::Dbo::ptr<Derived> dPtr);
    virtual ~ConnectorTable() {}

    Wt::Dbo::ptr<Derived> getDerived() const { return derivedPtr; }
    Wt::Dbo::ptr<Base> getBase() const { return basePtr; }

    template <class Action>
    void persist(Action &a)
    {
        Wt::Dbo::field(a, basePtr, "base");
        Wt::Dbo::belongsTo(
            a, 
            derivedPtr, 
            fieldName(),
            Wt::Dbo::OnDeleteCascade | Wt::Dbo::OnUpdateCascade
        );
    }

};


template <class Base, class Derived>
ConnectorTable<Base, Derived>::ConnectorTable(Wt::Dbo::ptr<Base> bPtr, Wt::Dbo::ptr<Derived> dPtr)
    : basePtr(bPtr), derivedPtr(dPtr)
{}

The Base Class

//b.h:
class BasePtr : public Wt::Dbo::Dbo<BasePtr>
{
public:
    BasePtr(bool derived = false);
    virtual ~BasePtr(){}

    static std::string refName() { return {"BasePtr"}; }

    virtual std::string getName() const;

    template <class Action>
    void persist(Action &a);

protected:
    bool has_derived;
};
//b.cpp:
BasePtr::BasePtr(bool derived)
{
    has_derived = derived;
}

std::string BasePtr::getName() const
{
    return "BasePtr";
}

template <class Action>
void BasePtr::persist(Action &a)
{
    Wt::Dbo::field(a, has_derived, "b_derived");
}

The Derived Class

//s.h
#include "t.h"

class SpecialPtr;

typedef ConnectorTable<BasePtr,SpecialPtr> BaseSpecialConnector;

class SpecialPtr : public BasePtr
{
public:
    SpecialPtr() : BasePtr(true) {}
    virtual ~SpecialPtr(){}

    static std::string refName() { return {"SpecialPtr"}; }

    virtual std::string getName() const { return "SpecialPtr"; }

    template <class Action>
    void persist(Action &a);

private:
    Wt::Dbo::weak_ptr<BaseSpecialConnector> baseConPtr;
    Wt::Dbo::ptr<BasePtr> basePtr;

};

DBO_EXTERN_TEMPLATES(Test::Dbo::BaseSpecialConnector)
DBO_EXTERN_TEMPLATES(Test::Dbo::SpecialPtr)


//s.cpp

DBO_INSTANTIATE_TEMPLATES(Test::Dbo::SpecialPtr)
DBO_INSTANTIATE_TEMPLATES(Test::Dbo::BaseSpecialConnector)

template <class Action>
void SpecialPtr::persist(Action &a)
{
    // // Adding this, crashes the App - Segfault
    // Wt::Dbo::hasOne(
    //     a, 
    //     baseConPtr,        
    //     BaseSpecialConnector::fieldName()
    // );
    Wt::Dbo::belongsTo(a, basePtr);
}

Mapping the Classes in Session

  session->mapClass<BasePtr>("Test_BasePtr");
  session->mapClass<SpecialPtr>("Test_SpecialPtr");
  auto mapClassName = 
      BasePtr::refName() 
      + "_" 
      + SpecialPtr::refName()
      +"_Connector";
      // Wt::WString::fromUTF8("{1}_{2}_Connector")
      //     .arg(BasePtr::refName())
      //     .arg(SpecialPtr::refName())
      //     .toUTF8();
  Wt::log("info") << "MapClasses" << ": Name(string): " << mapClassName;
  Wt::log("info") << "MapClasses" << ": Name(char*): " << mapClassName.c_str();
  session->mapClass<BaseSpecialConnector>(mapClassName.c_str()); 

Maybe there are some obvious flaws in the code that I did not see...
the mapClassName check seems to work now, but did give weird text or just two random values.

wt-4.8.0


Replies (2)

RE: Wt::Dbo -> "create table 'delete from xxx' and create table 'integer not null'" - Added by Christian Meyer over 1 year ago

Found the problem for 2:

mapClass does not seem to store the content of the char* as the tableName, but the Adress of the pointer.
Therefore, mapClass needs to be called with the spelled out name in qoutes -> mapClass<BaseSpecialConnector>("Test_BaseSpecialConnector");

    (1-2/2)