Project

General

Profile

Feature #10930

Support Polymorphism with Dbo Hierarchy

Added by Christian Meyer 3 months ago. Updated 3 months ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
09/10/2022
Due date:
% Done:

0%

Estimated time:

Description

There have been questions about how to implement this in the Forum

https://redmine.emweb.be/boards/2/topics/18066
https://redmine.emweb.be/boards/2/topics/17642
https://redmine.emweb.be/boards/2/topics/298

I also would like to have the ability to inherit from a Dbo-Table-Class, save the base portion of data within that table and add another table for the derived portion of data.

At the same time, It would help to return a polymorphic pointer to the derived class, if the corresponding base-class was extracted from the db.

I did some thinking, and a lot of reading through the codebase, but a 1-1 relation is impossible without knowing the derived class in the base. At the moment.

What I'd like to propose is a relation schema that might be able to include those features, merely by expanding the types of relations...

This would enable the use of Base Dbo-Table-Classes by themselfes, as well as enable the reuse in other Dbo-Table-Classes, Data and all.

As this is purley theoretical and have not been able to test it, I hope I can convey my thoughts about a possible implementation well enough.

new Functions:
Wt::Dbo::baseClass(a); -> to be added in every Class that wants to enable Polymorphism
Wt::Dbo::extends<BaseClass>(a); -> to be added in Derived classes.
Derived from Multiple Dbo-Classes: add another extends().
Want to enable deriving from this: add baseClass()

In Effect:

  • Dbo::baseClass():
    • creates a table <tableName>_Base
  • Dbo::extends()
    • adds Fields and constraints to the extended _Base table
    • creates a table <tableName>_Derived
    • adds Fields and constraints for every extended <BaseClass> to _Derived table

The tables for the relations could look like this:

create table "<tableName>_Base" (
  "base_id" bigint not null,
  "derived_<derived_tablename>_id" bigint, /* add field and constraint for every derived class: */
  constraint "fk_<tablename>_<derived_tablename>_key1" foreign key ("base_<tablename>_id") references "<tablename>" ("id") on delete cascade,
  constraint "fk_<tablename>_<derived_tablename>_key2" foreign key ("derived_<derived_tablename>_id") references "<derived_tablename>" ("id") on delete cascade
  /* Not sure on the primary key definition here */
);

create table "<tableName>_Derived" (
  "derived_id" bigint not null,
  "base_<base_tablename>_id" bigint, /*<add field and constraint for every base class: */
  constraint "fk_<base_tablename>_<tablename>_key1" foreign key ("derived_<tablename>_id") references "<tablename>" ("id") on delete cascade,
  constraint "fk_<base_tablename>_<tablename>_key2" foreign key ("base_<base_tablename>_id") references "<base_tablename>" ("id") on delete cascade
  /* Not sure on the primary key definition here */
);

With an Example Structure like this:

class User
{
protected:
    std::string email;

public:
    template <class Action>
    void persist(Action &a)
    {
        Wt::Dbo::field(a, email, "email");
        Wt::Dbo::baseClass(a);
    }
};
class Customer : public User
{
protected:
    std::string address;

public:
    template <class Action>
    void persist(Action &a)
    {
        Wt::Dbo::field(a, address, "address");
        Wt::Dbo::extends<User>(a);
    }
};
class Manager : public User
{
protected:
    std::string department;

public:
    template <class Action>
    void persist(Action &a)
    {
        Wt::Dbo::field(a, department, "department");
        Wt::Dbo::extends<User>(a);
    }
};

The Tables could look like that:
Table: User_Base

base_id derived_Customer_id derived_Manager_id
2 1 null
3 null 1

Table: Customer_Derived

derived_id base_User_id
1 2

Table: Manager_Derived

derived_id base_User_id
1 3

Having those extra Tables should help to get all the data together.
I think that might be relatively "easy" to implement. Unfortunately I don't see where or how this might be needed in the Source.
And it would help to have an adaption for Dbo::ptr<C>::get() to return the polymorphic Element pointer.

Those tables should enable multiple parents and deriving over multiple steps as well, at least in theory.
Looking forward to a possible implementation, or some thoughts about how to do it differently.

Also available in: Atom PDF