0

Information about the system in which the problem occurs:

OS: Debian 8.1 64 bits - MySQL Version: 5.5.44 - GCC: 4.9.2

I'm creating a simple UDF function that will return the string Hello World. The problem is that it will return Hello World, concat to it, there is a long random binary string with random data of variable size, that will change from execution to execution.

hello_world.c

#ifdef STANDARD
/* STANDARD is defined, 
don't use any mysql functions */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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 <my_global.h>
#include <my_sys.h>
#if defined(MYSQL_SERVER)
#include <m_string.h>      /* To get strmov() */
#else
/* when compiled as standalone */
#include <string.h>
#define strmov(a,b) stpcpy(a,b)
#define bzero(a,b) memset(a,0,b)
#endif
#endif
#include <mysql.h>
#include <ctype.h>

#ifdef _WIN32
/* inet_aton needs winsock library */
#pragma comment(lib, "ws2_32")
#endif

#ifdef HAVE_DLOPEN

#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST)
static pthread_mutex_t LOCK_hostname;
#endif

my_bool hello_world_init(UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)),
                     char* is_null __attribute__((unused)), char* message __attribute__((unused)))
{
   return 0;
}

void hello_world_deinit(UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)),
                     char* is_null __attribute__((unused)), char* message __attribute__((unused)))
{}

char* hello_world(UDF_INIT *initid __attribute__((unused)),
               UDF_ARGS *args, char *result, unsigned long *length,
               char *is_null, char *message __attribute__((unused)))
{
    char* hello = "Hello World";

    return hello;
}

#endif /* HAVE_DLOPEN */

I have tried to compile the source in 2 different ways with the same output:

gcc $(mysql_config --cflags) -shared -fPIC -o hello_world.so hello_world.c

gcc -shared -fPIC -o hello_world.so helloworld.c -I/usr/include/mysql

I included the UDF shared library to /usr/lib/mysql/plugin and I created the function in MySQL: CREATE FUNCTION hello_world RETURNS STRING SONAME "hello_world.so";

Everything is very smooth, problem comes when the function is executed:

Example output:

| Hello World    ;,      ��   �����              x
 �  $     ���0    FJ
V                      � ?;      D   ���    A�C
       d   
Q          ��            �       
                               ���o                                                                                                                                                                                                                |

What may be the problem?

Thank you.

Jesus Gonzalez
  • 411
  • 6
  • 17

2 Answers2

2

You're not properly calling making the UDF calls. Per the documentation:

The return value of the main function xxx() is the function value, for long long and double functions. A string function should return a pointer to the result and set *length to the length (in bytes) of the return value. For example:

memcpy(result, "result string", 13);
*length = 13;

There's a lot more to that documentation, too.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
0

MySQL doesn't use the null terminator in the C string. The UDF receives a parameter unsigned long *length and you have to set this.

*length = strlen(hello);
return hello;
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I have tried your solution as well. It doesn't return the expected value. It needs to memcpy the string into result pointer. Thank you. – Jesus Gonzalez Sep 04 '15 at 14:09
  • 1
    That shouldn't be necessary. The documentation says _If the function stores the result in a different buffer, it should return a pointer to that buffer._ – Barmar Sep 04 '15 at 14:22
  • You would only need to use `memcpy` if you were trying to return a local string, because it's destroyed when the function returns. But your example returns a pointer to a string literal, which isn't destroyed. – Barmar Sep 04 '15 at 14:24