为啥 MySQL UDF 返回随机数据?

Posted

技术标签:

【中文标题】为啥 MySQL UDF 返回随机数据?【英文标题】:Why MySQL UDF Returns Random Data?为什么 MySQL UDF 返回随机数据? 【发布时间】:2015-09-04 13:08:51 【问题描述】:

出现问题的系统信息:

操作系统:Debian 8.1 64 位 - mysql 版本:5.5.44 - GCC:4.9.2

我正在创建一个简单的 UDF 函数,它将返回字符串 Hello World。问题是它会返回 Hello World,concat 给它,有一个很长的随机二进制字符串,带有可变大小的随机数据,会随着执行而变化。

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 */

我尝试以 2 种不同的方式编译源代码,输出相同:

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

我将 UDF 共享库包含到 /usr/lib/mysql/plugin 并在 MySQL 中创建了函数:CREATE FUNCTION hello_world RETURNS STRING SONAME "hello_world.so";

一切都很顺利,函数执行时出现问题:

示例输出:

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

可能是什么问题?

谢谢。

【问题讨论】:

检查这个:***.com/questions/2911089/null-terminating-a-string @VincentRamdhanie 他使用的是字符串文字,它会自动以空值结尾。 您似乎没有设置长度,dev.mysql.com/doc/refman/5.1/en/udf-return-values.html 【参考方案1】:

您没有正确调用 UDF 调用。每the documentation:

主函数xxx()的返回值为函数值,对于 long long 和 double 函数。字符串函数应该返回一个 指向结果的指针并将 *length 设置为 返回值。例如:

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

该文档还有很多内容。

【讨论】:

太棒了!它现在正在返回预期值。非常感谢。【参考方案2】:

MySQL 不在 C 字符串中使用空终止符。 UDF 接收到一个参数unsigned long *length,你必须设置它。

*length = strlen(hello);
return hello;

【讨论】:

我也试过你的解决方案。它不会返回预期值。它需要将字符串 memcpy 到结果指针中。谢谢。 这应该没有必要。文档说 如果函数将结果存储在不同的缓冲区中,它应该返回指向该缓冲区的指针。 如果你试图返回一个本地字符串,你只需要使用memcpy,因为当函数返回时它被破坏了。但是您的示例返回一个指向字符串文字的指针,该指针没有被破坏。

以上是关于为啥 MySQL UDF 返回随机数据?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 随机查询若干条数据

UDF 随机数生成器类型不匹配

为啥我的 TSQL SELECT 命令会吐出随机数据?

MySQL:为啥将主键与不​​使用索引的随机生成的数字进行比较?

为啥来自 /dev/null 的 ioctl FIONREAD 在 Mac OS X 上返回 0 而在 Linux 上返回随机数?

Hive自定义UDF,生成32位随机数