[odb-users] one-to-many relationship question

Boris Kolpackov boris at codesynthesis.com
Wed Aug 13 07:50:28 EDT 2014


Hi Lidia,

Lidia Kalinovsky <lidia at lemur-soft.com> writes:

> #pragma db...
> class A
> {
>      bool hidden;
> };
> 
> #pragma db...
> class B
> {
>     bool hidden;
> 
>     #pragma db unordered
>     std::vector<A>  manyA;
> }
> 
> to load objects of B, i use
> 
> typedef odb::query<T> queryT;
> queryT q;
> if (!fullLoading)
> q = queryT(queryT::hidden != true );
> 
> typename odb::core::result<T>  r (m_DB->query<T>(q,true));
> 
> This way i have only Bs with hidden=0.
> 
> Is it possible to have some condition for loaded A's objects inside manyA
> vector inside pragma (means, at compilation) ?

No, and I doubt we will support something like this. Seems very
inflexible.


> inside dynamic query ?

Also not, but this is something on our TODO list. That is, support for
containers in queries.

What you can do as a workaround in the meantime is this (I am using
raw pointers below but you will want to replace them with smart
pointers):

1. Add the "back" pointer to A:

class B;

#pragma db...
class A
{
  bool hidden;

  #pragma db inverse(manyA)
  odb::lazy_ptr<B> oneB; // Use the lazy (and weak) pointer corresponding
                         // to the A's object pointer.
};

This doesn't cost anything on the database side. If you want, you can
also avoid loading it completely on the C++ side (see lazy-loaded 
sections).

2. Re-implement your query in terms of querying for A, not for B:

typedef odb::query<A> queryA;
typedef odb::result<A> resultA;

queryA q (!queryA::hidden && !queryA::oneB->hidden)

resultA r (db.query<A> (q));

// Create an object cache so that Bs points to As that we have already
// loaded.
//
odb::session s;

std::setM<B*> bs;

for (resultA::iterator i (r.begin ()); i != r.end (); ++i)
{
  bs.insert (i->oneB.load ());
}

// bs now contains all the Bs that are not hidden and only containing
// non-hidden As.

Boris



More information about the odb-users mailing list