Niels Horn's Blog
Random thoughts, tips & tricks about Slackware-Linux, Lego and Star WarsGetting mysqlcc to build with newer gcc compilers and mysql headers
June 17th, 2010 by Niels Horn in Patches, gcc, mysqlcc
mysqlcc revisited
I used to use MySQL Control Center ('mysqlcc') quite a lot until a few years ago, when I switched to phpMyAdmin.
The biggest advantage of phpMyAdmin is that it is actively maintained, while mysqlcc has not seen updates for almost three years.
mysqlcc's interface also had a bit of an "old-fashioned" look, as it is still based on the Qt3 library (known from KDE3).
Anyway, these days I took a second look at it, because of a question about building it on Slackware 13.1 on the SlackBuilds mailing list.
My first reaction was like "Hey, try something more modern", but on second thoughts I decided to give it a try and examine the source code and the build-time error messages from gcc.
The error messages
Without any modification, gcc throws several messages at you like this:
src/main.cpp:93: error: 'gptr' was not declared in this scope
So I took a look at main.cpp and noticed that the lines causing the error message are part of a structure of 'my_option' lines:
static struct my_option my_long_options[] =
The lines that give the error are:
{"connect_timeout", OPT_CONNECT_TIMEOUT, "", (gptr*) &opt_connect_timeout, (gptr*) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, 0, 1}, {"select_limit", OPT_SELECT_LIMIT, "", (gptr*) &select_limit, (gptr*) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ~0L, 0, 1, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "", (gptr*) &my_net_buffer_length, (gptr*) &my_net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 512*1024*1024L, 0, 1024, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "", (gptr*) &my_max_allowed_packet, (gptr*) &my_max_allowed_packet, 0, GET_ULONG, REQUIRED_ARG, 16 *1024L*1024L, 4096, 512*1024L*1024L, 0, 1024, 0}, {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE.", (gptr*) &opt_local_infile, (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"max_join_size", OPT_MAX_JOIN_SIZE, "", (gptr*) &max_join_size, (gptr*) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ~0L, 0, 1, 0},
These errors are caused by the newer versions of MySQL, where mysql.h does not define the type of gptr any longer.
The next logical step was to check the definition of 'my_option' and see what types were expected here.
'my_option' is a structure defined in <my_getopt.h>, included in main.cpp.
In previous versions of MySQL this was defined as:
struct my_option { const char *name; /* Name of the option */ int id; /* unique id or short option */ const char *comment; /* option comment, for autom. --help */ gptr *value; /* The variable value */ gptr *u_max_value; /* The user def. max variable value */ const char **str_values; /* Pointer to possible values */ ulong var_type; enum get_opt_arg_type arg_type; longlong def_value; /* Default value */ longlong min_value; /* Min allowed value */ longlong max_value; /* Max allowed value */ longlong sub_size; /* Subtract this from given value */ long block_size; /* Value should be a mult. of this */ int app_type; /* To be used by an application */ };
But in newer versions of MySQL it is defined as:
struct my_option { const char *name; /* Name of the option */ int id; /* unique id or short option */ const char *comment; /* option comment, for autom. --help */ uchar **value; /* The variable value */ uchar **u_max_value; /* The user def. max variable value */ struct st_typelib *typelib; /* Pointer to possible values */ ulong var_type; enum get_opt_arg_type arg_type; longlong def_value; /* Default value */ longlong min_value; /* Min allowed value */ longlong max_value; /* Max allowed value */ longlong sub_size; /* Subtract this from given value */ long block_size; /* Value should be a mult. of this */ void *app_type; /* To be used by an application */ };
So we find that:
gptr*
has been replaced byuchar**
The solution was to change the (gptr*) casts in main.cpp to (uchar**).
After the change, trying to compile mysqlcc again, the next error jumped at me:
src/main.cpp:158: warning: deprecated conversion from string constant to 'char*'
This one was simple and caused by the new gcc compiler… Just changed line 158 from:
add_argument(id, "");
to
add_argument(id, (char*)"");
But, trying once more to compile mysqlcc, we get one more error message:
src/main.cpp:118: error: invalid conversion from 'int' to 'void*'
Now, line 118 is actually the end of the structure of my_option lines, so the error is hidden inside.
After re-reading the new and old definitions of my_option I found that:
app_type
was defined asint
and is now defined asvoid*
Knowing this, the error message makes sense, and there is one line (93-95) in the structure that uses a non-zero value. Changing that line from:
{"connect_timeout", OPT_CONNECT_TIMEOUT, "", (gptr*) &opt_connect_timeout, (gptr*) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, 0, 1},
to:
{"connect_timeout", OPT_CONNECT_TIMEOUT, "", (uchar**) &opt_connect_timeout, (uchar**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, 0, (void*)1},
solved this last error and now mysqlcc built without problems
The result
And yes, the result worked fine as can be seen here:
The patches
Instead of applying all the changes manually, you can use the following file to patch your sources:
--- mysqlcc-0.9.8-src/src/main.cpp 2006-08-11 17:29:12.000000000 -0300 +++ mysqlcc-0.9.8-src_patched/src/main.cpp 2010-06-17 20:49:35.000000000 -0300 @@ -90,28 +90,28 @@ {"version", 'V', "Print version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (gptr*) &opt_connect_timeout, - (gptr*) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, - 0, 1}, + {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (uchar**) &opt_connect_timeout, + (uchar**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, + 0, (void*)1}, - {"select_limit", OPT_SELECT_LIMIT, "", (gptr*) &select_limit, - (gptr*) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ~0L, 0, 1, 0}, + {"select_limit", OPT_SELECT_LIMIT, "", (uchar**) &select_limit, + (uchar**) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ~0L, 0, 1, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "", - (gptr*) &my_net_buffer_length, (gptr*) &my_net_buffer_length, 0, GET_ULONG, + (uchar**) &my_net_buffer_length, (uchar**) &my_net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 512*1024*1024L, 0, 1024, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "", - (gptr*) &my_max_allowed_packet, (gptr*) &my_max_allowed_packet, 0, GET_ULONG, + (uchar**) &my_max_allowed_packet, (uchar**) &my_max_allowed_packet, 0, GET_ULONG, REQUIRED_ARG, 16 *1024L*1024L, 4096, 512*1024L*1024L, 0, 1024, 0}, {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE.", - (gptr*) &opt_local_infile, - (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + (uchar**) &opt_local_infile, + (uchar**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"max_join_size", OPT_MAX_JOIN_SIZE, "", (gptr*) &max_join_size, - (gptr*) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ~0L, 0, 1, + {"max_join_size", OPT_MAX_JOIN_SIZE, "", (uchar**) &max_join_size, + (uchar**) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ~0L, 0, 1, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} @@ -155,7 +155,7 @@ break; } if (opt->var_type == GET_NO_ARG && opt->arg_type == NO_ARG) //Boolean options - add_argument(id, ""); + add_argument(id, (char*)""); else add_argument(id, argument); }
The patch can also be downloaded here.