[odb-users] Loading persistent object using custom joins
Patrick Rotsaert
Patrick.Rotsaert at intoit.be
Sun Mar 3 12:22:15 EST 2013
Hi Boris,
thanks for the swift answer. I think I'll manage it like that.
Any chance there will be a future possibility to load objects directly from arbitrary SQL queries (select tablename.* from...), perhaps only specifying the part starting from 'from...' ?
The built-in query language covers most of my use cases, but it's for that occasional special situation that I think that might be really useful.
Pat
On 3-mrt.-2013, at 18:00, Boris Kolpackov <boris at codesynthesis.com> wrote:
> 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