[odb-users] Loading persistent object using custom joins
Boris Kolpackov
boris at codesynthesis.com
Sun Mar 3 12:00:10 EST 2013
Hi Patrick,
Patrick Rotsaert <Patrick.Rotsaert at intoit.be> writes:
> I know joins can be done with views, but if I understand correctly,
> views contain only a subset of the objects involved.
More precisely, views can contain a subset or a full set of data
members from one or more objects.
> #pragma db object
> class employer
> {
> ...
>
> #pragma db id
> unsigned long id_;
>
> std::string name_;
> };
>
> #pragma db object
> class employee
> {
> ...
>
> #pragma db id
> unsigned long id_;
>
> std::string first_;
> std::string last_;
>
> unsigned short age_;
>
> shared_ptr<employer> employer_;
> };
>
> Suppose I'd like to query all employers that have employees under 30
> years of age.
In ODB you can reference data members from the pointed-to objects (one
level deep) in queries. So, if, for example, you wanted to find all the
employees that have "Example, Inc" as an employer, then you could do:
typedef odb::query<employee> query;
typedef odb::result<employer> result;
result r (db.query<employee> (query::empployer->name == "Example, Inc"));
Your query is a bit different, however. First of all, there is no "back"
pointer from employer to employees, but even if we added one, it would
have been a container and there is no support for using containers in
queries, yet.
> In SQL speak, that would be something like:
> SELECT DISTINCT employer.*
> FROM employee
> NATURAL JOIN employer
> WHERE employee.age < 30
>
> How can this be done, so I have an odb::result<employer> to work with?
The only way to achieve this that I can think of is to use a view to get
the list of ids of all the employers that have employees under 30. Then,
you can use these ids to load each employer:
#pragma db view object(employer) \
object(employee) \
query((?) + "GROUP BY" + employer::id_)
struct employers
{
#pragma db column(employer::id_)
unsigned long id;
};
typedef odb::query<employers> query;
typedef odb::result<employers> result;
result r (db.query<employers> (query::employee::age < 30));
for (const employers& es: r)
{
shared_ptr<employer> e (db.load<employers> (es.id));
...
}
Boris
More information about the odb-users
mailing list