On 4/12/2011 4:45 PM, Dan Cook (dancook) wrote:
>>> http://dev.mysql.com/doc/refman/5.5/en/null-mysql-store-result.html
>
> What kind of workaround are you suggesting?
That page is pretty much a functional spec for a MySQL++ patch. It's
saying that Query::storein_sequence() shouldn't blindly assume the
underlying C API library will never somehow barf and therefore return
bogus results.
Try this patch:
Index: lib/query.cpp
===================================================================
--- lib/query.cpp (revision 2683)
+++ lib/query.cpp (working copy)
@@ -476,6 +476,13 @@
}
+bool
+Query::result_empty()
+{
+ return conn_->driver()->result_empty();
+}
+
+
StoreQueryResult
Query::store()
{
Index: lib/query.h
===================================================================
--- lib/query.h (revision 2683)
+++ lib/query.h (working copy)
@@ -274,6 +274,11 @@
/// or the stream interface.)
void reset();
+ /// \brief Returns true if the most recent result set was empty
+ ///
+ /// Wraps DBDriver::result_empty()
+ bool result_empty();
+
/// \brief Get built query as a C++ string
std::string str() { return str(template_defaults); }
@@ -748,17 +753,32 @@
template <class Sequence>
void storein_sequence(Sequence& con, const SQLTypeAdapter& s)
{
- UseQueryResult result = use(s);
- while (1) {
- MYSQL_ROW d = result.fetch_raw_row();
- if (!d)
- break;
- Row row(d, &result, result.fetch_lengths(),
- throw_exceptions());
- if (!row)
- break;
- con.push_back(typename Sequence::value_type(row));
+ if (UseQueryResult result = use(s)) {
+ while (1) {
+ MYSQL_ROW d = result.fetch_raw_row();
+ if (!d)
+ break;
+ Row row(d, &result, result.fetch_lengths(),
+ throw_exceptions());
+ if (!row)
+ break;
+ con.push_back(typename Sequence::value_type(row));
+ }
}
+ else if (!result_empty()) {
+ // Underlying MySQL C API returned an empty result for this
+ // query, but it also says it should have returned
+ // something. Reasons it can do that are given here:
+ //
http://dev.mysql.com/doc/refman/5.5/en/null-mysql-store-result.html
+ // Regardless, it means the C library barfed, so we can't
+ // just return an empty result set.
+ copacetic_ = false;
+ if (throw_exceptions()) {
+ throw UseQueryError("Bogus empty result");
+ }
+ }
+ // else, it was *supposed* to return nothing, because query was
+ // an INSERT, CREATE, etc. sort. So, leave con untouched.
}
/// \brief Execute template query using given parameters, storing
Be careful, my mailer wrapped the URL in the big comment above. Fix it
before applying the patch.
I don't see a way to distinguish the "malloc() returned 0" case, but if
that's happening, installing this patch will cause your program to start
crashing under the same conditions when *its* memory allocations fail
instead.
If that fixes your symptom, please let me know, as I haven't checked
this into svn. It is certainly incomplete, if for no other reason than
because it doesn't fix Query::storein_set() as well.
I also wonder whether, given the potential circumstances for this
problem to crop up, if Query::result_empty() should have additional
checks on conn_ and conn->driver().