Hi Vadim,
Let me clarify some of my comments.

> RFdA> My needs aren't related to what went wrong during execution but what
> RFdA> happened while building the query.
>
> VZ>But isn't this mostly important when things do go wrong?


> I meant that my goal was keeping track of parameter values of successfully
executed queries.


> RFdA> In my case, soci's exception messages are handled externally to soci
> RFdA> but I understand it can be done internally.
>
> Explaining better the last part: the idea was modifying soci to catch
internal exceptions logging their contents and finally rethrowing them to
applications.
However, I don't think this is a must-have feature.


> VZ> I'm not sure to understand this but maybe I hadn't explained my problem
> VZ>well enough to begin with, so let me try to do it again. We're handling
> VZ>SOCI exceptions in our own code, i.e. externally, too. But the problem
> is
> VZ>that we don't have the information about the values of the parameters
> when
> VZ>we catch them.
>

I see your point. A member function get_last_parameters would be very
useful in this case.

RFdA> The more important thing for me was knowing the values of the query
> RFdA> parameters for each execution.
>
> VZ>Yes, this is exactly what I want too. The difference seems to be that
> you

VZ>want to log them all while I just need them for the last query.
>
> So let's find away to have both.


> RFdA> > >         unique constraint violation on foo.bar while executing
> RFdA> > >         "insert into foo(bar) values(:bar)" with "bar"='baz'
>
> VZ> Yes, it's simple to generate and quite clear. But it can result in very
> VZ>long and hence rather unreadable messages for real-life queries.
>
> One way to avoid such long messages is imposing an optional size limit for
each variable.
Something like the first 20 chars is enough for all numeric types and
sufficient for strings.


> RFdA> Mixing the values of the query parameters with the literal values in
> the
> RFdA> query may lead to confusion about the responsibility of each value.
>
> VZ> I admit that I didn't think of this because I really don't care whether
> VZ>the parameter was specified literally or as a prepared statement
> parameter
> VZ>(if only because I always do the latter anyhow). Why is it important to
> VZ>distinguish between the two cases?
>
> Because I need to know if the source of an error was the development
(literals) or the usage (parameters) of the query.

>
> RFdA> I don't think saving parameter values makes much sense.
> RFdA> The query is saved because the statement is prepared with such query.
> RFdA> In the case of parameters, they're just references to variables so
> what
> RFdA> matters is their values at the time of the execution.
>
> VZ> I wanted to save (references to?) the parameter values to avoid logging
> VZ>them unconditionally but to be able to do it later if the query fails.
>

I might have a solution according to this logic.


> VZ>Again, this might be not a big deal but suppose you're working with
> VZ>(potentially several) long strings, copying them to the log buffer on
> each
> VZ>query execution could be potentially bothersome.
>
> Not longer than the query itself in most cases.

>
> VZ>I'd like to also have such access to the last
> VZ>query parameters and, again, I'd like it to be enabled by default.
>

The potential solution I have in my head allow that.

>
> VZ> Yes, but logging all values of a vector can definitely overwhelm the
> user
> VZ>trying to understand the error message. So while your approach is fine
> for
> VZ>the extensive logging, I don't think it's the right thing to do for the
> VZ>error reporting.
>
> You have a point, let's make it optional.

>
> VZ> Anyhow, once again, all this are details. My real problem with the
> current
> VZ>patch is just the code duplication among the backends.
>
> I agree this is the most important issue (logging code in the backend).

Now let's talk about a potential solution.

1) Backends may or may not participate in the log generation.
- I suggest the inclusion of virtual functions in *_use_type_backend
classes.
- Returning [std::string] has a copying cost. I suggest returning [const
char*/std::size_t]
- These functions return the string representation of each parameter.
- vector functions should include a index parameter [std::size_t].
- The default implementation is no-op and indicates that the backend can't
participate [return NULL/0].
  (does this hurt the current pure virtual interface of *_use_type_backend
classes?)
  (if it does, is a backend_conversion class a better idea?)
- If implemented, the current values will be available only after calling
pre_use.
- This is an optimization and the conversion is unconditional because uses
the same the backed already provides.

2) use_type_base is the interface from where the core obtain the string
representation of the parameter values.
- This class gets pure virtual functions with the same signature of the
vector backend ones.
- The implementation in standard_use_type only accepts index of 0.
- Conversion to string happens only if the member functions are called.
- Conversion uses the backend provided conversion if present.
- Conversion probably will be based on [std::ostringstream].

3) session class controls the parameter logging/reporting behavior.
- A new member function [set_log_params_length(std::size_t len,
bool expand)] enables parameter logging for any value greater than zero.
Second parameter means expand vectors.
- A new member function [set_last_params_length(std::size_t len, bool
expand)] enables parameter reporting for any value greater than zero.
Second parameter means expand vectors.
- A new member function pair [set_last_parameters/get_last_parameters] is
added to report parameter values.

4) statement_impl is the responsible for the concatenation of the parameter
values. The work happens in pre_use member function.
- It appends the parameter values obtained
from standard_use_type/vector_use_type in a [std::ostringstream] if
reporting is enabled (len ! = 0).
- it writes the parameter values to the log stream if parameter logging is
enabled (len ! = 0).
- It only iterates through vector_use_type values if expansion is enabled
for either reporting or logging (expand = true).
- [session::set_last_parameter] is called at the end passing the contents
of parameters' stringstream.

I'm planning to work on that on Sunday and everyone interested in such
feature is invited to give a feedback.
Questions are welcome too.

Regards,
Ricardo Andrade
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter
_______________________________________________
soci-devel mailing list
soci-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/soci-devel

Reply via email to