I played a bit with various interaction with outer world ideas in MySQL UDFs and ended up with something what was really really simple – a single libc call. I did shamelessly steal bare bones and simply added a single line of code in it:
#include <mysql.h> #include <string.h> #include <syslog.h> my_bool logger_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { initid->maybe_null=0; return 0; } long long logger(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { if (args->arg_count != 1) { strcpy(error, "LOGGER(): needs message"); return 1; } if (args->arg_type[0] != STRING_RESULT) { strcpy(error, "LOGGER() message should be string"); return 1; } syslog(LOG_INFO,"%s",args->args[0]); *is_null = 0; *error = 0; return 0; }
Of course, I had to compile it:
gcc -I /usr/include/mysql/ -shared -o syslogudf.so syslogudf.c
And later load it:
mysql> create function logger returns integer soname 'syslogudf.so'; Query OK, 0 rows affected (0.00 sec)
One more thing… testing:
mysql> select logger(concat(user()," wishes you ", -> if(rand()>0.3,"good","bad")," luck")); +---------------------------------------------------------------------------+ | logger(concat(user()," wishes you ",if(rand()>0.3,"good","bad")," luck")) | +---------------------------------------------------------------------------+ | 0 | +---------------------------------------------------------------------------+ 1 row in set (0.00 sec)
So now our systems administrator will see:
$ tail -1 /var/log/messages Dec 12 01:09:22 flake mysqld-max: root@localhost wishes you bad luck
Oops!
Hello!
Pretty nice syslog plugin you got there, used it before on 32 bit Linux, unfortunately it won’t compule on a 64 bit system (CentOS 6):
# gcc -I /usr/include/mysql/ -shared -o syslogudf.so syslogudf.c
/usr/bin/ld: /tmp/ccb270xG.o: relocation R_X86_64_32 against `.rodata’ can not be used when making a shared object; recompile with -fPIC
/tmp/ccb270xG.o: could not read symbols: Bad value
collect2: ld returned exit code 1
If I try using the “-fPIC” param, it’s even worse.
Any suggestions? Thx in advance!
SUCCESS! :)
After lots of googling and man page reading I finally found the solution. I simply copied the 64 bit “udfexample.c” file (from mysql-devel) file and modified it for my needs.
The following code needs to be compiled using
# gcc -I /usr/include/mysql/ -shared -o syslogudf.so syslogudf.c -fPIC
CODE:
#ifdef STANDARD
/* STANDARD is defined, don’t use any mysql functions */
#include
#include
#include
#ifdef __WIN__
typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif /*__WIN__*/
#else
#include
#include
#if defined(MYSQL_SERVER)
#include /* To get strmov() */
#else
/* when compiled as standalone */
#include
#define strmov(a,b) stpcpy(a,b)
#define bzero(a,b) memset(a,0,b)
#define memcpy_fixed(a,b,c) memcpy(a,b,c)
#endif
#endif
#include
#include
#include
#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST)
static pthread_mutex_t LOCK_hostname;
#endif
/* Logger */
my_bool logger_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
initid->maybe_null=0;
return 0;
}
long long logger(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) {
if (args->arg_count != 1) {
strcpy(error, “LOGGER(): needs message”);
return 1;
}
if (args->arg_type[0] != STRING_RESULT) {
strcpy(error, “LOGGER() message should be string”);
return 1;
}
syslog(LOG_INFO,”%s”,args->args[0]);
*is_null = 0;
*error = 0;
return 0;
}