Adi*_*ngh 5 c mysql user-defined-functions
因此,我创建了一个接受2个字符串并将其合并的UDF。
我的UDF:// concat_kv.c
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned long ulong;
my_bool concat_kv_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if(args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT) {
strcpy(message, "concat_kv(): Requires 2 string parameters: Key - Value.");
return 1;
}
return 0;
}
char *concat_kv(UDF_INIT *initid, UDF_ARGS *args, char *result, ulong *length, char *is_null, char *error) {
char *key = (char*)calloc(strlen(args->args[0]), sizeof(char));
char *value = (char*)calloc(strlen(args->args[1]), sizeof(char));
char *res = (char *)calloc(strlen(args->args[0]) + strlen(args->args[1]) + 2, sizeof(char));
int len = strlen(args->args[0]) + strlen(args->args[1]) + 2;
key = args->args[0];
value = args->args[1];
strcat(res, key);
strcat(res, " ");
strcat(res, value);
res[len-1] = '\0'; // Terminating character...
return res;
}
void concat_kv_deinit(UDF_INIT *initid) {
}
Run Code Online (Sandbox Code Playgroud)
将该文件编译为:
gcc $(mysql_config --cflags) -shared concat_kv.c -o concat_kv.so
Run Code Online (Sandbox Code Playgroud)
将concat_kv.so文件移到/usr/lib/mysql/plugins/。
在mysql中创建的函数为:
CREATE FUNCTION concat_kv RETURNS STRING SONAME 'concat_kv.so';
Run Code Online (Sandbox Code Playgroud)
然后做:
SELECT concat_kv("Aditya", "Singh") as conc;
Run Code Online (Sandbox Code Playgroud)
预期产量:
| conc |
--------
| "Aditya Singh" |
Run Code Online (Sandbox Code Playgroud)
但是获得意外的输出为:
mysql> SELECT concat_kv("Aditya", "Singh") as conc;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| conc
|
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Aditya Singh ?T
|+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
Run Code Online (Sandbox Code Playgroud)
重复的字符串之后,我得到一些无法打印的内容。一些垃圾值附加在字符串之后。
您的concat_kv函数应如下所示:
char *concat_kv(UDF_INIT *initid, UDF_ARGS *args, char *result, ulong *length, char *is_null, char *error) {
char *key = args->args[0];
char *value = args->args[1];
strcpy(result, key);
strcat(result, " ");
strcat(result, value);
*length = strlen(result);
return result;
}
Run Code Online (Sandbox Code Playgroud)
一些说明:
结果参数应用于结果
长度应返回
长度应不以空字符结尾,请参见此处:https : //dev.mysql.com/doc/refman/8.0/en/udf-return-values.html
键和值仅从args中使用,并通过strcpy / strcat复制到结果中
演示版
动态内存分配
如注释中已经指出的,如果超出了预分配缓冲区的大小,则存在缓冲区溢出的危险。
内存泄漏
如果要在concat_kv()中动态分配内存,则会导致内存泄漏,因为每次调用用户定义的函数时都会请求内存,并且不会再释放它。
解决方案是使用concat_kv_init()和concat_kv_deinit()函数,这些函数由MySQL在concat_kv()调用之前和之后直接调用。
这是MySQL文档的引文:
MySQL使用result参数将缓冲区传递给xxx()函数。该缓冲区足够长,可以容纳255个字符,可以是多字节字符。如果适合,xxx()函数可以将结果存储在此缓冲区中,在这种情况下,返回值应该是指向缓冲区的指针。如果函数将结果存储在另一个缓冲区中,则应返回一个指向该缓冲区的指针。
如果您的字符串函数不使用提供的缓冲区(例如,如果它需要返回长度超过255个字符的字符串),则必须在xxx_init()函数或xxx( )函数并在xxx_deinit()函数中将其释放。
参见https://dev.mysql.com/doc/refman/8.0/en/udf-return-values.html
动态内存分配示例
因此,如果我们不能保证结果的大小那么大,那么就需要预先分配缓冲区,我们需要在concat_kv_init()中分配内存,并在concat_kv_deinit()中释放它。
my_bool concat_kv_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if(args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT) {
strcpy(message, "concat_kv(): Requires 2 string parameters: Key - Value.");
return 1;
}
ulong length = strlen(args->args[0]) + strlen(args->args[1]) + 2;
initid->ptr = (char *)malloc(length);
return 0;
}
char *concat_kv(UDF_INIT *initid, UDF_ARGS *args, char *result, ulong *length, char *is_null, char *error) {
char *key = args->args[0];
char *value = args->args[1];
strcpy(initid->ptr, key);
strcat(initid->ptr, " ");
strcat(initid->ptr, value);
*length = strlen(initid->ptr);
return initid->ptr;
}
void concat_kv_deinit(UDF_INIT *initid) {
free(initid->ptr);
initid->ptr = NULL;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
147 次 |
| 最近记录: |