Boost logo

Boost :

Subject: Re: [boost] sqlpp11, 3rd iteration
From: Roland Bock (rbock_at_[hidden])
Date: 2014-08-18 17:55:29


On 2014-08-18 22:43, Adam Wulkiewicz wrote:
> Roland Bock wrote:
>> I was referring to what some sql libraries do, e.g. Mysql's C interface:
>> They take pointers to some memory and then write result fields to those
>> memory blocks, see for instance
>> http://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-bind-result.html
>>
>> I don't know if that would be legal to do with the value in optional.
> If some object containing value (corresponding to the data stored in
> DB) is created at some point, it may be stored in optional.
>
> I'm guessing that the problem exists because select is lazily
> executed. C++ objects corresponding to the data aren't created (e.g.
> std::string, int, float, etc.). Instead some pointers to buffers are
> kept (in sqlpp::result_field_t?). And C++ objects are created and
> returned later from value() method or conversion operators each time
> one of them is called. Is that right?
Not quite. Lets look at integral.h and the partial specialization of

template<typename Db, typename FieldSpec>
result_field_t<integral, Db, FieldSpec>
{...};

Now, this contains an int64_t value. The address of this value is given
to the backend in the method bind() when fetching each result row (no
laziness here). It seems to me that I cannot replace int64_t by
boost::optional<int64_t>. For instance, I cannot call get() to obtain
the address of the value if the optional is not initialized (I would run
into an assert).

> But AFAIU if the C++ objects were created along with the
> representation of a row, the results could be stored as optionals. Or
> am I missing something?
Yes the values are set when the row is fetched. The objects are re-used
for each row. And the backend is given pointers to write the value into
as explained above.

But while writing this, I just realized: I could do is offer a
conversion operator for std::optional<int64_t>, of course. Thus, given a
row with a column `a` which can be NULL, you would then have

std::optional<int64_t> a1 = row.a; // OK
int64_t a2 = row.a; // compile failure

>
> I saw that there are optional-like wrappers of values, e.g.
> sqlpp::text. They're close to optionals since they're storing a value
> and some flag. What are they used for?
These are the result fields as described above. I guess the key for
understanding their mechanics is the bind function. This gets called
when a row is fetched: It hands over the address of the field's value to
the database backend where it will be used in methods like
mysql-stmt-bind-result for instance.

I am offering the optional-like interface since I cannot use optional to
actually store the field's value, if I understand the semantics of
optional correctly.

But as mentioned above, I probably could offer a converter to optional.
>
> Are you using tabs? The code doesn't seem to look right on GitHub.

Yes, but actually, I think the worse problem is that vim indents
template code a bit weirdly. Its not so bad with a tab width of two, but
I'll have to take care of that sometime soon :-)

Regards,

Roland


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