我在MySQL中有以下查询:
SELECT FUNCTIONTEST(Column1, 27, 'SOMETHING', Column2) AS RANK1 FROM table1
字符串
- Column1* 为varchar(100),Column2 为unsigned tinyint(3),默认值为0。不使用NULL。
- FUNCTIONTEST* 是一个UDF函数,它以前工作得很好,但我想通过第四个参数来扩展它。
自定义项初始化函数清单:
bool FUNCTIONTEST_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if ((args->arg_count != 4) ||
(args->arg_type[0] != STRING_RESULT || args->arg_type[1] != INT_RESULT || args->arg_type[2] != STRING_RESULT || args->arg_type[3] != INT_RESULT)) {
strcpy(message, "Function requires 4 arguments, (string, int, string, int)");
return 1;
}
const longlong abc = *((longlong*) args->args[1]);
const long long def = *((long long*) args->args[3]);
型
当使用Column2时,最后一行会导致问题。它会生成错误:
- 错误代码:2013。查询过程中与MySQL服务器失去连接 *
但是,如果我直接用一个数字调用query,而不是使用column,它就可以工作。
SELECT FUNCTIONTEST(Column1, 27, 'SOMETHING', 0) AS RANK1 FROM table1
型
有谁知道,可能是什么问题?
Column1是一个字符串,可以正常工作(不是代码片段的一部分)。我尝试将Column2改为varchar,但在UDF中将字符串转换为整数时遇到了麻烦。我还尝试在查询中使用 CAST。
要复制,请在MySQL中创建以下表格:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
CREATE TABLE `stack` (
`ID` int(11) NOT NULL,
`Name` varchar(100) NOT NULL DEFAULT '',
`Subtract` tinyint(3) UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
INSERT INTO `stack` (`ID`, `Name`, `Subtract`) VALUES
(1, 'Test1 Test2 Test3', 0),
(2, 'Test4 Test5 Test6', 6);
ALTER TABLE `stack`
ADD PRIMARY KEY (`ID`);
ALTER TABLE `stack`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
型
名为levenshtein.c的UDF文件:
#ifdef STANDARD
/* STANDARD is defined, don't use any mysql functions */
#include <string.h>
#ifdef __WIN__
typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */
typedef __int64 longlong;
#else
#endif /*__WIN__*/
#else
//#include <my_global.h>
//#include <my_sys.h>
#if defined(MYSQL_SERVER)
#include <m_string.h>
#else
/* when compiled as standalone */
#include <string.h>
#endif
#endif
#include <mysql.h>
#include <ctype.h>
typedef unsigned long long ulonglong;
typedef long long longlong;
//#ifdef HAVE_DLOPEN
/* (Expected) maximum number of digits to return */
#define LEVENSHTEIN_MAX 3
#define INSERT_MULTIPLIER 5000
#define DELETE_MULTIPLIER 0
#define TRANSPOSITION_MULTIPLIER 2000
static inline int minimum(int a, int b, int c) {
int min = a;
if (b < min)
min = b;
if (c < min)
min = c;
return min;
}
#define min4(a,b,c,d) ((a)< (b) ? minimum((a),(c),(d)) : minimum((b),(c),(d)))
static inline int maximum(int a, int b) {
if (a > b) return a;
else return b;
}
#define min(x,y) ((x) < (y) ? (x) : (y))
bool levenshtein2_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
void levenshtein2_deinit(UDF_INIT *initid);
longlong levenshtein2(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
bool levenshtein2_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if ((args->arg_count != 4) ||
(args->arg_type[0] != STRING_RESULT || args->arg_type[1] != INT_RESULT || args->arg_type[2] != STRING_RESULT || args->arg_type[3] != INT_RESULT)) {
strcpy(message, "Function requires 4 arguments, (string, int, string, int)");
return 1;
}
const longlong sl = *((longlong*) args->args[1]);
const long long subtract = *((long long*) args->args[3]);
//const long long subtract = 3;
if (sl <= 0) {
strcpy(message, "Argument 1 must be greater than 0");
return 1;
}
if (subtract < 0) {
strcpy(message, "Argument 3 must be greater or equal to 0");
return 1;
}
if (subtract > sl) {
strcpy(message, "Argument 3 must be lower or greater to argument 1");
return 1;
}
//matrix for levenshtein calculations of size 6 x n+2 x m+2 (+1 for base values and +1 for \0)
int *d = (int *) malloc(sizeof(int) * 6 * (args->lengths[0] + 2) * (args->lengths[2] - subtract + 2));
if (d == NULL) {
strcpy(message, "Failed to allocate memory");
return 1;
}
initid->ptr = (char*) d;
initid->max_length = LEVENSHTEIN_MAX;
initid->maybe_null = 0; //doesn't return null
return 0;
}
void levenshtein2_deinit(UDF_INIT *initid) {
if (initid->ptr != NULL)
free(initid->ptr);
}
longlong levenshtein2(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) {
// Logic removed from example
longlong bestDistance = 5;
return (longlong) bestDistance;
}
型
编译为:
gcc -fPIC -o levenshtein.so -shared levenshtein.c `mysql_config --include`
型
创建函数:
CREATE FUNCTION levenshtein2 RETURNS INT SONAME 'levenshtein.so';
型
测试查询:
SELECT LEVENSHTEIN2(Name, 17, 'TEST1', Subtract) AS RANK1, stack.* FROM stack
型
当在levenshtein. c中注解第63行并取消注解第64行时,它可以工作。它也可以与第63行一起工作,它的查询是这样执行的:
SELECT LEVENSHTEIN2(Name, 17, 'TEST1', 3) AS RANK1, stack.* FROM stack
型
1条答案
按热度按时间mi7gmzs61#
我目前的解决方法是不验证和使用init函数中第四个参数的值,这意味着我分配了比我需要的更多的内存,但我可以接受,因为它与我以前使用这个函数没有什么不同。
字符串
我仍然不明白,为什么
longlong subtract = *((longlong*) args->args[3]);
在init函数中不起作用。显然,来自DB的结果是整数,并且根据文档进行了转换。它在main函数中起作用。如果提供了错误的参数值,我将 subtract 变量更改为0,而不是使函数失败。