Some time ago now, I've written a command-line tool, that connects to MySQL, and through a series of commands, does all sorts of good stuff. It was originally intended to be used by myself and, perhaps, by other developers.
Now, however, it's likely that non-devs will at some point be using this same tool, or at least a part of it. Given that many people sort of get nervous the moment you speak the forbidden words of death terminal or CLI, I've set about writing a rudimentary GUI using GTK+.
For obvious reasons, I kept things nicely separated, and only made those functions that the GUI tool needs to support visible.
But here, I ran into trouble. My code uses an unknown number of prepared statements. So far, I have been passing those around from function to function. I don't want to do this in my GUI code, of course. (I know, it's bad enough that I am doing this in the CLI version, and I do want to re-write chunks of that code, too).
So far, I've come up with 3 ways of fixing this. Effectively, I find myself having to write a wrapper-API around those bits and bolts of the MySQL API that need to be exposed. But which is the best? What are the down/up-sides of each approach? Am I missing the obvious fourth approach?
Here are the options I'm currently considering:
- write a simple header with typedefs, and some macro's (
MAKE_STMT("My query")
sort of things, and prefix all types relating to the MySQL API withDB_
or something.
I don't fancy this, simple because the GTK+ API is quite similar, and it tends to make code look, to my eye at least, a tad messy. It also doesn't really solve the issue, but rather masks it. - Use a global hash table, or simple array in the mysql code, and allocate memory for each prepared statement I need, and return its offset/hash. I can then pass that around in my CLI/GUI code, and use a function like
execute_stmt(int offset, struct param_list *params);
which can then use theoffset
.
This is the approach that I'm likely going to use ATM, simply because this has to be the most straightforward way to keep db-related data out of the front-end code - use
void *
in front-end code and macro's that cast & call the right functions at the right time. I'd hate to use this approach, but at least I can check forNULL
pointers, and not leave error reporting/handling to the DB code, which doesn't know if the program is running in CLI or GUI mode (and I'd like to handle errors differently in both cases). - Perhaps a last alternative, and this is what I'm currently doing, given I've not set about reworking the CLI code, is using separate .h files. Possibly expanding this further into 3 .c files: 1 for common functions, 1 for CLI specific code, and 1 for GUI code.
I'm probably bound to end up with something like this, but then the question remains:
what is the best way to keep MySQL-related code as far away as possible from the UI code?