|
Boost : |
Subject: Re: [boost] sqlpp11, 3rd iteration
From: Adam Wulkiewicz (adam.wulkiewicz_at_[hidden])
Date: 2014-08-19 08:03:57
Roland Bock wrote:
> On 2014-08-19 09:39, Gavin Lambert wrote:
>>
>> I think we've had a terminology clash. By "backend" I thought you
>> meant "the sqlpp11 class that knows how to talk to the native driver",
>> not the native driver itself. Of course the native driver probably
>> won't know how to drive an optional, nor should it be expected to.
>>
>> There are several layers, I assume:
>>
>> 1. User code
>> 2. sqlpp11 database-independent frontend
>> 3. sqlpp11 database-specific connector
>> 4. native database library
> Perfectly correct :-)
>> Between layers 3 & 4 obviously you have to use whatever the native
>> library supports, which is unlikely to be boost::optional (but still
>> possible in some cases). So you might have to provide a raw int64_t
>> pointer to the database up front, and translate from a int64_t pointer
>> and an "is this null" method call (or a bool*) to a boost::optional
>> when it calls you back saying the complete row is ready. (I'm
>> assuming this is asynchronous, otherwise it's easier.)
> As of today, it is synchronous.
>
>> But between layers 1 & 2 and 2 & 3 you'd only have boost::optionals.
> I can see the reasoning for 1&2. And I understand that it can be done
> with 2&3 of course, but I am not sure there is a benefit.
As I see it, the benefit would be the use of the standard-approved way
of handling values that could be invalid instead of using a
library-specific handling.
But I think optionals wouldn't be safe. Correct me if I'm wrong. If
optionals were used without a check for validity and the unexpected NULL
value was set in the DB (maybe by mistake), it could result in
segmentation fault. Of course assuming that the macro BOOST_ASSERT()
wouldn't be expanded to some exception throw. This could lead to some
security vulnerabilities in apps using this library.
>>>> Otherwise how does the backend return a NULL value?
>>> The backend is called with two parameters, one pointer for the value,
>>> the other for the is_null information.
>> So once you know that those have been filled in, you can translate it
>> into a boost::optional to be returned to the higher layer. It does
>> mean the value has to be copied (unless boost::optional has had move
>> assignment added since I last looked), but you'd be doing that anyway
>> for std::string so this doesn't seem any worse than that.
> I can see that for the 1&2 interface, but not necessarily for 2&3 since
> then I would have two copies of the string: once when obtaining the
> value from 4 and copying it into 2&3, one for copying it from 2->1.
The above assuming that RVO can't be applied, rvalue refs aren't
supported by the compiler, move semantics isn't supported by
boost::optional and swap() isn't explicitly used.
> As of now, I create a temporary string when the value is requested in
> the 1&2 interface.
So there always must be some temporary object. You could directly create
boost::optional<std::string> using InPlaceFactory
(http://www.boost.org/doc/libs/1_56_0/libs/optional/doc/html/boost_optional/in_place_factories.html)
or as I mentioned earlier create default-constructed string within
optional and assign to it (assuming it's a valid way of modifying an
optional).
But as I wrote above, I'm not sure if supporting "raw" optionals would
be safe.
Regards,
Adam
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk