Ваша функция 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;
}
Некоторые замечания:
Демо
![concat_kv in MySQL on Ubuntu](https://i.stack.imgur.com/hPf96.png)
Динамическое выделение памяти
Как уже указывалось в комментариях, существует опасность переполнения буфера, если размер предварительно выделенного буфера превышен.
Утечка памяти
Если бы мы динамически распределяли память в concat_kv (), мы бы привели к утечке памяти, поскольку память запрашивается каждый раз, когда вызывается пользовательская функция, и больше никогда не освобождается.
Решением является использование функций concat_kv_init () и concat_kv_deinit (), которые вызываются MySQL непосредственно до и после вызова concat_kv ().
Вот цитата из документации MySQL:
MySQL передает буфер в функцию xxx (), используя параметр результата. Этот буфер достаточно длинный, чтобы вместить 255 символов, которые могут быть многобайтовыми символами. Функция xxx () может сохранить результат в этом буфере, если он подходит, и в этом случае возвращаемое значение должно быть указателем на буфер. Если функция сохраняет результат в другом буфере, она должна вернуть указатель на этот буфер.
Если ваша строковая функция не использует предоставленный буфер (например, если ей нужно вернуть строку длиной более 255 символов), вы должны выделить место для вашего собственного буфера с помощью malloc () в вашей функции 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;
}