I created a MySQL UDF in C++ and uploaded it into the MySQL’s plugin directory. I am able to install the UDF in MySQL, but when I try to call it, the MySQL server stops. I am using visual studio 2019 to create the shared library(.dll in windows) on windows 10 operating system.
I am calling a method from java in my MySQL C++ UDF, I am using graalVM to call the java methods from C++ functions.
I created a shared library out of my java code and I use them in my C++ code to access my java methods.
MySQL UDF code:DemoAgg.cpp
#ifdef STANDARD #include <stdlib.h> #include <stdio.h> #include <string.h> #ifdef __WIN__ typedef unsigned __int64 ulonglong; typedef __int64 longlong; #else typedef unsigned long long ulonglong; typedef long long longlong; #endif /*__WIN__*/ #endif #include <mysql.h> #include <iostream> #include <ctype.h> #include <demolibmysqlagg.h> extern "C" bool test_agg_init(UDF_INIT * initid, UDF_ARGS * args, char* message) { long long* i = new long long; *i = 0; initid->ptr = (char*)i; std::cout << "in init func" << std::endl; if (args->arg_count != 1) { strcpy_s(message, 50, "testagg() requires one arguments"); return 1; } if (args->arg_type[0] != INT_RESULT) { strcpy_s(message, 50, "testagg() requires one integer"); return 1; } return 0; } extern "C" void test_agg_deinit(UDF_INIT * initid) { std::cout << "in deinit func" << std::endl; delete (long long*)initid->ptr; } extern "C" void test_agg_clear(UDF_INIT* initid, char* is_null, char* error) { std::cout << "in clear func" << std::endl; *((long long*)initid->ptr) = 0; } extern "C" void test_agg_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error) { graal_isolate_t* isolate = NULL; graal_isolatethread_t* thread = NULL; std::cout << "in add func" << std::endl; long long int_val; int_val = *((long long*)initid->ptr); long long int_val2; int_val2 = *((long long*)args->args[0]); long long sum; sum = aggadd(thread, int_val, int_val2); //my java method which i call from this program std::cout << sum; *((long long*)initid->ptr) = sum; } extern "C" long long test_agg(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error) { std::cout <<"in main func"<<std::endl; return *((long long*)initid->ptr); }
My Module Definition File:DemoAgg.def
LIBRARY testagg EXPORTS test_agg_init test_agg_deinit test_agg_clear test_agg_add test_agg
My java code:
package testmysql; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.c.function.CEntryPoint; public class demo_mysqlagg { @CEntryPoint (name = "aggadd") public static int aggadd(IsolateThread thread, int x, int y) { return x+y; } }
After building my C++ project, I get a dll file which I copy to the MySQL’s plugin directory.
I install the UDF using the following query:
create aggregate function test_agg returns integer soname 'testagg.dll';
I call my UDF using the following query:
select test_agg(c1) from demo_agg;
where,
demo_agg is a table with only one column.
c1 is the column name of type integer.
But when I execute the above query, the following error pops up:
18:52:53 select test_agg(c1) from demo_agg LIMIT 0, 1000 Error Code: 2013. Lost connection to MySQL server during query 0.063 sec
My error log:
2020-09-29T14:41:24.584058Z 0 [Warning] [MY-010915] [Server] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release. 2020-09-29T14:41:24.587014Z 0 [System] [MY-010116] [Server] C:Program FilesMySQLMySQL Server 8.0binmysqld.exe (mysqld 8.0.21) starting as process 48276 2020-09-29T14:41:24.653757Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. 2020-09-29T14:41:28.123852Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. 2020-09-29T14:41:28.958692Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060 2020-09-29T14:41:30.249252Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. 2020-09-29T14:41:30.250713Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. 2020-09-29T14:41:30.653518Z 0 [System] [MY-010931] [Server] C:Program FilesMySQLMySQL Server 8.0binmysqld.exe: ready for connections. Version: '8.0.21' socket: '' port: 3306 MySQL Community Server - GPL. in init func in clear func in add func 2020-09-29T14:42:49.045501Z 0 [Warning] [MY-010915] [Server] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release. 2020-09-29T14:42:49.053090Z 0 [System] [MY-010116] [Server] C:Program FilesMySQLMySQL Server 8.0binmysqld.exe (mysqld 8.0.21) starting as process 188880 2020-09-29T14:42:49.102031Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. 2020-09-29T14:42:53.150956Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. 2020-09-29T14:42:53.914379Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060 2020-09-29T14:42:54.728381Z 0 [System] [MY-010229] [Server] Starting XA crash recovery... 2020-09-29T14:42:54.737801Z 0 [System] [MY-010232] [Server] XA crash recovery finished. 2020-09-29T14:42:55.464369Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. 2020-09-29T14:42:55.465965Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. 2020-09-29T14:42:56.133327Z 0 [System] [MY-010931] [Server] C:Program FilesMySQLMySQL Server 8.0binmysqld.exe: ready for connections. Version: '8.0.21' socket: '' port: 3306 MySQL Community Server - GPL.
I put some cout statements to know in which function I am.
Can anyone help me out here? What I am doing here? Any kind of help or suggestion will be of great help.
Advertisement
Answer
the problem is with:
graal_isolate_t* isolate = NULL; graal_isolatethread_t* thread = NULL;
they are null, that’s why it is not able to call the java method and the connection is getting timed out.
if I initialize them like this:
if (graal_create_isolate(NULL, &isolate, &thread) != 0) { fprintf(stderr, "initialization errorn"); return; }
then it is working fine.