尝试在 mysql 中添加 udf 会出现错误 ERROR 1127 (HY000): Can't find symbol in library

Posted

技术标签:

【中文标题】尝试在 mysql 中添加 udf 会出现错误 ERROR 1127 (HY000): Can\'t find symbol in library【英文标题】:trying to add udf in mysql gives error ERROR 1127 (HY000): Can't find symbol in library尝试在 mysql 中添加 udf 会出现错误 ERROR 1127 (HY000): Can't find symbol in library 【发布时间】:2016-11-11 16:15:19 【问题描述】:

我一直在尝试在 mysql 5.6 中添加用户定义的函数,它执行一个简单的任务 - 即找到 column1 的最大值并返回另一列的值,即 column2 对应于 column1 的最大值。

我知道在这个概念中很少有注意事项,比如如果 column1 有 2 个最大值,那么应该返回 column2 的哪个对应值。但这些事情并不是我现在主要关注的领域。

我已经编写了函数的程序,其中 column1 和 column2 都是双精度数。它正在运行。但是当我尝试 column1 是 double 并且 column2 是 string 类型的情况时。我面临的问题是它给出了错误 ERROR 1127 (HY000): Can't find symbol 'strvalformax' in library 。这是我的complete code

#ifdef STANDARD
#include <stdio.h>
#include <string.h>
#ifdef __WIN__
typedef unsigned __int64 ulonglong; 
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif /*__WIN__*/
#else
#include <my_global.h>
#include <my_sys.h>
#endif
#include <mysql.h>
#include <m_ctype.h>
#include <m_string.h>       

#ifdef HAVE_DLOPEN


extern "C" 

  my_bool strvalformax_init( UDF_INIT* initid, UDF_ARGS* args, char* message );
  void strvalformax_deinit( UDF_INIT* initid );
  void strvalformax_clear(UDF_INIT *initid, char *is_null, char *is_error);
  void strvalformax_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
  void strvalformax_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
  char* strvalformax( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );




struct max_data

  double max;
  char* colval;
;


my_bool strvalformax_init( UDF_INIT* initid, UDF_ARGS* args, char* message )

  if (args->arg_count != 2)
  
    strcpy(message,"wrong number of arguments: strvalformax() requires two arguments");
    return 1;
  
  if (args->arg_type[1]!=STRING_RESULT)
  
    strcpy(message,"correlation() requires a string as parameter 2");
    return 1;
  

  max_data   *buffer = new max_data;
  buffer->max = NULL;
  buffer->colval= NULL;
  initid->ptr = (char*)buffer;
  return 0;



void strvalformax_deinit( UDF_INIT* initid )

  max_data *buffer = (max_data*)initid->ptr;
  if(buffer->colval!=NULL)
    free(buffer->colval);
    buffer->colval=NULL;
  
  delete initid->ptr;


void strvalformax_clear(UDF_INIT *initid, char *is_null, char *is_error)
  
  max_data *buffer = (max_data*)initid->ptr;
  *is_null = 0;
  *is_error = 0;
  buffer->max=NULL;
  buffer->colval=NULL;


void strvalformax_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )

  strvalformax_clear(initid, is_null, is_error);
  strvalformax_add( initid, args, is_null, is_error );



void strvalformax_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* is_error )

  max_data *buffer = (max_data*)initid->ptr;
  if (args->args[0]!=NULL && args->args[1]!=NULL)
  
    if(buffer->max==NULL)
      buffer->max = *(double*)args->args[0];
      if(buffer->colval!=NULL)
    free(buffer->colval);
    buffer->colval=NULL;
      
      buffer->colval = (char *)malloc(args->attribute_lengths[1]+1);
      strcpy(buffer->colval,args->args[1],attribute_lengths[1]);
    else
      if((*(double*)args->args[0])>(buffer->max))
    buffer->max = *(double *)args->args[0];
    if(buffer->colval!=NULL)
      free(buffer->colval);
      buffer->colval=NULL;
    
    buffer->colval = (char *)malloc(args->attribute_lengths[1]+1);
    strcpy(buffer->colval,args->args[1]);
      
    
  



char *strvalformax ( UDF_INIT* initid, UDF_ARGS* args,char* result,unsigned long* res_length, char* is_null, char* is_error )

  max_data* buffer = (max_data*)initid->ptr;
  result = buffer->colval;
  *res_length = strlen(buffer->colval);
  return result;




#endif

用于编译和链接的命令 g++ -o udf_strvalformax.o -O2 -fPIC -I/usr/src/mariadb-5.5.30/include/ -I/usr/include/mysql -DHAVE_DLOPEN=1 -DMYSQL_DYNAMIC_PLUGIN -c udf_strvalformax.cc

用于链接到共享库的命令 ld -shared -o udf_strvalformax.so udf_strvalformax.o

将共享对象文件复制到 mysql 插件库 cp udf_strvalformax.so /usr/lib/mysql/plugin/

终于调用了create函数 CREATE AGGREGATE FUNCTION strvalformax RETURNS STRING SONAME 'udf_strvalformax.so';

它给出了错误 ERROR 1127 (HY000): Can't find symbol 'strvalformax' in library 我还签入了共享对象文件以查看符号是否可用以及它是否可用。这是nm -gC --demangle udf_strvalformax.so的结果

0000000000200a50 D __bss_start 0000000000200a50 D _edata 0000000000200a50 D _end U free U malloc U strcpy U strlen 00000000000006c0 T strvalformax_add 00000000000006a0 T strvalformax_clear 0000000000000660 T strvalformax_deinit 0000000000000540 T strvalformax_init 0000000000000760 T strvalformax_reset 00000000000007a0 T strvalformax(st_udf_init*, st_udf_args*, char*, unsigned long*, char*, char*) U operator delete(void*) U operator new(unsigned long)

我已经尝试找出问题 1.5 天,但没有任何进展。可能是我在这里遗漏了一些东西。提前致谢。

【问题讨论】:

【参考方案1】:

我还检查了共享对象文件以查看符号是否可用 与否,它是可用的。

不,它不存在。 .so 包含一个损坏的符号

00000000000007a0 T strvalformax(st_udf_init*, st_udf_args*, char*, unsigned long*, char*, char*)

服务器只查找strvalformax

使用普通的

nm udf_strvalformax.so

看看有什么不同。

问题在于声明使用extern "C"

  char* strvalformax( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );

以及函数的实现

char *strvalformax ( UDF_INIT* initid, UDF_ARGS* args,char* result,unsigned long* res_length, char* is_null, char* is_error )

使用不同的原型,所以它们的功能不同。

尝试使用确切的函数原型声明extern C(缺少参数resultres_length)。

【讨论】:

感谢马克我犯了这样一个菜鸟错误。我对 nm 的理解还不够。

以上是关于尝试在 mysql 中添加 udf 会出现错误 ERROR 1127 (HY000): Can't find symbol in library的主要内容,如果未能解决你的问题,请参考以下文章

在 VBA UDF 中添加超链接

[Q]:mysql创建UDF语法错误

UDF 并在 MySql 中运行它

无法创建此 MySQL UDF

执行 UDF 失败

无法序列化 PySpark UDF