Simple

The idea here is to make a simple (to code and to use) class to interface to sqlite3. Each of the examples creates a class called Xql3 as in "execute SQL with sqlite3" ...

v1

The first example, v1, uses the "convenience" function sqlite3_get_table that keeps the entire results in memory. The class then copies the values out of the first memory location to put them into a standard C++ container (ie: from a char **_result to a std::vector). If the return set is large, this would not be the best technique due to the amount of copying.

v2

The second example, v2, uses sqlite3_prepare_v2 plus sqlite3_step since this apparently is the new and preferred method of accessing the sqlite3 system. So although the legacy exec did just this, there were a few other legacy dependencies and if those were changed, it would probably break some code. Therefore, this class will use the legacy "exec" with a virtual callback that if not overridden, simply places the values into a standard container.

simple_v2a uses the default Xql3 callback_out which puts the header and result data information into the std::vector of strings in the Xql3 class. simple_v2b has a new embedded class, Xql4, that simply extends Xql3 and then overrides the callback_out method. This callback puts header and data results into Xql4 class vector of string variables "h" and "d" -- respectively. The point of this is that Xql4 didn't have to put the values into a vector, but could have done something else. The different variables were used to make sure the default variables were not being used. Finally, the technique of a static callback being passed a void* pointer only to static_cast it to the current object type in order to be able to call a non-static method is just plain fugly.

This version of the class handles multi-part SQL statements because the legacy exec call handles multi-part SQL statements. Sure, it's probably also possible to register a different callback via the standard sqlite3 API, but this was only meant to be a simple test.

v3

The third example, v3, has an Xql3 class that (re)implements "exec" that is similar to the legacy exec, but not exactly the same. This exec will call a virtual callback that if not overridden, simply returns (ie: returned results are ignored).

This version of the class handles multi-part SQL statements.