7. Important Underlying C API Limitations

Since MySQL++ is built on top of the MySQL C API (libmysqlclient), it shares all of its limitations. The following points out some of these limitations that frequently bite newbies. Some of these may be papered over at the MySQL++ layer in future releases, but it's best to write your program as if they were permanent fixtures of the universe.

  1. Only one active query per connection. This one bites MySQL++ newbies most often in multithreaded programs. If the program has only one Connection object and each thread gets their Query objects from it, it's inevitable that one of those query objects will try to execute while another query is already running on that single connection. The safest course is to have a separate Connection object per thread, and for your code to get Query objects in a thread only from that thread's Connection object. Alternately, you can confine MySQL database access to a single thread.

  2. You must consume all rows from a query before you can start a new query. This one bites MySQL++ newbies most often when they try code like this:

    Connection c(...);
    Query q = c.query();
    Result r1 = q.use("select garbage from plink where foobie='tamagotchi'");
    Result r2 = q.use("select blah from bonk where bletch='smurf'");

    This will fail because a "use" query consumes rows only on demand, so the MySQL server is still keeping information around about the first query when the second one comes in on the connection. When you try the second query, MySQL++ will throw an exception containing an obscure MySQL C API error message about "commands out of sync".

    This is not the only situation where this can happen, but all of these issues boil down to the fact that MySQL requires that certain operations complete before you can start a new one.

  3. The Result object must outlive the use of any Row objects it returns. This is because the Row objects refer back to the Result object that created them for certain data. (Field names, for example.) MySQL does this for efficiency, because there is some information about a row that is the same for all rows in a result set. We could avoid this in MySQL++ by making redundant copies of this data for each row, but that would be quite wasteful.

    Beware of some of the more obscure ways this can happen. For example:

    Connection c(...);
    Query q = c.query();
    Result res = q.store("...");
    Row row = res.at(0);
    res = q.store("...");

    At this point, the row variable's contents are likely no longer usable. The program may run, but the row object will use data (field names, etc.) from the second query, not the first.