[odb-users] One-to-many bidirectional relationship without intermediary table

Boris Kolpackov boris at codesynthesis.com
Mon Oct 14 10:11:45 EDT 2019


Mocnik Marko <marko.mocnik at lisec.com> writes:

> I'm trying to map two tables of the form:
> 
> CREATE TABLE testi
> (
>     asdf integer NOT NULL,
>     description varchar(500),
>     CONSTRAINT testi_pkey PRIMARY KEY (asdf)
> )
> 
> CREATE TABLE testi2
> (
>     asdf integer NOT NULL,
>     qwer integer NOT NULL,
>     moredata varchar(100),
>     CONSTRAINT pk_testi2 PRIMARY KEY (asdf, qwer),
>     CONSTRAINT fk_t2_t FOREIGN KEY (asdf) REFERENCES testi (asdf)
> )
> 
> I know that's not pretty, but we have some legacy tables that have
> this kind of relationship. Is there any way to map this and if so, how?

This is actually a pretty standard one-to-many mapping except for the
foreign key (testi2.asdf) also being part of the primary key, which is
something we don't yet support in ODB out of the box.

I was able to get the identical mapping using these classes:

#pragma db object
struct testi
{
  #pragma db id
  int asdf;
};

#pragma db object
struct testi2
{
  #pragma db value
  struct id_type
  {
    #pragma db points_to(testi)
    int asdf;
    int qwer;
  };

  #pragma db id column("")
  id_type id;
};

The generated database schema (PostgreSQL version):

CREATE TABLE "testi" (
  "asdf" INTEGER NOT NULL PRIMARY KEY);

CREATE TABLE "testi2" (
  "asdf" INTEGER NOT NULL,
  "qwer" INTEGER NOT NULL,
  PRIMARY KEY ("asdf",
               "qwer"),
  CONSTRAINT "asdf_fk"
    FOREIGN KEY ("asdf")
    REFERENCES "testi" ("asdf")
    INITIALLY DEFERRED);

With virtual data members and a bit of effort you should be able
to change testi2::id_type::asdf to a pointer, something along these
lines (a sketch):

#pragma db object
struct testi2
{
  #pragma db transient
  testi* asdf;

  #pragma db transient
  int qwer;

  #pragma db value
  struct id_type
  {
    #pragma db points_to(testi)
    int asdf;
    int qwer;
  };

  #pragma db member(id) virtual(id_type) id column("") \
    get (...) \
    set (...)
};

More information on virtual data members:

https://codesynthesis.com/products/odb/doc/manual.xhtml#14.4.13


> The only way I could manage to get a mapping to compile produced a
> stack overflow when running a query...

It's hard to say what's wrong without seeing the code.


> Also, is it possible to use two separate headers for testi and testi2?
> I could not get this to compile because in one of the files I would
> need to use a forward declaration instead of a direct include and
> then the compiler would not find the appropriate template specializations.

Maybe this will help:

https://codesynthesis.com/products/odb/doc/manual.xhtml#6.3



More information about the odb-users mailing list