0

As it's my first time to write UDF so I tried to write simple UDF to return the same argument which is passed to UDF.

code as below:

#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <cstring>
#include <mysql.h>
#include <ctype.h>
#include <my_global.h>
#include <my_sys.h>
using namespace std;


extern "C" my_bool get_arg_init(UDF_INIT *initid, UDF_ARGS *args,
                               char *message)
{
    if ( ( args->arg_count != 1 ) || ( args->arg_type[0] != STRING_RESULT ) )
     {
      strcpy( message, "Wrong argument type." );
      return 1;
     }

    return 0;
}

extern "C" void get_arg_deinit(UDF_INIT *initid)
{
    //nothing to free here
}

extern "C" char *get_arg(UDF_INIT *initid, UDF_ARGS *args,
          char *result, unsigned long *length,
          char *is_null, char *error)
{
    std::string str = args->args[0]; // get the first argument passed
    memcpy(result, str.c_str(), str.size()); // copy argument value into result buffer
    *length = str.size(); // set length

    return result;//return the same argument
}

My table having data as;

SELECT c_name FROM tbl;

This will return data as:

# c_name
amogh bharat shah
viraj

If I execute query using UDF :

SELECT get_arg(c_name) FROM tbl;

This returns:

# get_arg(c_name)
amogh bharat shah
viraj bharat shah

It looks like while second row first 5 characters are replaced with actual row data other part of string is garbage from first row.

Why this happens? and what should I change in function to avoid overlapping of string?

1
  • i added the C++ tag to the question it might help to get answers. Commented Dec 19, 2018 at 14:55

1 Answer 1

1

The strings passed to your function are not necessarily null terminated, from https://dev.mysql.com/doc/refman/8.0/en/udf-arguments.html:

Do not assume that the string is null-terminated.

Constructing a std::string from a non-null terminated character string is undefined behaviour, in this case I guess the buffer was initially 0 filled so the string ends at the end of the longest string which has ever been put into the buffer.

The correct code is:

std::string str( args->args[0], args->lengths[0] );

Or skip creating the unnecessary copy in the std::string:

memcpy(result, args->args[0], args->lengths[0]);
*length = args->lengths[0];
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.