Jul 19, 2014
Toolkit, Part II
Written by Katie Gomez
I want to show you the easy way to read results from MySQL in C++. But, we’re not ready yet. In a previous article I showed you some of the basic tools that we reuse in a lot of places. Before we get to the MySQL code, I need to show you more of these basic tools.
Have you noticed a theme here? Good programming involves:
- Finding the easiest way to do things.
- And reusing a lot of the work you’ve already done.
A lot of my MySQL code is based on the way I use MySQL in PHP. So it shouldn’t be surprising that I use a smart pointer class in the C++ version. Now you can pass around the result from a MySQL query without worrying about memory allocation. The memory will automatically be released when we are done with it, no sooner, no later. That’s a big step making C++ easier to use, and more like PHP.
This article includes the code for my RefCount class. I won’t discuss the details. This is a textbook exercise that you should have seen in school. As I mentioned in a previous article, I actually have multiple versions of this class. This version is not thread safe. It doesn’t have to be. The underlying MySQL result object is not thread safe. A version of this class is present in the newest versions of C++. I’ve been using my library since long before it became standard. I see no reason to change (and re-test!) a lot of working code.
I’m including the code for RefCount so the rest of the code I present will compile. I won’t be offended if you use the new, standard smart pointers in your own code.
The other big thing that I need is a way to convert strings into integers and floating point numbers. The default way that MySQL works is to send everything as a string. There are alternatives, but these have their plusses and minuses. My MySQL classes are based on the most common case, and can easily be used in a lot of places.
Of course, C comes with code that converts strings to numbers. But that code is very hard to use. The library I’m showing you is a wrapper around the standard C code.
I’ve actually included several versions of my string to number conversion code. The first thing to notice is that most of these use a default. The user provides a string and a default value. If the string is not a valid number, we return the default value, rather than reporting an error.
This is another common theme in my code. In a previous article I showed how to read from a map, and return a default item if the requested item was not found. One nice thing about default values is that they flow from one decision to the next. If you look up an item in a map, and you convert that item from a string to a number, either step could fail. Do you really care which step failed? Perhaps sometimes you do, but that’s not the common case. Look up the value and return “” if it doesn’t exist. Convert the value to a number, and return -1 if it’s not a value number. You will get -1 if either case fails.
This will become more important as the code gets more complicated. There are more and more places where a failure could occur. Usually you don’t care about the details. Either everything worked or something failed. Those are the only two interesting cases.
I offer a version of the conversion code which will throw a specific exception on failure. That was helpful in one very specific place in my code. It won’t be used in the MySQL code.
Another option in the code is whether you want to use char * or std::string to represent a string. The bulk of my code uses std::string exclusively. I added the char * version just for the MySQL code. The MySQL API gives me a char *, and the C conversion routines read a char *. It seemed wasteful to create a temporary object of a different type.
My standard library also includes two special classes, NoCopy and NoAssign. If you inherit from NoCopy, C++ will not automatically create the copy constructor. If you inherit from NoAssign, C++ will not automatically create the assignment operator.
These are useful in a lot of places. But they work especially well in combination with the smart pointers. You don’t want to copy or assign a MySQL result. These are opaque pointers. MySQL doesn’t give you an API to copy their data. Instead, you just want to copy and assign the smart pointers to the data. If you try to copy or overwrite the actual data, the compiler will give you an error.
As with the smart pointers, the newest C++ standard includes something similar. But I’ve had these classes for years, and I’m not going to rewrite (and re-test!) a lot of working code.