Description:
Hi there,
there is a major bug with UDFs. I developed a simple UDF function in C and when I call it from mysql console I got the parameters. Function takes 2 parameters however I can never get the length of the 2nd parameter (args->lengths[1]) correct eventhough the value is correct. However when I passed 3 parameters the args->lengths[1] gives me the third parameter value. So I can't get the 2nd parameter length.
For example;
my function is demonstrated below
SELECT SIMIL("a", "a", "abc") FROM dual;
and I get the following values in C code
args->args[0] => correct
args->args[1] => correct
args->args[2] => correct
args->lengths[0] => correct
args->lengths[1] => nothing
args->lengths[2] => 2nd parameter length
Here is my code as well
DLL_EXPORT my_bool SIMIL_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
//if (args->arg_count != 2)
//{
//Requires more argument for instance
//x_strlcpy(message, "No arguments allowed (udf: lib_mysqludf_str_info)", MYSQL_ERRMSG_SIZE);
// return 1;
//}
if (args->arg_type[0] != STRING_RESULT)
return 1;
if (args->arg_type[1] != STRING_RESULT)
return 1;
initid->maybe_null = 1;
initid->max_length = 255+1;//20;//(4) - 1;
//initid->const_item = 0;//1 if the result same for each calls
return 0;
}
DLL_EXPORT void SIMIL_deinit(UDF_INIT *initid ATTRIBUTE_UNUSED)
{
}
DLL_EXPORT char* SIMIL( UDF_INIT *initid,
UDF_ARGS *args,
char *result,
unsigned long *res_length,
char *null_value,
char *error)
{
//memcpy(result, args->args[0], args->lengths[0]);
unsigned long iStrLen0 = args->lengths[0];
unsigned long iStrLen1 = args->lengths[1];
unsigned long iStrLen2 = 0;
if (args->arg_count>2)
{
iStrLen2 = args->lengths[2];
}
//char sTest = 0x30 + iStrLen0;
//int len = 6;
int len0 = (int)iStrLen0;
int len1 = (int)iStrLen1;
int len2 = (int)iStrLen2;
if (len0>=255)
len0=255;
//if (len1>=255)
// len1=strlen(args->lengths[1]);
char word0[255]="";
char word1[255]="";
//memcpy(word0, args->args[1], len1);
//memcpy(word1, args->args[1], len1);
int index=0;
result[index++] = 0x30 + args->arg_count;
result[index++] = 0x30 + len0;
result[index++] = 0x30 + len1;
result[index++] = 0x30 + len2;
memcpy(result+index, args->args[1], 4);
//memcpy(result, word1, len1);
*res_length = 6;
return result;
}
How to repeat:
For example;
my function is demonstrated below
SELECT SIMIL("a", "a", "abc") FROM dual;
and I get the following values in C code
args->args[0] => correct
args->args[1] => correct
args->args[2] => correct
args->lengths[0] => correct
args->lengths[1] => nothing
args->lengths[2] => 2nd parameter length
Here is my code as well
DLL_EXPORT my_bool SIMIL_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
//if (args->arg_count != 2)
//{
//Requires more argument for instance
//x_strlcpy(message, "No arguments allowed (udf: lib_mysqludf_str_info)", MYSQL_ERRMSG_SIZE);
// return 1;
//}
if (args->arg_type[0] != STRING_RESULT)
return 1;
if (args->arg_type[1] != STRING_RESULT)
return 1;
initid->maybe_null = 1;
initid->max_length = 255+1;//20;//(4) - 1;
//initid->const_item = 0;//1 if the result same for each calls
return 0;
}
DLL_EXPORT void SIMIL_deinit(UDF_INIT *initid ATTRIBUTE_UNUSED)
{
}
DLL_EXPORT char* SIMIL( UDF_INIT *initid,
UDF_ARGS *args,
char *result,
unsigned long *res_length,
char *null_value,
char *error)
{
//memcpy(result, args->args[0], args->lengths[0]);
unsigned long iStrLen0 = args->lengths[0];
unsigned long iStrLen1 = args->lengths[1];
unsigned long iStrLen2 = 0;
if (args->arg_count>2)
{
iStrLen2 = args->lengths[2];
}
//char sTest = 0x30 + iStrLen0;
//int len = 6;
int len0 = (int)iStrLen0;
int len1 = (int)iStrLen1;
int len2 = (int)iStrLen2;
if (len0>=255)
len0=255;
//if (len1>=255)
// len1=strlen(args->lengths[1]);
char word0[255]="";
char word1[255]="";
//memcpy(word0, args->args[1], len1);
//memcpy(word1, args->args[1], len1);
int index=0;
result[index++] = 0x30 + args->arg_count;
result[index++] = 0x30 + len0;
result[index++] = 0x30 + len1;
result[index++] = 0x30 + len2;
memcpy(result+index, args->args[1], 4);
//memcpy(result, word1, len1);
*res_length = 6;
return result;
}