Commit 0a0dfd63 authored by Alexey Botchkov's avatar Alexey Botchkov Committed by Oleksandr Byelkin

MDEV-19275 Provide SQL service to plugins.

SQL service added.
It provides the limited set of client library functions
to be used by plugin.
parent 401ff699
...@@ -77,7 +77,7 @@ typedef struct st_mysql_xid MYSQL_XID; ...@@ -77,7 +77,7 @@ typedef struct st_mysql_xid MYSQL_XID;
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104 #define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104
/* MariaDB plugin interface version */ /* MariaDB plugin interface version */
#define MARIA_PLUGIN_INTERFACE_VERSION 0x010e #define MARIA_PLUGIN_INTERFACE_VERSION 0x010f
/* /*
The allowable types of plugins The allowable types of plugins
......
/* Copyright (C) 2021 MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
#if defined(MYSQL_SERVER) && !defined MYSQL_SERVICE_SQL
#define MYSQL_SERVICE_SQL
#include <mysql.h>
/**
@file
SQL service
Interface for plugins to execute SQL queries on the local server.
Functions of the service are the 'server-limited' client library:
mysql_init
mysql_real_connect_local
mysql_real_connect
mysql_errno
mysql_error
mysql_real_query
mysql_affected_rows
mysql_num_rows
mysql_store_result
mysql_free_result
mysql_fetch_row
mysql_close
*/
#ifdef __cplusplus
extern "C" {
#endif
extern struct sql_service_st {
MYSQL *(STDCALL *mysql_init)(MYSQL *mysql);
MYSQL *(*mysql_real_connect_local)(MYSQL *mysql,
const char *host, const char *user, const char *db,
unsigned long clientflag);
MYSQL *(STDCALL *mysql_real_connect)(MYSQL *mysql, const char *host,
const char *user, const char *passwd, const char *db, unsigned int port,
const char *unix_socket, unsigned long clientflag);
unsigned int(STDCALL *mysql_errno)(MYSQL *mysql);
const char *(STDCALL *mysql_error)(MYSQL *mysql);
int (STDCALL *mysql_real_query)(MYSQL *mysql, const char *q,
unsigned long length);
my_ulonglong (STDCALL *mysql_affected_rows)(MYSQL *mysql);
my_ulonglong (STDCALL *mysql_num_rows)(MYSQL_RES *res);
MYSQL_RES *(STDCALL *mysql_store_result)(MYSQL *mysql);
void (STDCALL *mysql_free_result)(MYSQL_RES *result);
MYSQL_ROW (STDCALL *mysql_fetch_row)(MYSQL_RES *result);
void (STDCALL *mysql_close)(MYSQL *sock);
} *sql_service;
#ifdef MYSQL_DYNAMIC_PLUGIN
#define mysql_init sql_service->mysql_init
#define mysql_real_connect_local sql_service->mysql_real_connect_local
#define mysql_real_connect sql_service->mysql_real_connect
#define mysql_errno(M) sql_service->mysql_errno(M)
#define mysql_error(M) sql_service->mysql_error(M)
#define mysql_real_query sql_service->mysql_real_query
#define mysql_affected_rows sql_service->mysql_affected_rows
#define mysql_num_rows sql_service->mysql_num_rows
#define mysql_store_result sql_service->mysql_store_result
#define mysql_free_result sql_service->mysql_free_result
#define mysql_fetch_row sql_service->mysql_fetch_row
#define mysql_close sql_service->mysql_close
#else
MYSQL *mysql_real_connect_local(MYSQL *mysql,
const char *host, const char *user, const char *db,
unsigned long clientflag);
/* The rest of the function declarations mest be taken from the mysql.h */
#endif /*MYSQL_DYNAMIC_PLUGIN*/
#ifdef __cplusplus
}
#endif
#endif /*MYSQL_SERVICE_SQL */
...@@ -41,6 +41,7 @@ extern "C" { ...@@ -41,6 +41,7 @@ extern "C" {
#include <mysql/service_thd_wait.h> #include <mysql/service_thd_wait.h>
#include <mysql/service_json.h> #include <mysql/service_json.h>
/*#include <mysql/service_wsrep.h>*/ /*#include <mysql/service_wsrep.h>*/
#include <mysql/service_sql.h>
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -44,3 +44,4 @@ ...@@ -44,3 +44,4 @@
#define VERSION_wsrep 0x0500 #define VERSION_wsrep 0x0500
#define VERSION_json 0x0100 #define VERSION_json 0x0100
#define VERSION_thd_mdl 0x0100 #define VERSION_thd_mdl 0x0100
#define VERSION_sql_service 0x0100
...@@ -61,13 +61,13 @@ typedef struct st_mysql_methods ...@@ -61,13 +61,13 @@ typedef struct st_mysql_methods
MYSQL_ROW column, unsigned int field_count); MYSQL_ROW column, unsigned int field_count);
void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results); void (*flush_use_result)(MYSQL *mysql, my_bool flush_all_results);
int (*read_change_user_result)(MYSQL *mysql); int (*read_change_user_result)(MYSQL *mysql);
void (*on_close_free)(MYSQL *mysql);
#if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) #if !defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY)
MYSQL_FIELD * (*list_fields)(MYSQL *mysql); MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt); my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
int (*stmt_execute)(MYSQL_STMT *stmt); int (*stmt_execute)(MYSQL_STMT *stmt);
int (*read_binary_rows)(MYSQL_STMT *stmt); int (*read_binary_rows)(MYSQL_STMT *stmt);
int (*unbuffered_fetch)(MYSQL *mysql, char **row); int (*unbuffered_fetch)(MYSQL *mysql, char **row);
void (*free_embedded_thd)(MYSQL *mysql);
const char *(*read_statistics)(MYSQL *mysql); const char *(*read_statistics)(MYSQL *mysql);
my_bool (*next_result)(MYSQL *mysql); my_bool (*next_result)(MYSQL *mysql);
int (*read_rows_from_cursor)(MYSQL_STMT *stmt); int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
......
...@@ -43,7 +43,7 @@ C_MODE_START ...@@ -43,7 +43,7 @@ C_MODE_START
extern unsigned int mysql_server_last_errno; extern unsigned int mysql_server_last_errno;
extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE]; extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
static my_bool emb_read_query_result(MYSQL *mysql); static my_bool emb_read_query_result(MYSQL *mysql);
static void emb_free_embedded_thd(MYSQL *mysql); static void free_embedded_thd(MYSQL *mysql);
static bool embedded_print_errors= 0; static bool embedded_print_errors= 0;
extern "C" void unireg_clear(int exit_code) extern "C" void unireg_clear(int exit_code)
...@@ -121,7 +121,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, ...@@ -121,7 +121,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
thd->killed= NOT_KILLED; thd->killed= NOT_KILLED;
else else
{ {
emb_free_embedded_thd(mysql); free_embedded_thd(mysql);
thd= 0; thd= 0;
} }
} }
...@@ -430,7 +430,7 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row) ...@@ -430,7 +430,7 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row)
return 0; return 0;
} }
static void emb_free_embedded_thd(MYSQL *mysql) static void free_embedded_thd(MYSQL *mysql)
{ {
THD *thd= (THD*)mysql->thd; THD *thd= (THD*)mysql->thd;
server_threads.erase(thd); server_threads.erase(thd);
...@@ -453,12 +453,23 @@ static MYSQL_RES * emb_store_result(MYSQL *mysql) ...@@ -453,12 +453,23 @@ static MYSQL_RES * emb_store_result(MYSQL *mysql)
return mysql_store_result(mysql); return mysql_store_result(mysql);
} }
int emb_read_change_user_result(MYSQL *mysql) static int emb_read_change_user_result(MYSQL *mysql)
{ {
mysql->net.read_pos= (uchar*)""; // fake an OK packet mysql->net.read_pos= (uchar*)""; // fake an OK packet
return mysql_errno(mysql) ? (int)packet_error : 1 /* length of the OK packet */; return mysql_errno(mysql) ? (int)packet_error : 1 /* length of the OK packet */;
} }
static void emb_on_close_free(MYSQL *mysql)
{
my_free(mysql->info_buffer);
mysql->info_buffer= 0;
if (mysql->thd)
{
free_embedded_thd(mysql);
mysql->thd= 0;
}
}
MYSQL_METHODS embedded_methods= MYSQL_METHODS embedded_methods=
{ {
emb_read_query_result, emb_read_query_result,
...@@ -468,12 +479,12 @@ MYSQL_METHODS embedded_methods= ...@@ -468,12 +479,12 @@ MYSQL_METHODS embedded_methods=
emb_fetch_lengths, emb_fetch_lengths,
emb_flush_use_result, emb_flush_use_result,
emb_read_change_user_result, emb_read_change_user_result,
emb_on_close_free,
emb_list_fields, emb_list_fields,
emb_read_prepare_result, emb_read_prepare_result,
emb_stmt_execute, emb_stmt_execute,
emb_read_binary_rows, emb_read_binary_rows,
emb_unbuffered_fetch, emb_unbuffered_fetch,
emb_free_embedded_thd,
emb_read_statistics, emb_read_statistics,
emb_read_query_result, emb_read_query_result,
emb_read_rows_from_cursor emb_read_rows_from_cursor
......
...@@ -38,6 +38,7 @@ SET(MYSQLSERVICES_SOURCES ...@@ -38,6 +38,7 @@ SET(MYSQLSERVICES_SOURCES
thd_wait_service.c thd_wait_service.c
wsrep_service.c wsrep_service.c
json_service.c json_service.c
sql_service.c
) )
ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
......
/* Copyright (c) 2018, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <service_versions.h>
SERVICE_VERSION sql_service= (void*)VERSION_sql_service;
...@@ -5,7 +5,7 @@ plugin_version 1.0 ...@@ -5,7 +5,7 @@ plugin_version 1.0
plugin_status ACTIVE plugin_status ACTIVE
plugin_type DAEMON plugin_type DAEMON
plugin_library handlersocket.so plugin_library handlersocket.so
plugin_library_version 1.14 plugin_library_version 1.15
plugin_author higuchi dot akira at dena dot jp plugin_author higuchi dot akira at dena dot jp
plugin_description Direct access into InnoDB plugin_description Direct access into InnoDB
plugin_license BSD plugin_license BSD
......
...@@ -12,7 +12,7 @@ PLUGIN_STATUS ACTIVE ...@@ -12,7 +12,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE STORAGE ENGINE
PLUGIN_TYPE_VERSION # PLUGIN_TYPE_VERSION #
PLUGIN_LIBRARY ha_example.so PLUGIN_LIBRARY ha_example.so
PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_LIBRARY_VERSION 1.15
PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_AUTHOR Brian Aker, MySQL AB
PLUGIN_DESCRIPTION Example storage engine PLUGIN_DESCRIPTION Example storage engine
PLUGIN_LICENSE GPL PLUGIN_LICENSE GPL
...@@ -25,7 +25,7 @@ PLUGIN_STATUS ACTIVE ...@@ -25,7 +25,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE DAEMON PLUGIN_TYPE DAEMON
PLUGIN_TYPE_VERSION # PLUGIN_TYPE_VERSION #
PLUGIN_LIBRARY ha_example.so PLUGIN_LIBRARY ha_example.so
PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_LIBRARY_VERSION 1.15
PLUGIN_AUTHOR Sergei Golubchik PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Unusable Daemon PLUGIN_DESCRIPTION Unusable Daemon
PLUGIN_LICENSE GPL PLUGIN_LICENSE GPL
...@@ -64,7 +64,7 @@ PLUGIN_STATUS DELETED ...@@ -64,7 +64,7 @@ PLUGIN_STATUS DELETED
PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE STORAGE ENGINE
PLUGIN_TYPE_VERSION # PLUGIN_TYPE_VERSION #
PLUGIN_LIBRARY ha_example.so PLUGIN_LIBRARY ha_example.so
PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_LIBRARY_VERSION 1.15
PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_AUTHOR Brian Aker, MySQL AB
PLUGIN_DESCRIPTION Example storage engine PLUGIN_DESCRIPTION Example storage engine
PLUGIN_LICENSE GPL PLUGIN_LICENSE GPL
......
...@@ -27,7 +27,7 @@ PLUGIN_STATUS ACTIVE ...@@ -27,7 +27,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE AUTHENTICATION PLUGIN_TYPE AUTHENTICATION
PLUGIN_TYPE_VERSION 2.2 PLUGIN_TYPE_VERSION 2.2
PLUGIN_LIBRARY auth_ed25519.so PLUGIN_LIBRARY auth_ed25519.so
PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_LIBRARY_VERSION 1.15
PLUGIN_AUTHOR Sergei Golubchik PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Elliptic curve ED25519 based authentication PLUGIN_DESCRIPTION Elliptic curve ED25519 based authentication
PLUGIN_LICENSE GPL PLUGIN_LICENSE GPL
......
...@@ -6,7 +6,7 @@ PLUGIN_STATUS ACTIVE ...@@ -6,7 +6,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE PASSWORD VALIDATION PLUGIN_TYPE PASSWORD VALIDATION
PLUGIN_TYPE_VERSION 1.0 PLUGIN_TYPE_VERSION 1.0
PLUGIN_LIBRARY cracklib_password_check.so PLUGIN_LIBRARY cracklib_password_check.so
PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_LIBRARY_VERSION 1.15
PLUGIN_AUTHOR Sergei Golubchik PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Password validation via CrackLib PLUGIN_DESCRIPTION Password validation via CrackLib
PLUGIN_LICENSE GPL PLUGIN_LICENSE GPL
......
...@@ -4,8 +4,8 @@ Variable_name Value ...@@ -4,8 +4,8 @@ Variable_name Value
Opened_plugin_libraries 0 Opened_plugin_libraries 0
select * from information_schema.all_plugins where plugin_library='ha_example.so'; select * from information_schema.all_plugins where plugin_library='ha_example.so';
PLUGIN_NAME PLUGIN_VERSION PLUGIN_STATUS PLUGIN_TYPE PLUGIN_TYPE_VERSION PLUGIN_LIBRARY PLUGIN_LIBRARY_VERSION PLUGIN_AUTHOR PLUGIN_DESCRIPTION PLUGIN_LICENSE LOAD_OPTION PLUGIN_MATURITY PLUGIN_AUTH_VERSION PLUGIN_NAME PLUGIN_VERSION PLUGIN_STATUS PLUGIN_TYPE PLUGIN_TYPE_VERSION PLUGIN_LIBRARY PLUGIN_LIBRARY_VERSION PLUGIN_AUTHOR PLUGIN_DESCRIPTION PLUGIN_LICENSE LOAD_OPTION PLUGIN_MATURITY PLUGIN_AUTH_VERSION
EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE MYSQL_VERSION_ID ha_example.so 1.14 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1 EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE MYSQL_VERSION_ID ha_example.so 1.15 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1
UNUSABLE 3.14 NOT INSTALLED DAEMON MYSQL_VERSION_ID ha_example.so 1.14 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926 UNUSABLE 3.14 NOT INSTALLED DAEMON MYSQL_VERSION_ID ha_example.so 1.15 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926
show status like '%libraries%'; show status like '%libraries%';
Variable_name Value Variable_name Value
Opened_plugin_libraries 1 Opened_plugin_libraries 1
......
...@@ -6,7 +6,7 @@ PLUGIN_STATUS ACTIVE ...@@ -6,7 +6,7 @@ PLUGIN_STATUS ACTIVE
PLUGIN_TYPE PASSWORD VALIDATION PLUGIN_TYPE PASSWORD VALIDATION
PLUGIN_TYPE_VERSION 1.0 PLUGIN_TYPE_VERSION 1.0
PLUGIN_LIBRARY simple_password_check.so PLUGIN_LIBRARY simple_password_check.so
PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_LIBRARY_VERSION 1.15
PLUGIN_AUTHOR Sergei Golubchik PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Simple password strength checks PLUGIN_DESCRIPTION Simple password strength checks
PLUGIN_LICENSE GPL PLUGIN_LICENSE GPL
......
install plugin test_sql_service soname 'test_sql_service'; install plugin test_sql_service soname 'test_sql_service';
show status like 'test_sql_service_passed';
Variable_name Value
Test_sql_service_passed 1
set global test_sql_service_run_test= 1; set global test_sql_service_run_test= 1;
show status like 'test_sql_service%'; show status like 'test_sql_service_passed';
Variable_name Value
Test_sql_service_passed 1
set global test_sql_service_execute_sql_local= 'create table test.t1(id int)';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query affected 0 rows.
set global test_sql_service_execute_sql_local= 'insert into test.t1 values (1), (2)';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query affected 2 rows.
set global test_sql_service_execute_sql_local= 'select * from test.t1';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query returned 2 rows.
set global test_sql_service_execute_sql_local= 'drop table test.t1';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query affected 0 rows.
set global test_sql_service_execute_sql_local= 'drop table test.t1';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Error 1051 returned. Unknown table 'test.t1'
set global test_sql_service_execute_sql_global= 'create table test.t1(id int)';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query affected 0 rows.
set global test_sql_service_execute_sql_global= 'insert into test.t1 values (1), (2)';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query affected 2 rows.
set global test_sql_service_execute_sql_global= 'select * from test.t1';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query returned 2 rows.
set global test_sql_service_execute_sql_global= 'drop table test.t1';
show status like 'test_sql_query_result';
Variable_name Value
Test_sql_query_result Query affected 0 rows.
set global test_sql_service_execute_sql_global= 'drop table test.t1';
show status like 'test_sql_query_result';
Variable_name Value Variable_name Value
Test_sql_service_passed 0 Test_sql_query_result Error 1051 returned. Unknown table 'test.t1'
uninstall plugin test_sql_service; uninstall plugin test_sql_service;
Warnings: Warnings:
Warning 1620 Plugin is busy and will be uninstalled on shutdown Warning 1620 Plugin is busy and will be uninstalled on shutdown
...@@ -9,9 +9,40 @@ let count_sessions= 1; ...@@ -9,9 +9,40 @@ let count_sessions= 1;
source include/wait_until_count_sessions.inc; source include/wait_until_count_sessions.inc;
install plugin test_sql_service soname 'test_sql_service'; install plugin test_sql_service soname 'test_sql_service';
show status like 'test_sql_service_passed';
set global test_sql_service_run_test= 1; set global test_sql_service_run_test= 1;
show status like 'test_sql_service%'; show status like 'test_sql_service_passed';
set global test_sql_service_execute_sql_local= 'create table test.t1(id int)';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_local= 'insert into test.t1 values (1), (2)';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_local= 'select * from test.t1';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_local= 'drop table test.t1';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_local= 'drop table test.t1';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_global= 'create table test.t1(id int)';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_global= 'insert into test.t1 values (1), (2)';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_global= 'select * from test.t1';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_global= 'drop table test.t1';
show status like 'test_sql_query_result';
set global test_sql_service_execute_sql_global= 'drop table test.t1';
show status like 'test_sql_query_result';
uninstall plugin test_sql_service; uninstall plugin test_sql_service;
...@@ -15,4 +15,5 @@ ...@@ -15,4 +15,5 @@
SET(SOURCES test_sql_service.c) SET(SOURCES test_sql_service.c)
MYSQL_ADD_PLUGIN(test_sql_service ${SOURCES} MODULE_ONLY RECOMPILE_FOR_EMBEDDED) ADD_DEFINITIONS(-DMYSQL_SERVER)
MYSQL_ADD_PLUGIN(test_sql_service ${SOURCES} MODULE_ONLY)
...@@ -14,71 +14,113 @@ ...@@ -14,71 +14,113 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#define PLUGIN_VERSION 0x100 #define PLUGIN_VERSION 0x20000
#define PLUGIN_STR_VERSION "1.0.0" #define PLUGIN_STR_VERSION "2.0"
#define _my_thread_var loc_thread_var
#include <my_config.h> #include <my_config.h>
#include <assert.h>
#include <my_global.h> #include <my_global.h>
#include <my_base.h> #include <my_base.h>
#include <typelib.h>
//#include <mysql_com.h> /* for enum enum_server_command */
#include <mysql/plugin.h>
#include <mysql/plugin_audit.h> #include <mysql/plugin_audit.h>
//#include <string.h> #include <mysql.h>
LEX_STRING * thd_query_string (MYSQL_THD thd);
unsigned long long thd_query_id(const MYSQL_THD thd);
size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen);
const char *thd_user_name(MYSQL_THD thd);
const char *thd_client_host(MYSQL_THD thd);
const char *thd_client_ip(MYSQL_THD thd);
LEX_CSTRING *thd_current_db(MYSQL_THD thd);
int thd_current_status(MYSQL_THD thd);
enum enum_server_command thd_current_command(MYSQL_THD thd);
int maria_compare_hostname(const char *wild_host, long wild_ip, long ip_mask,
const char *host, const char *ip);
void maria_update_hostname(const char **wild_host, long *wild_ip, long *ip_mask,
const char *host);
/* Status variables for SHOW STATUS */ /* Status variables for SHOW STATUS */
static long test_passed= 0; static long test_passed= 0;
static char *sql_text_local, *sql_text_global;
static char qwe_res[1024]= "";
static struct st_mysql_show_var test_sql_status[]= static struct st_mysql_show_var test_sql_status[]=
{ {
{"test_sql_service_passed", (char *)&test_passed, SHOW_LONG}, {"test_sql_service_passed", (char *)&test_passed, SHOW_LONG},
{"test_sql_query_result", qwe_res, SHOW_CHAR},
{0,0,0} {0,0,0}
}; };
static my_bool do_test= TRUE; static my_bool do_test= TRUE;
static void run_test(MYSQL_THD thd, struct st_mysql_sys_var *var, static int run_test(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
void *var_ptr, const void *save); struct st_mysql_value *value);
static MYSQL_SYSVAR_BOOL(run_test, do_test, PLUGIN_VAR_OPCMDARG, static int run_sql_local(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
"Perform the test now.", NULL, run_test, FALSE); struct st_mysql_value *value);
static int run_sql_global(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
struct st_mysql_value *value);
static void noop_update(MYSQL_THD thd, struct st_mysql_sys_var *var,
void *var_ptr, const void *save);
static MYSQL_SYSVAR_BOOL(run_test, do_test,
PLUGIN_VAR_OPCMDARG,
"Perform the test now.",
run_test, NULL, FALSE);
static MYSQL_SYSVAR_STR(execute_sql_local, sql_text_local,
PLUGIN_VAR_OPCMDARG,
"Create the new local connection, execute SQL statement with it.",
run_sql_local, noop_update, FALSE);
static MYSQL_SYSVAR_STR(execute_sql_global, sql_text_global,
PLUGIN_VAR_OPCMDARG,
"Execute SQL statement using the global connection.",
run_sql_global, noop_update, FALSE);
static struct st_mysql_sys_var* test_sql_vars[]= static struct st_mysql_sys_var* test_sql_vars[]=
{ {
MYSQL_SYSVAR(run_test), MYSQL_SYSVAR(run_test),
MYSQL_SYSVAR(execute_sql_local),
MYSQL_SYSVAR(execute_sql_global),
NULL NULL
}; };
static MYSQL *global_mysql;
static int run_queries(MYSQL *mysql)
{
MYSQL_RES *res;
if (mysql_real_query(mysql,
STRING_WITH_LEN("CREATE TABLE test.ts_table"
" ( hash varbinary(512),"
" time timestamp default current_time,"
" primary key (hash), index tm (time) )")))
return 1;
if (mysql_real_query(mysql,
STRING_WITH_LEN("INSERT INTO test.ts_table VALUES('1234567890', NULL)")))
return 1;
extern int execute_sql_command(const char *command, if (mysql_real_query(mysql, STRING_WITH_LEN("select * from test.ts_table")))
char *hosts, char *names, char *filters); return 1;
if (!(res= mysql_store_result(mysql)))
return 1;
mysql_free_result(res);
if (mysql_real_query(mysql, STRING_WITH_LEN("DROP TABLE test.ts_table")))
return 1;
return 0;
}
static int do_tests() static int do_tests()
{ {
char plugins[1024]; MYSQL *mysql;
char names[1024]; int result= 1;
char dl[2048];
int result; mysql= mysql_init(NULL);
if (mysql_real_connect_local(mysql, NULL, NULL, NULL, 0) == NULL)
return 1;
if (run_queries(mysql))
goto exit;
result= execute_sql_command("select 'plugin', name, dl from mysql.plugin", if (run_queries(global_mysql))
plugins, names, dl); goto exit;
result= 0;
exit:
mysql_close(mysql);
return result; return result;
} }
...@@ -89,12 +131,87 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) ...@@ -89,12 +131,87 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
} }
static void run_test(MYSQL_THD thd __attribute__((unused)), static int run_test(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
struct st_mysql_sys_var *var __attribute__((unused)), struct st_mysql_value *value)
void *var_ptr __attribute__((unused)), {
const void *save __attribute__((unused))) return (test_passed= (do_tests() == 0)) == 0;
}
static int run_sql(MYSQL *mysql, void *save, struct st_mysql_value *value)
{
const char *str;
int len= 0;
MYSQL_RES *res;
str= value->val_str(value, NULL, &len);
if (mysql_real_query(mysql, str, len))
{
if (mysql_error(mysql)[0])
{
my_snprintf(qwe_res, sizeof(qwe_res), "Error %d returned. %s",
mysql_errno(mysql), mysql_error(mysql));
return 0;
}
return 1;
}
if ((res= mysql_store_result(mysql)))
{
my_snprintf(qwe_res, sizeof(qwe_res), "Query returned %lld rows.",
mysql_num_rows(res));
mysql_free_result(res);
}
else
{
if (mysql_error(mysql)[0])
{
my_snprintf(qwe_res, sizeof(qwe_res), "Error %d returned. %s",
mysql_errno(mysql), mysql_error(mysql));
}
else
my_snprintf(qwe_res, sizeof(qwe_res), "Query affected %lld rows.",
mysql_affected_rows(mysql));
}
return 0;
}
static void noop_update(MYSQL_THD thd, struct st_mysql_sys_var *var,
void *var_ptr, const void *save)
{ {
test_passed= do_tests(); sql_text_local= sql_text_global= qwe_res;
}
static int run_sql_local(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
struct st_mysql_value *value)
{
MYSQL *mysql;
int result= 1;
mysql= mysql_init(NULL);
if (mysql_real_connect_local(mysql, NULL, NULL, NULL, 0) == NULL)
return 1;
if (run_sql(mysql, save, value))
goto exit;
result= 0;
exit:
mysql_close(mysql);
return result;
}
static int run_sql_global(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save,
struct st_mysql_value *value)
{
return run_sql(global_mysql, save, value);
} }
...@@ -102,7 +219,16 @@ static int init_done= 0; ...@@ -102,7 +219,16 @@ static int init_done= 0;
static int test_sql_service_plugin_init(void *p __attribute__((unused))) static int test_sql_service_plugin_init(void *p __attribute__((unused)))
{ {
global_mysql= mysql_init(NULL);
if (!global_mysql ||
mysql_real_connect_local(global_mysql, NULL, NULL, NULL, 0) == NULL)
return 1;
init_done= 1; init_done= 1;
test_passed= (do_tests() == 0);
return 0; return 0;
} }
...@@ -112,6 +238,8 @@ static int test_sql_service_plugin_deinit(void *p __attribute__((unused))) ...@@ -112,6 +238,8 @@ static int test_sql_service_plugin_deinit(void *p __attribute__((unused)))
if (!init_done) if (!init_done)
return 0; return 0;
mysql_close(global_mysql);
return 0; return 0;
} }
......
...@@ -1712,14 +1712,14 @@ static MYSQL_METHODS client_methods= ...@@ -1712,14 +1712,14 @@ static MYSQL_METHODS client_methods=
cli_use_result, /* use_result */ cli_use_result, /* use_result */
cli_fetch_lengths, /* fetch_lengths */ cli_fetch_lengths, /* fetch_lengths */
cli_flush_use_result, /* flush_use_result */ cli_flush_use_result, /* flush_use_result */
cli_read_change_user_result /* read_change_user_result */ cli_read_change_user_result, /* read_change_user_result */
NULL /* on_close_free */
#ifndef MYSQL_SERVER #ifndef MYSQL_SERVER
,cli_list_fields, /* list_fields */ ,cli_list_fields, /* list_fields */
cli_read_prepare_result, /* read_prepare_result */ cli_read_prepare_result, /* read_prepare_result */
cli_stmt_execute, /* stmt_execute */ cli_stmt_execute, /* stmt_execute */
cli_read_binary_rows, /* read_binary_rows */ cli_read_binary_rows, /* read_binary_rows */
cli_unbuffered_fetch, /* unbuffered_fetch */ cli_unbuffered_fetch, /* unbuffered_fetch */
NULL, /* free_embedded_thd */
cli_read_statistics, /* read_statistics */ cli_read_statistics, /* read_statistics */
cli_read_query_result, /* next_result */ cli_read_query_result, /* next_result */
cli_read_binary_rows /* read_rows_from_cursor */ cli_read_binary_rows /* read_rows_from_cursor */
...@@ -3319,10 +3319,8 @@ static void mysql_close_free(MYSQL *mysql) ...@@ -3319,10 +3319,8 @@ static void mysql_close_free(MYSQL *mysql)
my_free(mysql->user); my_free(mysql->user);
my_free(mysql->passwd); my_free(mysql->passwd);
my_free(mysql->db); my_free(mysql->db);
#if defined(EMBEDDED_LIBRARY) || MYSQL_VERSION_ID >= 50100 if (mysql->methods && mysql->methods->on_close_free)
my_free(mysql->info_buffer); (*mysql->methods->on_close_free)(mysql);
mysql->info_buffer= 0;
#endif
/* Clear pointers for better safety */ /* Clear pointers for better safety */
mysql->host_info= mysql->user= mysql->passwd= mysql->db= 0; mysql->host_info= mysql->user= mysql->passwd= mysql->db= 0;
} }
...@@ -3441,13 +3439,6 @@ void STDCALL mysql_close(MYSQL *mysql) ...@@ -3441,13 +3439,6 @@ void STDCALL mysql_close(MYSQL *mysql)
mysql_close_free_options(mysql); mysql_close_free_options(mysql);
mysql_close_free(mysql); mysql_close_free(mysql);
mysql_detach_stmt_list(&mysql->stmts, "mysql_close"); mysql_detach_stmt_list(&mysql->stmts, "mysql_close");
#ifndef MYSQL_SERVER
if (mysql->thd)
{
(*mysql->methods->free_embedded_thd)(mysql);
mysql->thd= 0;
}
#endif
if (mysql->free_me) if (mysql->free_me)
my_free(mysql); my_free(mysql);
} }
......
...@@ -1526,6 +1526,16 @@ static void end_ssl(); ...@@ -1526,6 +1526,16 @@ static void end_ssl();
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
extern Atomic_counter<uint32_t> local_connection_thread_count;
uint THD_count::connection_thd_count()
{
return value() -
binlog_dump_thread_count -
local_connection_thread_count;
}
/**************************************************************************** /****************************************************************************
** Code to end mysqld ** Code to end mysqld
****************************************************************************/ ****************************************************************************/
...@@ -1757,7 +1767,7 @@ static void close_connections(void) ...@@ -1757,7 +1767,7 @@ static void close_connections(void)
*/ */
DBUG_PRINT("info", ("THD_count: %u", THD_count::value())); DBUG_PRINT("info", ("THD_count: %u", THD_count::value()));
for (int i= 0; (THD_count::value() - binlog_dump_thread_count) && i < 1000; i++) for (int i= 0; (THD_count::connection_thd_count()) && i < 1000; i++)
my_sleep(20000); my_sleep(20000);
if (global_system_variables.log_warnings) if (global_system_variables.log_warnings)
...@@ -1772,12 +1782,12 @@ static void close_connections(void) ...@@ -1772,12 +1782,12 @@ static void close_connections(void)
/* All threads has now been aborted */ /* All threads has now been aborted */
DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", THD_count::value())); DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", THD_count::value()));
while (THD_count::value() - binlog_dump_thread_count) while (THD_count::connection_thd_count())
my_sleep(1000); my_sleep(1000);
/* Kill phase 2 */ /* Kill phase 2 */
server_threads.iterate(kill_thread_phase_2); server_threads.iterate(kill_thread_phase_2);
for (uint64 i= 0; THD_count::value(); i++) for (uint64 i= 0; THD_count::connection_thd_count(); i++)
{ {
/* /*
This time the warnings are emitted within the loop to provide a This time the warnings are emitted within the loop to provide a
...@@ -5056,6 +5066,7 @@ static int init_server_components() ...@@ -5056,6 +5066,7 @@ static int init_server_components()
init_global_table_stats(); init_global_table_stats();
init_global_index_stats(); init_global_index_stats();
init_update_queries();
/* Allow storage engine to give real error messages */ /* Allow storage engine to give real error messages */
if (unlikely(ha_init_errors())) if (unlikely(ha_init_errors()))
...@@ -5063,6 +5074,9 @@ static int init_server_components() ...@@ -5063,6 +5074,9 @@ static int init_server_components()
tc_log= 0; // ha_initialize_handlerton() needs that tc_log= 0; // ha_initialize_handlerton() needs that
if (ddl_log_initialize())
unireg_abort(1);
if (plugin_init(&remaining_argc, remaining_argv, if (plugin_init(&remaining_argc, remaining_argv,
(opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
(opt_abort ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) (opt_abort ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
...@@ -5304,9 +5318,6 @@ static int init_server_components() ...@@ -5304,9 +5318,6 @@ static int init_server_components()
} }
#endif #endif
if (ddl_log_initialize())
unireg_abort(1);
tc_log= get_tc_log_implementation(); tc_log= get_tc_log_implementation();
if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
...@@ -5387,7 +5398,6 @@ static int init_server_components() ...@@ -5387,7 +5398,6 @@ static int init_server_components()
ft_init_stopwords(); ft_init_stopwords();
init_max_user_conn(); init_max_user_conn();
init_update_queries();
init_global_user_stats(); init_global_user_stats();
init_global_client_stats(); init_global_client_stats();
if (!opt_bootstrap) if (!opt_bootstrap)
......
...@@ -1131,6 +1131,7 @@ struct THD_count ...@@ -1131,6 +1131,7 @@ struct THD_count
{ {
static Atomic_counter<uint32_t> count; static Atomic_counter<uint32_t> count;
static uint value() { return static_cast<uint>(count); } static uint value() { return static_cast<uint>(count); }
static uint connection_thd_count();
THD_count() { count++; } THD_count() { count++; }
~THD_count() { count--; } ~THD_count() { count--; }
}; };
...@@ -3918,6 +3919,11 @@ class THD: public THD_count, /* this must be first */ ...@@ -3918,6 +3919,11 @@ class THD: public THD_count, /* this must be first */
user_time= t; user_time= t;
set_time(); set_time();
} }
inline void force_set_time(my_time_t t, ulong sec_part)
{
start_time= system_time.sec= t;
start_time_sec_part= system_time.sec_part= sec_part;
}
/* /*
this is only used by replication and BINLOG command. this is only used by replication and BINLOG command.
usecs > TIME_MAX_SECOND_PART means "was not in binlog" usecs > TIME_MAX_SECOND_PART means "was not in binlog"
...@@ -3929,15 +3935,9 @@ class THD: public THD_count, /* this must be first */ ...@@ -3929,15 +3935,9 @@ class THD: public THD_count, /* this must be first */
else else
{ {
if (sec_part <= TIME_MAX_SECOND_PART) if (sec_part <= TIME_MAX_SECOND_PART)
{ force_set_time(t, sec_part);
start_time= system_time.sec= t;
start_time_sec_part= system_time.sec_part= sec_part;
}
else if (t != system_time.sec) else if (t != system_time.sec)
{ force_set_time(t, 0);
start_time= system_time.sec= t;
start_time_sec_part= system_time.sec_part= 0;
}
else else
{ {
start_time= t; start_time= t;
......
...@@ -230,6 +230,22 @@ static struct thd_mdl_service_st thd_mdl_handler= ...@@ -230,6 +230,22 @@ static struct thd_mdl_service_st thd_mdl_handler=
thd_mdl_context thd_mdl_context
}; };
struct sql_service_st sql_service_handler=
{
mysql_init,
mysql_real_connect_local,
mysql_real_connect,
mysql_errno,
mysql_error,
mysql_real_query,
mysql_affected_rows,
mysql_num_rows,
mysql_store_result,
mysql_free_result,
mysql_fetch_row,
mysql_close,
};
static struct st_service_ref list_of_services[]= static struct st_service_ref list_of_services[]=
{ {
{ "base64_service", VERSION_base64, &base64_handler }, { "base64_service", VERSION_base64, &base64_handler },
...@@ -254,5 +270,6 @@ static struct st_service_ref list_of_services[]= ...@@ -254,5 +270,6 @@ static struct st_service_ref list_of_services[]=
{ "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler },
{ "wsrep_service", VERSION_wsrep, &wsrep_handler }, { "wsrep_service", VERSION_wsrep, &wsrep_handler },
{ "json_service", VERSION_json, &json_handler }, { "json_service", VERSION_json, &json_handler },
{ "thd_mdl_service", VERSION_thd_mdl, &thd_mdl_handler } { "thd_mdl_service", VERSION_thd_mdl, &thd_mdl_handler },
{ "sql_service", VERSION_sql_service, &sql_service_handler },
}; };
This diff is collapsed.
...@@ -351,4 +351,6 @@ class Ed_row: public Sql_alloc ...@@ -351,4 +351,6 @@ class Ed_row: public Sql_alloc
size_t m_column_count; /* TODO: change to point to metadata */ size_t m_column_count; /* TODO: change to point to metadata */
}; };
extern Atomic_counter<uint32_t> local_connection_thread_count;
#endif // SQL_PREPARE_H #endif // SQL_PREPARE_H
...@@ -14,9 +14,9 @@ along with this program; if not, write to the Free Software ...@@ -14,9 +14,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 - 1301 USA*/
#include <mysql_version.h> #include <mysql_version.h>
#include <mysql/plugin.h>
#include <my_global.h> #include <my_global.h>
#include <mysql/plugin.h>
#include <sql_class.h> #include <sql_class.h>
#include <sql_i_s.h> #include <sql_i_s.h>
#include <mysql/plugin.h> #include <mysql/plugin.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment