How I built the NOW_USEC() UDF for MySQL

Last week I wrote about my efforts to measure MySQL’s replication speed precisely. The most important ingredient in that recipe was the user-defined function to get the system time with microsecond precision. This post is about that function, which turned out to be surprisingly easy to write.

The manual section on user-defined functions provides very good instructions on how they work and how to build them. But just for the record, on Ubuntu 7.04 on an AMD64 machine, all I had to do was install the libmysqlclient15-dev package, and I was then able to compile the UDF with no further ado. Also for the record, MySQL header files have some dependencies they shouldn’t that break building against a downloaded tarball. So don’t be surprised if you have troubles building against anything but Ubuntu’s provided header files.

Here’s the source, which I basically cribbed from a NOW_MSEC() function I saw in a bug report somewhere. Really, there’s not much to it besides the basic skeleton of a UDF, with a few lines to actually get the system time. And I actually believe if I took another ten minutes to learn about strftime(), there’s probably no need to do it in two steps; I could probably do the whole thing with one strftime() call and save a little memory and time. But that’s what I get for copying and pasting code of unknown quality:

#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

extern "C" {
   my_bool now_usec_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
   char *now_usec(
               UDF_INIT *initid,
               UDF_ARGS *args,
               char *result,
               unsigned long *length, char *is_null, char *error);
}

my_bool now_usec_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
   return 0;
}

char *now_usec(UDF_INIT *initid, UDF_ARGS *args, char *result,
               unsigned long *length, char *is_null, char *error) {

  struct timeval tv;
  struct tm* ptm;
  char time_string[20]; /* e.g. "2006-04-27 17:10:52" */
  char *usec_time_string = result;
  time_t t;

  /* Obtain the time of day, and convert it to a tm struct. */
  gettimeofday (&tv, NULL);
  t = (time_t)tv.tv_sec;
  ptm = localtime (&t);   

  /* Format the date and time, down to a single second.  */
  strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm);

  /* Print the formatted time, in seconds, followed by a decimal point
 *      and the microseconds.  */
  sprintf(usec_time_string, "%s.%06ld\n", time_string, tv.tv_usec);

  *length = 26;

  return(usec_time_string);
}

The installation looks like this:

baron@tigger now_usec $ make
gcc -fPIC -Wall -I/usr/include/mysql -shared -o now_usec.so now_usec.cc
baron@tigger now_usec $ sudo cp now_usec.so /lib
baron@tigger now_usec $ mysql test
mysql> create function now_usec returns string soname 'now_usec.so';
Query OK, 0 rows affected (0.00 sec)

mysql> select now_usec();
+----------------------------+
| now_usec()                 |
+----------------------------+
| 2007-10-23 10:28:13.862116 | 
+----------------------------+

For those who have reached this page via Google searches and are looking for more information, you should check out the MySQL User Defined Function Library project. Lots of good UDFs there.

Technorati Tags:, , , , , ,

You might also like:

  1. How fast is MySQL replication?
  2. More alternatives to openxml
  3. A bug in Microsoft SQL Server’s replace() function

10 Responses to “How I built the NOW_USEC() UDF for MySQL”


  1. 1 Roland Bouman

    Hi Baron,

    thanks for sharing this code! And, thanks for the link to the UDF repository page ;-)

    I just wanted to let you know that the code sample does not render the #include lines properly - you probably should escape the angle brackets

    #include &lt;stdio.h&gt;

  2. 2 Xaprb

    Ooh, good catch. Weird, I thought it usually handled that inside ‘pre’ tags. Thanks.

  3. 3 Roland Bouman

    Hi Baron,

    “I thought it usually handled that inside ‘pre’ tags”

    The best thing of pre is that it treats all white space as significant white space:

    http://www.w3.org/TR/REC-html40/struct/text.html#h-9.3.4

    However, the contents are still parsed as HTML. The greater than sign is usually printed literally but most parsers assume that the less than sign is the start of a new tag.

    A trick that sometimes work is to put everything inside pre inside a CDATA section:

    <pre>&lt![CDATA[

    #include <stdio.h>

    ]]></pre>

  4. 4 Xaprb

    Right, what I meant was I thought I had Wordpress configured to automatically entity-ify inside pre.

  5. 5 Justin Swanhart

    Thanks for this great UDF. I need to profile some stored procedures, and this will do just the trick.

  6. 6 Xaprb

    For readers’ edification: Justin wrote about how to compile this UDF on Mac OS 10.4 here: http://swanhart.livejournal.com/116981.html

  7. 7 Marian Neubert

    Note: Since this is C++ i had to compile this with g++ . gcc also builds the library successful but when creating the function mysql returns an error like “undefined symbol: __gxx_personality_v0″

  8. 8 Xaprb

    Yeah, sorry about that — WP has a bug with plus signs. I think it urldecodes them into spaces or something. No time to upgrade….

  9. 9 Nyna

    Handy function, however I’m curious as to the decision to make NOW_USEC() return a dynamic value (i.e. recomputed on every call) rather than a constant value like NOW().

    And, how complex would it be to modify the udf sources to enable functionality like NOW() 0, i.e. returning a decimal (or double) when used in a numeric context?

  10. 10 Xaprb

    Those weren’t needed for my testing, so I never thought about it.

Leave a Reply

Please do not use this blog to get help with problems or bugs in Maatkit or innotop: use the Sourceforge forums, mailing list, or bug trackers. If you're asking for help with MySQL, please use the MySQL mailing list instead.