Boost logo

Boost :

Subject: Re: [boost] quince: queries in C++ expressions
From: Roland Bock (rbock_at_[hidden])
Date: 2014-07-17 12:26:33


On 2014-07-17 15:34, Michael Shepanski wrote:
> On 17/07/2014 10:48 PM, Roland Bock wrote:
>> On 2014-07-17 13:11, Michael Shepanski wrote:
>>> Every query produces values of its "value type", which can be any type
>>> in this taxonomy:
>>> http://quince-lib.com/mapped_data_types.html#mapped_data_types.definition_taxonomy
>>>
>>> . It is common for a query's value type to be the same as a table's
>>> value type, but this is not the case for queries that use join() or
>>> select().
>> Shouldn't collections be mentioned on that page, too?
>
> I'm not sure I understand. Do you mean STL containers? Then no,
> these are not mapped types (except for the special cases std::string
> and std::vector<uint8_t>). You can't have a table<std::list<float>>.
No, sorry for the confusion, I meant the usage of collector classes.
>
>>> Sure. Quince's select() is analogous to supplying an SQL "select
>>> list". (I say "analogous", not identical, because here again we work
>>> at the level of C++ types, without regard to whether they are
>>> single-column or multi-column.)
>>>
>>> So it's:
>>>
>>> struct something {
>>> metadata meta; // metadata is some mapped type defined
>>> elsewhere
>>> vector<uint8_t> blob;
>>> string other;
>>> };
>>> QUINCE_MAP_CLASS(something, (meta)(blob)(other))
>>>
>>> extern table<something> somethings;
>>>
>>> [...]
>> Hmm. I guess my question was unclear or I misunderstood you answer.
>>
>> I was thinking something like
>>
>> auto query = somethings.select(somethings->meta)
>> if (userWantsBlob)
>> query.add_to_select_list(somethings-blob);
>> for(const auto& row : query)
>> {
>> if (userWantsBlob)
>> {
>> //somehow access blob here
>> }
>> }
>
> Ah, I see. No, on two counts.

> [...]
>
> Iiuc you are starting with a query that gets something narrow, and
> then using add_to_select_list() to widen it. With quince, you would
> work in the opposite direction: start with a query that gets all the
> information anyone needs (or just start with the table itself), and
> use select(...) to make narrower queries as needed. Making new queries
> in this way is a cheap operation.
>
> Would that cause you any problems? (I'm not sure what you mean by
> "Multiplying the code".)

Say I have two conditions, userWantsBlob and userWantsOther. I would
want to have everything in one loop.

In sqlpp11 I could say something like:

auto query = dynamic_select(db, t.meta)...;
if (userWantsBlob)
   query.add_column(t.blob);
if (userWantsOther)
   query.add_column(t.other);

for (const auto& row : db(query))
{
   std::cout << t.meta << '\n';
   if (userWantsBlob)
     std::cout << t.at("blob") << '\n';
   if (userWantsOther)
     std::cout << t.at("other") << '\n';
};

How would you do that in quince?

>> If you knew the database type while constructing the query, you could d
>> those tests during construction. It probably wouldn't even be that hard
>> with a similar mechanism as used in sqlpp11 (easy for me to say, still
>> not knowing really much about your code).
>
> As quince builds a query it always "knows" the database type in a
> dynamic sense, but not in a static sense.

OK

Cheers,

Roland


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk