1

I am trying to use my own UDF (written in c++) as a mysql extension. I was able to install the function via

CREATE FUNCTION  decrypt RETURNS STRING SONAME "libudf_func.so";

and use it. I could also drop the function via

DROP FUNCTION decrypt;

After that it would not be listed in the mysql.func table, so Im pretty sure it was successfully deleted.

Now I want to use an updated version of my function, and therefore reload it in mysql. However, mysql only reloads the old version of my file (which I completely removed from the computer). Even if I remove ALL files named "libudf_func.so" it will be reloaded.

I'm using mysql version 8.0.28 for macos12.0 on localhost.

How can I remove this cached version or force mysql to reload?

EDIT

  • All my steps, from loading the first version to my attempt to load the updated version:
  1. I used: CREATE FUNCTION decrypt RETURNS STRING SONAME "libudf.so"; to initially create the function decrypt
  2. I changed something in my udf.cpp file.
  3. I used: DROP FUNCTION decrypt; to remove the function decrypt
  4. I used CREATE FUNCTION decrypt RETURNS STRING SONAME "libudf.so"; as an attempt to reload/refresh the function decrypt (NO ERRORS)
  5. the behaviors did not change (among other things I wanted to output a different error message, so that was pretty obviously the old behavior)
  6. I renamed libudf.so to lubudf_func.so
  7. I replicated this with the new name.
  8. I deleted ALL files with the names libudf.so or lubudf_func.so from my machine
  9. I could still execute CREATE FUNCTION decrypt RETURNS STRING SONAME "libudf.so"; without any errors
  10. I tried to call CREATE FUNCTION decrypt RETURNS STRING SONAME "libudf_xyz.so"; (never existed), which failed. Error message: "Error Code: 1126. Can't open shared library 'libudf_xyz.so' (errno: 2 dlopen(/usr/local/opt/mysql/lib/plugin/libudf_xyz.so, 0x0002): tried: '/usr/local/opt/mysql/lib/plugin/libudf_xyz.so' (no such f)"
  • plugin_dir: /usr/local/opt/mysql/lib/plugin/ --->(this is where the .so file WAS located, but is not anymore)
  • How did I notice the old behavior was still present? The dead giveaway was that the function used the old error message ("Please use plaintext(int), iv(string), key(string)"), and not the new message ("Please use plaintext(string), iv(string), key(string)") after step no. 4
  • Also add the content of the plugins/ directory, which CREATE FUNCTION uses to load the function: I wrote the library in c++, then built it as a shared library. The c++ code would be as follows (but Im not sure this is relevant):
extern "C" {
    bool decrypt_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
    char *decrypt(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
    void decrypt_deinit(UDF_INIT *initid);
}
bool decrypt_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
    if (args->arg_count != 3 or
        args->arg_type[0] != STRING_RESULT or
        args->arg_type[1] != STRING_RESULT or
        args->arg_type[2] != STRING_RESULT
            ) {
        strcpy(message, "Usage: decrypt_poly(string ctext, string key, string iv)");
        return 1;
    }
    if (args->lengths[2] != 48) {
        strcpy(message, "Only 24-length IVs are allowed. Make sure IV is hexed.");
        return 1;
    }
    initid->ptr = new char[args->lengths[0]];
    initid->maybe_null = 1;

    return 0;
}
char *decrypt(UDF_INIT *initid, UDF_ARGS *args,
                  char *result, unsigned long *length,
                  char *is_null, char *error) {
    std::string dvalue;
    if (NULL != args->args[0]) {
        std::string value = std::string(args->args[0], args->lengths[0]);
        std::string key = std::string(args->args[1], args->lengths[1]);
        std::string iv = std::string(args->args[2], args->lengths[2]);

        try {
            dvalue = ((encryption::poly_based_encryption::decrypt(value, key, iv))));
        }
        catch (CryptoPP::Exception &e) {
            std::cerr << e.what() << std::endl;
            *error = 1;
        }

    } else {
        dvalue = "";
        *is_null = 1;
        *error = 1;
        return NULL;
    }
    strcpy(initid->ptr, dvalue.c_str());
    *length = dvalue.length();
    result = initid->ptr;
    *is_null = 0;
    *error = 0;
    return result;
}
void decrypt_deinit(UDF_INIT *initid) {
    if (initid->ptr)
        delete[] initid->ptr;
}
Carlotta
  • 11
  • 3
  • 1
    Welcome to Stack Overflow. Please [edit] your question to include all the steps you performed from loading the first version of your library to your attempt to load the updated version of your library. Also add the content of the plugins/ directory, which `CREATE FUNCTION` uses to load the function. Add a description how you recognize that the old version is loaded, not the new version. Add any log messages related to this issue to your post as well, including relevant system variables (like the `plugin_dir` variable). – Progman Feb 27 '22 at 13:00
  • 1
    @Progman, thank you very much for your comment. I tried to include all your suggestions, but I'm not sure I really understood what you meant by "content of the plugins". I hope this a bit clearer now anyway. – Carlotta Feb 28 '22 at 10:05
  • It might be a little bit overkill, but can you run `strace mysql 2>test.txt` and do the `DROP FUNCTION` and `CREATE FUNCTION` statements again and quit the `mysql` client again. After that check the (lengthy) content of the `test.txt` file if you can see how any file is loaded from your disks. Maybe you can do the same with the actual MySQL server (something like `strace mysqld 2>server.txt`), but it might be more tricky to get it work, since you might need the correct permissions. And reading/understanding the content of strace isn't easy... – Progman Feb 28 '22 at 18:25
  • Also (separately) try increasing the log level of the MySQL client and the MySQL server to see (hopefully) useful info-messages generated by the MySQL applications itself. Maybe there is some cache being used we don't see. – Progman Feb 28 '22 at 18:27

0 Answers0