Niels Horn's Blog

Random thoughts, tips & tricks about Slackware-Linux, Lego and Star Wars

Getting mysqlcc to build with newer gcc compilers and mysql headers

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 by uchar**

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 as int and is now defined as void*

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:
mysqlcc

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.

Bookmark and Share

This entry was posted on Thursday, June 17th, 2010 at 22:42 and is filed under Patches, gcc, mysqlcc. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

11 Responses to “Getting mysqlcc to build with newer gcc compilers and mysql headers”

  1. Jeff Says:

    Awesome! Your patch worked like a champ on Fedora Core 11 (x86_64).
    Thanks!

  2. Niels Horn Says:

    Good to know it helped you.
    Thanks for your feedback!

  3. Iain Kay Says:

    Hey thanks for this.
    I was just researching MySQL with C client library for the first time and when the example code I had found through up an error about gptr I was at a loss.

    This post cracked it and it taught me an important lesson about how to investigate errors in C and where to find fixes.

    Thanks so much for this. =)

  4. Niels Horn Says:

    Glad I could be of help!

  5. Trevor Cordes Says:

    Care to take a stab at getting mysqlcc to work with Mysql 5.5, 1 year later? :-)

    Missing symbol errors for functions defined in /usr/include/mysql/my_getopt.h that don’t seem to be in the .so. I commented out all these functions in main.cpp (they just check cmd line args, which I don’t use) but the resulting binary immediately segfaults in /usr/lib/mysql/libmysqlclient.so.18. Perhaps too much changed in the API? Or maybe there is a quick fix?

    Cheers, and thanks for the great tips: saved my bacon 1 year ago.

  6. Niels Horn Says:

    Hi,

    I’m extremely busy with job-related things at the moment, but I’ll take a look at this as soon as I can find some spare time!

  7. Niels Horn Says:

    Hi Trevor,

    I did some investigation and indeed some functions were not exported any longer by libmysqlclient.so.18. This mysql 5.5 bug report explains that these functions were actually not official in the first place.
    Anyway, I managed to get them back by editing the libmysql/CMakeLists.txt and rebuilding mysql 5.5.
    After that, mysqlcc built without problems, but – as you already experienced as well – immediately segfaults.

    If there is a “quick fix”, I could not find it. I guess that too much has changed…
    I even tried version 1.0.1 of mysqlcc, but it had the same effect – it just did not need my patch any longer.

    Maybe the mysqlcc author will eventually fix this, when mysql 5.5 becomes more popular, but I wouldn’t hold my breath :)

  8. Niels Horn Says:

    OK, did some more checking and managed to get mysqlcc to work with mysql 5.5.
    I need to clean up some things to write a decent patch, so check back here for more news :)

  9. Niels Horn Says:

    And the patch can be found in this post: http://blog.nielshorn.net/2011/12/mysqlcc-revisited-making-it-work-with-mysql-5-5/

  10. Trevor Cordes Says:

    Hi! Had a chance to check back and continue. Your new patch works great! Not sure why my attempt at the same thing failed, probably cut out too much (like the argv[0] bit). This is awesome, I can use mysqlcc again! Thanks!

  11. Niels Horn Says:

    Hi,
    Sorry for the late reply (vacation…). But I’m glad it worked for you!

Leave a Reply



XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

It may take some time for your comment to appear, it is not necessary to submit it again.