MDEV-8931: (server part of) session state tracking
System variables tracking
This commit is contained in:
parent
e7608a78ef
commit
c8948b0d0d
@ -288,7 +288,7 @@ enum enum_server_command
|
|||||||
CLIENT_MULTI_RESULTS | \
|
CLIENT_MULTI_RESULTS | \
|
||||||
CLIENT_PS_MULTI_RESULTS | \
|
CLIENT_PS_MULTI_RESULTS | \
|
||||||
CLIENT_SSL_VERIFY_SERVER_CERT | \
|
CLIENT_SSL_VERIFY_SERVER_CERT | \
|
||||||
CLIENT_REMEMBER_OPTIONS | \
|
CLIENT_REMEMBER_OPTIONS | \
|
||||||
MARIADB_CLIENT_PROGRESS | \
|
MARIADB_CLIENT_PROGRESS | \
|
||||||
CLIENT_PLUGIN_AUTH | \
|
CLIENT_PLUGIN_AUTH | \
|
||||||
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \
|
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \
|
||||||
@ -556,9 +556,9 @@ enum enum_mysql_set_option
|
|||||||
*/
|
*/
|
||||||
enum enum_session_state_type
|
enum enum_session_state_type
|
||||||
{
|
{
|
||||||
SESSION_TRACK_SYSTEM_VARIABLES, /* Session system variables */
|
SESSION_TRACK_SYSTEM_VARIABLES, /* Session system variables */
|
||||||
SESSION_TRACK_SCHEMA, /* Current schema */
|
SESSION_TRACK_SCHEMA, /* Current schema */
|
||||||
SESSION_TRACK_STATE_CHANGE, /* track session state changes */
|
SESSION_TRACK_STATE_CHANGE, /* track session state changes */
|
||||||
SESSION_TRACK_GTIDS,
|
SESSION_TRACK_GTIDS,
|
||||||
SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */
|
SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */
|
||||||
SESSION_TRACK_TRANSACTION_STATE /* Transaction state */
|
SESSION_TRACK_TRANSACTION_STATE /* Transaction state */
|
||||||
|
@ -908,6 +908,8 @@ The following options may be given as the first argument:
|
|||||||
(Defaults to on; use --skip-session-track-schema to disable.)
|
(Defaults to on; use --skip-session-track-schema to disable.)
|
||||||
--session-track-state-change
|
--session-track-state-change
|
||||||
Track changes to the 'session state'.
|
Track changes to the 'session state'.
|
||||||
|
--session-track-system-variables=name
|
||||||
|
Track changes in registered system variables.
|
||||||
--show-slave-auth-info
|
--show-slave-auth-info
|
||||||
Show user and password in SHOW SLAVE HOSTS on this
|
Show user and password in SHOW SLAVE HOSTS on this
|
||||||
master.
|
master.
|
||||||
@ -1392,6 +1394,7 @@ secure-file-priv (No default value)
|
|||||||
server-id 1
|
server-id 1
|
||||||
session-track-schema TRUE
|
session-track-schema TRUE
|
||||||
session-track-state-change FALSE
|
session-track-state-change FALSE
|
||||||
|
session-track-system-variables autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
show-slave-auth-info FALSE
|
show-slave-auth-info FALSE
|
||||||
silent-startup FALSE
|
silent-startup FALSE
|
||||||
skip-grant-tables TRUE
|
skip-grant-tables TRUE
|
||||||
|
@ -0,0 +1,162 @@
|
|||||||
|
#
|
||||||
|
# Variable name : session_track_system_variables
|
||||||
|
# Scope : Global & Session
|
||||||
|
#
|
||||||
|
# Global - default
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
# Session - default
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
|
||||||
|
# via INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
|
SESSION_TRACK_SCHEMA ON
|
||||||
|
SESSION_TRACK_STATE_CHANGE OFF
|
||||||
|
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
# via INFORMATION_SCHEMA.SESSION_VARIABLES
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
|
SESSION_TRACK_SCHEMA ON
|
||||||
|
SESSION_TRACK_STATE_CHANGE OFF
|
||||||
|
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
SET @global_saved_tmp = @@global.session_track_system_variables;
|
||||||
|
|
||||||
|
# Altering global variable's value
|
||||||
|
SET @@global.session_track_system_variables='autocommit';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
|
||||||
|
# Altering session variable's value
|
||||||
|
SET @@session.session_track_system_variables='autocommit';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit
|
||||||
|
|
||||||
|
# Variables' values in a new session.
|
||||||
|
connect con1,"127.0.0.1",root,,test,$MASTER_MYPORT,;
|
||||||
|
# Global - expect "autocommit"
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit
|
||||||
|
|
||||||
|
# Session - expect "autocommit"
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit
|
||||||
|
|
||||||
|
# Switching to the default connection.
|
||||||
|
connection default;
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit
|
||||||
|
|
||||||
|
# Test if DEFAULT is working as expected.
|
||||||
|
SET @@global.session_track_system_variables = DEFAULT;
|
||||||
|
SET @@session.session_track_system_variables = DEFAULT;
|
||||||
|
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
|
||||||
|
# Variables' values in a new session (con2).
|
||||||
|
connect con2,"127.0.0.1",root,,test,$MASTER_MYPORT,;
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
|
||||||
|
# Altering session should not affect global.
|
||||||
|
SET @@session.session_track_system_variables = 'sql_mode';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
sql_mode
|
||||||
|
|
||||||
|
# Variables' values in a new session (con3).
|
||||||
|
connect con3,"127.0.0.1",root,,test,$MASTER_MYPORT,;
|
||||||
|
# Altering global should not affect session.
|
||||||
|
SET @@global.session_track_system_variables = 'sql_mode';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
sql_mode
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
|
||||||
|
# Switching to the default connection.
|
||||||
|
connection default;
|
||||||
|
# Testing NULL
|
||||||
|
SET @@global.session_track_system_variables = NULL;
|
||||||
|
SET @@session.session_track_system_variables = NULL;
|
||||||
|
# Global - expect "" instead of NULL
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
NULL
|
||||||
|
# Session - expect "" instead of NULL
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
|
||||||
|
# testing with duplicate entries.
|
||||||
|
SET @@global.session_track_system_variables= "time_zone";
|
||||||
|
SET @@session.session_track_system_variables= "time_zone";
|
||||||
|
SET @@global.session_track_system_variables= "sql_mode,sql_mode";
|
||||||
|
SET @@session.session_track_system_variables= "sql_mode,sql_mode";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
sql_mode
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
sql_mode
|
||||||
|
|
||||||
|
# testing ordering
|
||||||
|
SET @@global.session_track_system_variables= "time_zone,sql_mode";
|
||||||
|
SET @@session.session_track_system_variables= "time_zone,sql_mode";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
sql_mode,time_zone
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
sql_mode,time_zone
|
||||||
|
|
||||||
|
# special values
|
||||||
|
SET @@global.session_track_system_variables= "*";
|
||||||
|
SET @@session.session_track_system_variables= "*";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
*
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
*
|
||||||
|
SET @@global.session_track_system_variables= "";
|
||||||
|
SET @@session.session_track_system_variables= "";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
@@global.session_track_system_variables
|
||||||
|
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
@@session.session_track_system_variables
|
||||||
|
|
||||||
|
|
||||||
|
# Restoring the original values.
|
||||||
|
SET @@global.session_track_system_variables = @global_saved_tmp;
|
||||||
|
# End of tests.
|
@ -3817,6 +3817,20 @@ NUMERIC_BLOCK_SIZE NULL
|
|||||||
ENUM_VALUE_LIST OFF,ON
|
ENUM_VALUE_LIST OFF,ON
|
||||||
READ_ONLY NO
|
READ_ONLY NO
|
||||||
COMMAND_LINE_ARGUMENT OPTIONAL
|
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||||
|
VARIABLE_NAME SESSION_TRACK_SYSTEM_VARIABLES
|
||||||
|
SESSION_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
GLOBAL_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
|
DEFAULT_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
||||||
|
VARIABLE_SCOPE SESSION
|
||||||
|
VARIABLE_TYPE VARCHAR
|
||||||
|
VARIABLE_COMMENT Track changes in registered system variables.
|
||||||
|
NUMERIC_MIN_VALUE NULL
|
||||||
|
NUMERIC_MAX_VALUE NULL
|
||||||
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
|
ENUM_VALUE_LIST NULL
|
||||||
|
READ_ONLY NO
|
||||||
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
VARIABLE_NAME SKIP_EXTERNAL_LOCKING
|
VARIABLE_NAME SKIP_EXTERNAL_LOCKING
|
||||||
SESSION_VALUE NULL
|
SESSION_VALUE NULL
|
||||||
GLOBAL_VALUE ON
|
GLOBAL_VALUE ON
|
||||||
|
@ -0,0 +1,133 @@
|
|||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Variable name : session_track_system_variables
|
||||||
|
--echo # Scope : Global & Session
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo # Global - default
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
--echo # Session - default
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # via INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
|
--disable_warnings
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo # via INFORMATION_SCHEMA.SESSION_VARIABLES
|
||||||
|
--disable_warnings
|
||||||
|
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
# Save the global value to be used to restore the original value.
|
||||||
|
SET @global_saved_tmp = @@global.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Altering global variable's value
|
||||||
|
SET @@global.session_track_system_variables='autocommit';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Altering session variable's value
|
||||||
|
SET @@session.session_track_system_variables='autocommit';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Variables' values in a new session.
|
||||||
|
connect (con1,"127.0.0.1",root,,test,$MASTER_MYPORT,);
|
||||||
|
|
||||||
|
--echo # Global - expect "autocommit"
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
--echo # Session - expect "autocommit"
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Switching to the default connection.
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Test if DEFAULT is working as expected.
|
||||||
|
SET @@global.session_track_system_variables = DEFAULT;
|
||||||
|
SET @@session.session_track_system_variables = DEFAULT;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Variables' values in a new session (con2).
|
||||||
|
connect (con2,"127.0.0.1",root,,test,$MASTER_MYPORT,);
|
||||||
|
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Altering session should not affect global.
|
||||||
|
SET @@session.session_track_system_variables = 'sql_mode';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Variables' values in a new session (con3).
|
||||||
|
connect (con3,"127.0.0.1",root,,test,$MASTER_MYPORT,);
|
||||||
|
|
||||||
|
--echo # Altering global should not affect session.
|
||||||
|
SET @@global.session_track_system_variables = 'sql_mode';
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # Switching to the default connection.
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
--echo # Testing NULL
|
||||||
|
SET @@global.session_track_system_variables = NULL;
|
||||||
|
SET @@session.session_track_system_variables = NULL;
|
||||||
|
|
||||||
|
--echo # Global - expect "" instead of NULL
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
--echo # Session - expect "" instead of NULL
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
|
||||||
|
--echo # testing with duplicate entries.
|
||||||
|
# Lets first set it to some valid value.
|
||||||
|
SET @@global.session_track_system_variables= "time_zone";
|
||||||
|
SET @@session.session_track_system_variables= "time_zone";
|
||||||
|
# Now set with duplicate entries (must pass)
|
||||||
|
SET @@global.session_track_system_variables= "sql_mode,sql_mode";
|
||||||
|
SET @@session.session_track_system_variables= "sql_mode,sql_mode";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # testing ordering
|
||||||
|
SET @@global.session_track_system_variables= "time_zone,sql_mode";
|
||||||
|
SET @@session.session_track_system_variables= "time_zone,sql_mode";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
--echo # special values
|
||||||
|
SET @@global.session_track_system_variables= "*";
|
||||||
|
SET @@session.session_track_system_variables= "*";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
SET @@global.session_track_system_variables= "";
|
||||||
|
SET @@session.session_track_system_variables= "";
|
||||||
|
SELECT @@global.session_track_system_variables;
|
||||||
|
SELECT @@session.session_track_system_variables;
|
||||||
|
--echo
|
||||||
|
|
||||||
|
|
||||||
|
--echo # Restoring the original values.
|
||||||
|
SET @@global.session_track_system_variables = @global_saved_tmp;
|
||||||
|
|
||||||
|
--echo # End of tests.
|
@ -690,6 +690,14 @@ THD *next_global_thread(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct system_variables global_system_variables;
|
struct system_variables global_system_variables;
|
||||||
|
/**
|
||||||
|
Following is just for options parsing, used with a difference against
|
||||||
|
global_system_variables.
|
||||||
|
|
||||||
|
TODO: something should be done to get rid of following variables
|
||||||
|
*/
|
||||||
|
const char *current_dbug_option="";
|
||||||
|
|
||||||
struct system_variables max_system_variables;
|
struct system_variables max_system_variables;
|
||||||
struct system_status_var global_status_var;
|
struct system_status_var global_status_var;
|
||||||
|
|
||||||
@ -1463,7 +1471,6 @@ my_bool plugins_are_initialized= FALSE;
|
|||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
static const char* default_dbug_option;
|
static const char* default_dbug_option;
|
||||||
#endif
|
#endif
|
||||||
const char *current_dbug_option="";
|
|
||||||
#ifdef HAVE_LIBWRAP
|
#ifdef HAVE_LIBWRAP
|
||||||
const char *libwrapName= NULL;
|
const char *libwrapName= NULL;
|
||||||
int allow_severity = LOG_INFO;
|
int allow_severity = LOG_INFO;
|
||||||
@ -5278,6 +5285,17 @@ static int init_server_components()
|
|||||||
}
|
}
|
||||||
plugins_are_initialized= TRUE; /* Don't separate from init function */
|
plugins_are_initialized= TRUE; /* Don't separate from init function */
|
||||||
|
|
||||||
|
{
|
||||||
|
Session_tracker session_track_system_variables_check;
|
||||||
|
if (session_track_system_variables_check.
|
||||||
|
server_boot_verify(system_charset_info))
|
||||||
|
{
|
||||||
|
sql_print_error("The variable session_track_system_variables has "
|
||||||
|
"invalid values.");
|
||||||
|
unireg_abort(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* we do want to exit if there are any other unknown options */
|
/* we do want to exit if there are any other unknown options */
|
||||||
if (remaining_argc > 1)
|
if (remaining_argc > 1)
|
||||||
{
|
{
|
||||||
|
@ -135,6 +135,7 @@ extern my_bool lower_case_file_system;
|
|||||||
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
|
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
|
||||||
extern my_bool opt_secure_auth;
|
extern my_bool opt_secure_auth;
|
||||||
extern const char *current_dbug_option;
|
extern const char *current_dbug_option;
|
||||||
|
extern const char *current_session_track_system_variables;
|
||||||
extern char* opt_secure_file_priv;
|
extern char* opt_secure_file_priv;
|
||||||
extern char* opt_secure_backup_file_priv;
|
extern char* opt_secure_backup_file_priv;
|
||||||
extern size_t opt_secure_backup_file_priv_len;
|
extern size_t opt_secure_backup_file_priv_len;
|
||||||
|
@ -276,7 +276,6 @@ net_send_ok(THD *thd,
|
|||||||
/* the info field */
|
/* the info field */
|
||||||
if (state_changed || (message && message[0]))
|
if (state_changed || (message && message[0]))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(strlen(message) <= MYSQL_ERRMSG_SIZE);
|
|
||||||
store.q_net_store_data((uchar*) message, message ? strlen(message) : 0);
|
store.q_net_store_data((uchar*) message, message ? strlen(message) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
|
||||||
|
#include "sql_plugin.h"
|
||||||
#include "session_tracker.h"
|
#include "session_tracker.h"
|
||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#include "sql_class.h"
|
#include "sql_class.h"
|
||||||
#include "sql_show.h"
|
#include "sql_show.h"
|
||||||
#include "sql_plugin.h"
|
#include "sql_plugin.h"
|
||||||
|
#include "set_var.h"
|
||||||
|
|
||||||
class Not_implemented_tracker : public State_tracker
|
class Not_implemented_tracker : public State_tracker
|
||||||
{
|
{
|
||||||
@ -40,6 +42,182 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static my_bool name_array_filler(void *ptr, void *data_ptr);
|
||||||
|
/**
|
||||||
|
Session_sysvars_tracker
|
||||||
|
|
||||||
|
This is a tracker class that enables & manages the tracking of session
|
||||||
|
system variables. It internally maintains a hash of user supplied variable
|
||||||
|
references and a boolean field to store if the variable was changed by the
|
||||||
|
last statement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Session_sysvars_tracker : public State_tracker
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct sysvar_node_st {
|
||||||
|
sys_var *m_svar;
|
||||||
|
bool *test_load;
|
||||||
|
bool m_changed;
|
||||||
|
};
|
||||||
|
|
||||||
|
class vars_list
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
Registered system variables. (@@session_track_system_variables)
|
||||||
|
A hash to store the name of all the system variables specified by the
|
||||||
|
user.
|
||||||
|
*/
|
||||||
|
HASH m_registered_sysvars;
|
||||||
|
/** Size of buffer for string representation */
|
||||||
|
size_t buffer_length;
|
||||||
|
myf m_mem_flag;
|
||||||
|
/**
|
||||||
|
If TRUE then we want to check all session variable.
|
||||||
|
*/
|
||||||
|
bool track_all;
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
my_hash_init(&m_registered_sysvars,
|
||||||
|
&my_charset_bin,
|
||||||
|
4, 0, 0, (my_hash_get_key) sysvars_get_key,
|
||||||
|
my_free, MYF(HASH_UNIQUE |
|
||||||
|
((m_mem_flag & MY_THREAD_SPECIFIC) ?
|
||||||
|
HASH_THREAD_SPECIFIC : 0)));
|
||||||
|
}
|
||||||
|
void free_hash()
|
||||||
|
{
|
||||||
|
if (my_hash_inited(&m_registered_sysvars))
|
||||||
|
{
|
||||||
|
my_hash_free(&m_registered_sysvars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar* search(const sys_var *svar)
|
||||||
|
{
|
||||||
|
return (my_hash_search(&m_registered_sysvars, (const uchar *)&svar,
|
||||||
|
sizeof(sys_var *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
vars_list() :
|
||||||
|
buffer_length(0)
|
||||||
|
{
|
||||||
|
m_mem_flag= current_thd ? MY_THREAD_SPECIFIC : 0;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_buffer_length()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(buffer_length != 0); // asked earlier then should
|
||||||
|
return buffer_length;
|
||||||
|
}
|
||||||
|
~vars_list()
|
||||||
|
{
|
||||||
|
/* free the allocated hash. */
|
||||||
|
if (my_hash_inited(&m_registered_sysvars))
|
||||||
|
{
|
||||||
|
my_hash_free(&m_registered_sysvars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar* search(sysvar_node_st *node, const sys_var *svar)
|
||||||
|
{
|
||||||
|
uchar *res;
|
||||||
|
res= search(svar);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
if (track_all)
|
||||||
|
{
|
||||||
|
insert(node, svar, m_mem_flag);
|
||||||
|
return search(svar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar* operator[](ulong idx)
|
||||||
|
{
|
||||||
|
return my_hash_element(&m_registered_sysvars, idx);
|
||||||
|
}
|
||||||
|
bool insert(sysvar_node_st *node, const sys_var *svar, myf mem_flag);
|
||||||
|
void reset();
|
||||||
|
void copy(vars_list* from, THD *thd);
|
||||||
|
bool parse_var_list(THD *thd, LEX_STRING var_list, bool throw_error,
|
||||||
|
const CHARSET_INFO *char_set, bool session_created);
|
||||||
|
bool construct_var_list(char *buf, size_t buf_len);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Two objects of vars_list type are maintained to manage
|
||||||
|
various operations.
|
||||||
|
*/
|
||||||
|
vars_list *orig_list, *tool_list;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Session_sysvars_tracker()
|
||||||
|
{
|
||||||
|
orig_list= new (std::nothrow) vars_list();
|
||||||
|
tool_list= new (std::nothrow) vars_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Session_sysvars_tracker()
|
||||||
|
{
|
||||||
|
if (orig_list)
|
||||||
|
delete orig_list;
|
||||||
|
if (tool_list)
|
||||||
|
delete tool_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_buffer_length()
|
||||||
|
{
|
||||||
|
return orig_list->get_buffer_length();
|
||||||
|
}
|
||||||
|
bool construct_var_list(char *buf, size_t buf_len)
|
||||||
|
{
|
||||||
|
return orig_list->construct_var_list(buf, buf_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Method used to check the validity of string provided
|
||||||
|
for session_track_system_variables during the server
|
||||||
|
startup.
|
||||||
|
*/
|
||||||
|
static bool server_init_check(THD *thd, const CHARSET_INFO *char_set,
|
||||||
|
LEX_STRING var_list)
|
||||||
|
{
|
||||||
|
vars_list dummy;
|
||||||
|
bool result;
|
||||||
|
result= dummy.parse_var_list(thd, var_list, false, char_set, false);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
static bool server_init_process(THD *thd, const CHARSET_INFO *char_set,
|
||||||
|
LEX_STRING var_list)
|
||||||
|
{
|
||||||
|
vars_list dummy;
|
||||||
|
bool result;
|
||||||
|
result= dummy.parse_var_list(thd, var_list, false, char_set, false);
|
||||||
|
if (!result)
|
||||||
|
dummy.construct_var_list(var_list.str, var_list.length + 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
bool enable(THD *thd);
|
||||||
|
bool check(THD *thd, set_var *var);
|
||||||
|
bool check_str(THD *thd, LEX_STRING val);
|
||||||
|
bool update(THD *thd);
|
||||||
|
bool store(THD *thd, String *buf);
|
||||||
|
void mark_as_changed(THD *thd, LEX_CSTRING *tracked_item_name);
|
||||||
|
/* callback */
|
||||||
|
static uchar *sysvars_get_key(const char *entry, size_t *length,
|
||||||
|
my_bool not_used __attribute__((unused)));
|
||||||
|
|
||||||
|
friend my_bool name_array_filler(void *ptr, void *data_ptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Current_schema_tracker,
|
Current_schema_tracker,
|
||||||
@ -108,6 +286,540 @@ public:
|
|||||||
/* To be used in expanding the buffer. */
|
/* To be used in expanding the buffer. */
|
||||||
static const unsigned int EXTRA_ALLOC= 1024;
|
static const unsigned int EXTRA_ALLOC= 1024;
|
||||||
|
|
||||||
|
|
||||||
|
void Session_sysvars_tracker::vars_list::reset()
|
||||||
|
{
|
||||||
|
buffer_length= 0;
|
||||||
|
track_all= 0;
|
||||||
|
if (m_registered_sysvars.records)
|
||||||
|
my_hash_reset(&m_registered_sysvars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Copy the given list.
|
||||||
|
|
||||||
|
@param from Source vars_list object.
|
||||||
|
@param thd THD handle to retrive the charset in use.
|
||||||
|
|
||||||
|
@retval true there is something to track
|
||||||
|
@retval false nothing to track
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Session_sysvars_tracker::vars_list::copy(vars_list* from, THD *thd)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
track_all= from->track_all;
|
||||||
|
free_hash();
|
||||||
|
buffer_length= from->buffer_length;
|
||||||
|
m_registered_sysvars= from->m_registered_sysvars;
|
||||||
|
from->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Inserts the variable to be tracked into m_registered_sysvars hash.
|
||||||
|
|
||||||
|
@param node Node to be inserted.
|
||||||
|
@param svar address of the system variable
|
||||||
|
|
||||||
|
@retval false success
|
||||||
|
@retval true error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node,
|
||||||
|
const sys_var *svar,
|
||||||
|
myf mem_flag)
|
||||||
|
{
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
if (!(node= (sysvar_node_st *) my_malloc(sizeof(sysvar_node_st),
|
||||||
|
MYF(MY_WME | mem_flag))))
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node->m_svar= (sys_var *)svar;
|
||||||
|
node->test_load= node->m_svar->test_load;
|
||||||
|
node->m_changed= false;
|
||||||
|
if (my_hash_insert(&m_registered_sysvars, (uchar *) node))
|
||||||
|
{
|
||||||
|
my_free(node);
|
||||||
|
if (!search((sys_var *)svar))
|
||||||
|
{
|
||||||
|
//EOF (error is already reported)
|
||||||
|
reset();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parse the specified system variables list.
|
||||||
|
|
||||||
|
@Note In case of invalid entry a warning is raised per invalid entry.
|
||||||
|
This is done in order to handle 'potentially' valid system
|
||||||
|
variables from uninstalled plugins which might get installed in
|
||||||
|
future.
|
||||||
|
|
||||||
|
|
||||||
|
@param thd [IN] The thd handle.
|
||||||
|
@param var_list [IN] System variable list.
|
||||||
|
@param throw_error [IN] bool when set to true, returns an error
|
||||||
|
in case of invalid/duplicate values.
|
||||||
|
@param char_set [IN] charecter set information used for string
|
||||||
|
manipulations.
|
||||||
|
@param session_created [IN] bool variable which says if the parse is
|
||||||
|
already executed once. The mutex on variables
|
||||||
|
is not acquired if this variable is false.
|
||||||
|
|
||||||
|
@return
|
||||||
|
true Error
|
||||||
|
false Success
|
||||||
|
*/
|
||||||
|
bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
|
||||||
|
LEX_STRING var_list,
|
||||||
|
bool throw_error,
|
||||||
|
const CHARSET_INFO *char_set,
|
||||||
|
bool session_created)
|
||||||
|
{
|
||||||
|
const char separator= ',';
|
||||||
|
char *token, *lasts= NULL;
|
||||||
|
size_t rest= var_list.length;
|
||||||
|
|
||||||
|
if (!var_list.str || var_list.length == 0)
|
||||||
|
{
|
||||||
|
buffer_length= 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcmp(var_list.str,(const char *)"*"))
|
||||||
|
{
|
||||||
|
track_all= true;
|
||||||
|
buffer_length= 2;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_length= var_list.length + 1;
|
||||||
|
token= var_list.str;
|
||||||
|
|
||||||
|
track_all= false;
|
||||||
|
/*
|
||||||
|
If Lock to the plugin mutex is not acquired here itself, it results
|
||||||
|
in having to acquire it multiple times in find_sys_var_ex for each
|
||||||
|
token value. Hence the mutex is handled here to avoid a performance
|
||||||
|
overhead.
|
||||||
|
*/
|
||||||
|
if (!thd || session_created)
|
||||||
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
sys_var *svar;
|
||||||
|
LEX_STRING var;
|
||||||
|
|
||||||
|
lasts= (char *) memchr(token, separator, rest);
|
||||||
|
|
||||||
|
var.str= token;
|
||||||
|
if (lasts)
|
||||||
|
{
|
||||||
|
var.length= (lasts - token);
|
||||||
|
rest-= var.length + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
var.length= rest;
|
||||||
|
|
||||||
|
/* Remove leading/trailing whitespace. */
|
||||||
|
trim_whitespace(char_set, &var);
|
||||||
|
|
||||||
|
if ((svar= find_sys_var_ex(thd, var.str, var.length, throw_error, true)))
|
||||||
|
{
|
||||||
|
if (insert(NULL, svar, m_mem_flag) == TRUE)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else if (throw_error && session_created && thd)
|
||||||
|
{
|
||||||
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||||
|
ER_WRONG_VALUE_FOR_VAR,
|
||||||
|
"%.*s is not a valid system variable and will"
|
||||||
|
"be ignored.", (int)var.length, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (lasts)
|
||||||
|
token= lasts + 1;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!thd || session_created)
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (!thd || session_created)
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct name_array_filler_data
|
||||||
|
{
|
||||||
|
LEX_CSTRING **names;
|
||||||
|
uint idx;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Collects variable references into array */
|
||||||
|
static my_bool name_array_filler(void *ptr, void *data_ptr)
|
||||||
|
{
|
||||||
|
Session_sysvars_tracker::sysvar_node_st *node=
|
||||||
|
(Session_sysvars_tracker::sysvar_node_st *)ptr;
|
||||||
|
name_array_filler_data *data= (struct name_array_filler_data *)data_ptr;
|
||||||
|
if (*node->test_load)
|
||||||
|
data->names[data->idx++]= &node->m_svar->name;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sorts variable references array */
|
||||||
|
static int name_array_sorter(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
LEX_CSTRING **an= (LEX_CSTRING **)a, **bn=(LEX_CSTRING **)b;
|
||||||
|
size_t min= MY_MIN((*an)->length, (*bn)->length);
|
||||||
|
int res= strncmp((*an)->str, (*bn)->str, min);
|
||||||
|
if (res == 0)
|
||||||
|
res= ((int)(*bn)->length)- ((int)(*an)->length);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Construct variable list by internal hash with references
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Session_sysvars_tracker::vars_list::construct_var_list(char *buf,
|
||||||
|
size_t buf_len)
|
||||||
|
{
|
||||||
|
struct name_array_filler_data data;
|
||||||
|
size_t left= buf_len;
|
||||||
|
size_t names_size= m_registered_sysvars.records * sizeof(LEX_CSTRING *);
|
||||||
|
const char separator= ',';
|
||||||
|
|
||||||
|
if (unlikely(buf_len < 1))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (unlikely(track_all))
|
||||||
|
{
|
||||||
|
if (buf_len < 2)
|
||||||
|
return true;
|
||||||
|
buf[0]= '*';
|
||||||
|
buf[1]= '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_registered_sysvars.records == 0)
|
||||||
|
{
|
||||||
|
buf[0]= '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.names= (LEX_CSTRING**)my_safe_alloca(names_size);
|
||||||
|
|
||||||
|
if (unlikely(!data.names))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
data.idx= 0;
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
|
my_hash_iterate(&m_registered_sysvars, &name_array_filler, &data);
|
||||||
|
DBUG_ASSERT(data.idx <= m_registered_sysvars.records);
|
||||||
|
|
||||||
|
|
||||||
|
if (m_registered_sysvars.records == 0)
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
buf[0]= '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_qsort(data.names, data.idx, sizeof(LEX_CSTRING *),
|
||||||
|
&name_array_sorter);
|
||||||
|
|
||||||
|
for(uint i= 0; i < data.idx; i++)
|
||||||
|
{
|
||||||
|
LEX_CSTRING *nm= data.names[i];
|
||||||
|
size_t ln= nm->length + 1;
|
||||||
|
if (ln > left)
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
my_safe_afree(data.names, names_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
memcpy(buf, nm->str, nm->length);
|
||||||
|
buf[nm->length]= separator;
|
||||||
|
buf+= ln;
|
||||||
|
left-= ln;
|
||||||
|
}
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
|
buf--; buf[0]= '\0';
|
||||||
|
my_safe_afree(data.names, names_size);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable session tracker by parsing global value of tracked variables.
|
||||||
|
|
||||||
|
@param thd [IN] The thd handle.
|
||||||
|
|
||||||
|
@retval true Error
|
||||||
|
@retval false Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Session_sysvars_tracker::enable(THD *thd)
|
||||||
|
{
|
||||||
|
sys_var *svar;
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
|
svar= find_sys_var_ex(thd, SESSION_TRACK_SYSTEM_VARIABLES_NAME.str,
|
||||||
|
SESSION_TRACK_SYSTEM_VARIABLES_NAME.length,
|
||||||
|
false, true);
|
||||||
|
DBUG_ASSERT(svar);
|
||||||
|
|
||||||
|
set_var tmp(thd, SHOW_OPT_GLOBAL, svar, &null_lex_str, NULL);
|
||||||
|
svar->session_save_default(thd, &tmp);
|
||||||
|
|
||||||
|
if (tool_list->parse_var_list(thd, tmp.save_result.string_value,
|
||||||
|
true, thd->charset(), false) == true)
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
orig_list->copy(tool_list, thd);
|
||||||
|
m_enabled= true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check system variable name(s).
|
||||||
|
|
||||||
|
@note This function is called from the ON_CHECK() function of the
|
||||||
|
session_track_system_variables' sys_var class.
|
||||||
|
|
||||||
|
@param thd [IN] The thd handle.
|
||||||
|
@param var [IN] A pointer to set_var holding the specified list of
|
||||||
|
system variable names.
|
||||||
|
|
||||||
|
@retval true Error
|
||||||
|
@retval false Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline bool Session_sysvars_tracker::check(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
return check_str(thd, var->save_result.string_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Session_sysvars_tracker::check_str(THD *thd, LEX_STRING val)
|
||||||
|
{
|
||||||
|
tool_list->reset();
|
||||||
|
return tool_list->parse_var_list(thd, val, true,
|
||||||
|
thd->charset(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Once the value of the @@session_track_system_variables has been
|
||||||
|
successfully updated, this function calls
|
||||||
|
Session_sysvars_tracker::vars_list::copy updating the hash in orig_list
|
||||||
|
which represents the system variables to be tracked.
|
||||||
|
|
||||||
|
@note This function is called from the ON_UPDATE() function of the
|
||||||
|
session_track_system_variables' sys_var class.
|
||||||
|
|
||||||
|
@param thd [IN] The thd handle.
|
||||||
|
|
||||||
|
@retval true Error
|
||||||
|
@retval false Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Session_sysvars_tracker::update(THD *thd)
|
||||||
|
{
|
||||||
|
orig_list->copy(tool_list, thd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Store the data for changed system variables in the specified buffer.
|
||||||
|
Once the data is stored, we reset the flags related to state-change
|
||||||
|
(see reset()).
|
||||||
|
|
||||||
|
@param thd [IN] The thd handle.
|
||||||
|
@paran buf [INOUT] Buffer to store the information to.
|
||||||
|
|
||||||
|
@retval true Error
|
||||||
|
@retval false Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Session_sysvars_tracker::store(THD *thd, String *buf)
|
||||||
|
{
|
||||||
|
char val_buf[SHOW_VAR_FUNC_BUFF_SIZE];
|
||||||
|
SHOW_VAR show;
|
||||||
|
const char *value;
|
||||||
|
sysvar_node_st *node;
|
||||||
|
const CHARSET_INFO *charset;
|
||||||
|
size_t val_length, length;
|
||||||
|
int idx= 0;
|
||||||
|
|
||||||
|
/* As its always system variable. */
|
||||||
|
show.type= SHOW_SYS;
|
||||||
|
|
||||||
|
while ((node= (sysvar_node_st *) (*orig_list)[idx]))
|
||||||
|
{
|
||||||
|
if (node->m_changed)
|
||||||
|
{
|
||||||
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
|
if (!*node->test_load)
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sys_var *svar= node->m_svar;
|
||||||
|
show.name= svar->name.str;
|
||||||
|
show.value= (char *) svar;
|
||||||
|
|
||||||
|
value= get_one_variable(thd, &show, OPT_SESSION, SHOW_SYS, NULL,
|
||||||
|
&charset, val_buf, &val_length);
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
|
length= net_length_size(svar->name.length) +
|
||||||
|
svar->name.length +
|
||||||
|
net_length_size(val_length) +
|
||||||
|
val_length;
|
||||||
|
|
||||||
|
compile_time_assert(SESSION_TRACK_SYSTEM_VARIABLES < 251);
|
||||||
|
buf->prep_alloc(1 + net_length_size(length) + length, EXTRA_ALLOC);
|
||||||
|
|
||||||
|
/* Session state type (SESSION_TRACK_SYSTEM_VARIABLES) */
|
||||||
|
buf->q_net_store_length((ulonglong)SESSION_TRACK_SYSTEM_VARIABLES);
|
||||||
|
|
||||||
|
/* Length of the overall entity. */
|
||||||
|
buf->q_net_store_length((ulonglong)length);
|
||||||
|
|
||||||
|
/* System variable's name (length-encoded string). */
|
||||||
|
buf->q_net_store_data((const uchar*)svar->name.str, svar->name.length);
|
||||||
|
|
||||||
|
/* System variable's value (length-encoded string). */
|
||||||
|
buf->q_net_store_data((const uchar*)value, val_length);
|
||||||
|
}
|
||||||
|
++ idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Mark the system variable as changed.
|
||||||
|
|
||||||
|
@param [IN] pointer on a variable
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Session_sysvars_tracker::mark_as_changed(THD *thd,
|
||||||
|
LEX_CSTRING *var)
|
||||||
|
{
|
||||||
|
sysvar_node_st *node= NULL;
|
||||||
|
sys_var *svar= (sys_var *)var;
|
||||||
|
/*
|
||||||
|
Check if the specified system variable is being tracked, if so
|
||||||
|
mark it as changed and also set the class's m_changed flag.
|
||||||
|
*/
|
||||||
|
if ((node= (sysvar_node_st *) (orig_list->search(node, svar))))
|
||||||
|
{
|
||||||
|
node->m_changed= true;
|
||||||
|
m_changed= true;
|
||||||
|
/* do not cache the statement when there is change in session state */
|
||||||
|
thd->lex->safe_to_cache_query= 0;
|
||||||
|
thd->server_status|= SERVER_SESSION_STATE_CHANGED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Supply key to a hash.
|
||||||
|
|
||||||
|
@param entry [IN] A single entry.
|
||||||
|
@param length [OUT] Length of the key.
|
||||||
|
@param not_used Unused.
|
||||||
|
|
||||||
|
@return Pointer to the key buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uchar *Session_sysvars_tracker::sysvars_get_key(const char *entry,
|
||||||
|
size_t *length,
|
||||||
|
my_bool not_used __attribute__((unused)))
|
||||||
|
{
|
||||||
|
*length= sizeof(sys_var *);
|
||||||
|
return (uchar *) &(((sysvar_node_st *) entry)->m_svar);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prepare/reset the m_registered_sysvars hash for next statement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Session_sysvars_tracker::reset()
|
||||||
|
{
|
||||||
|
sysvar_node_st *node;
|
||||||
|
int idx= 0;
|
||||||
|
|
||||||
|
while ((node= (sysvar_node_st *) (*orig_list)[idx]))
|
||||||
|
{
|
||||||
|
node->m_changed= false;
|
||||||
|
++ idx;
|
||||||
|
}
|
||||||
|
m_changed= false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Session_sysvars_tracker* sysvar_tracker(THD *thd)
|
||||||
|
{
|
||||||
|
return (Session_sysvars_tracker*)
|
||||||
|
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sysvartrack_validate_value(THD *thd, const char *str, size_t len)
|
||||||
|
{
|
||||||
|
LEX_STRING tmp= {(char *)str, len};
|
||||||
|
if (thd && sysvar_tracker(thd)->is_enabled())
|
||||||
|
return sysvar_tracker(thd)->check_str(thd, tmp);
|
||||||
|
return Session_sysvars_tracker::server_init_check(thd, system_charset_info,
|
||||||
|
tmp);
|
||||||
|
}
|
||||||
|
bool sysvartrack_reprint_value(THD *thd, char *str, size_t len)
|
||||||
|
{
|
||||||
|
LEX_STRING tmp= {str, len};
|
||||||
|
return Session_sysvars_tracker::server_init_process(thd,
|
||||||
|
system_charset_info,
|
||||||
|
tmp);
|
||||||
|
}
|
||||||
|
bool sysvartrack_update(THD *thd)
|
||||||
|
{
|
||||||
|
return sysvar_tracker(thd)->update(thd);
|
||||||
|
}
|
||||||
|
size_t sysvartrack_value_len(THD *thd)
|
||||||
|
{
|
||||||
|
return sysvar_tracker(thd)->get_buffer_length();
|
||||||
|
}
|
||||||
|
bool sysvartrack_value_construct(THD *thd, char *val, size_t len)
|
||||||
|
{
|
||||||
|
return sysvar_tracker(thd)->construct_var_list(val, len);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,18 +994,11 @@ bool Session_state_change_tracker::is_state_changed(THD *)
|
|||||||
|
|
||||||
Session_tracker::Session_tracker()
|
Session_tracker::Session_tracker()
|
||||||
{
|
{
|
||||||
m_trackers[SESSION_SYSVARS_TRACKER]=
|
for (int i= 0; i <= SESSION_TRACKER_END; i ++)
|
||||||
new (std::nothrow) Not_implemented_tracker;
|
m_trackers[i]= NULL;
|
||||||
m_trackers[CURRENT_SCHEMA_TRACKER]=
|
|
||||||
new (std::nothrow) Current_schema_tracker;
|
|
||||||
m_trackers[SESSION_STATE_CHANGE_TRACKER]=
|
|
||||||
new (std::nothrow) Session_state_change_tracker;
|
|
||||||
m_trackers[SESSION_GTIDS_TRACKER]=
|
|
||||||
new (std::nothrow) Not_implemented_tracker;
|
|
||||||
m_trackers[TRANSACTION_INFO_TRACKER]=
|
|
||||||
new (std::nothrow) Not_implemented_tracker;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Enables the tracker objects.
|
@brief Enables the tracker objects.
|
||||||
|
|
||||||
@ -301,13 +1006,57 @@ Session_tracker::Session_tracker()
|
|||||||
|
|
||||||
@return void
|
@return void
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Session_tracker::enable(THD *thd)
|
void Session_tracker::enable(THD *thd)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Originally and correctly this allocation was in the constructor and
|
||||||
|
deallocation in the destructor, but in this case memory counting
|
||||||
|
system works incorrectly (for example in INSERT DELAYED thread)
|
||||||
|
*/
|
||||||
|
deinit();
|
||||||
|
m_trackers[SESSION_SYSVARS_TRACKER]=
|
||||||
|
new (std::nothrow) Session_sysvars_tracker();
|
||||||
|
m_trackers[CURRENT_SCHEMA_TRACKER]=
|
||||||
|
new (std::nothrow) Current_schema_tracker;
|
||||||
|
m_trackers[SESSION_STATE_CHANGE_TRACKER]=
|
||||||
|
new (std::nothrow) Session_state_change_tracker;
|
||||||
|
m_trackers[SESSION_GTIDS_TRACKER]=
|
||||||
|
new (std::nothrow) Not_implemented_tracker;
|
||||||
|
m_trackers[TRANSACTION_INFO_TRACKER]=
|
||||||
|
new (std::nothrow) Not_implemented_tracker;
|
||||||
|
|
||||||
for (int i= 0; i <= SESSION_TRACKER_END; i ++)
|
for (int i= 0; i <= SESSION_TRACKER_END; i ++)
|
||||||
m_trackers[i]->enable(thd);
|
m_trackers[i]->enable(thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Method called during the server startup to verify the contents
|
||||||
|
of @@session_track_system_variables.
|
||||||
|
|
||||||
|
@retval false Success
|
||||||
|
@retval true Failure
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Session_tracker::server_boot_verify(const CHARSET_INFO *char_set)
|
||||||
|
{
|
||||||
|
Session_sysvars_tracker *server_tracker;
|
||||||
|
bool result;
|
||||||
|
sys_var *svar= find_sys_var_ex(NULL, SESSION_TRACK_SYSTEM_VARIABLES_NAME.str,
|
||||||
|
SESSION_TRACK_SYSTEM_VARIABLES_NAME.length,
|
||||||
|
false, true);
|
||||||
|
DBUG_ASSERT(svar);
|
||||||
|
set_var tmp(NULL, SHOW_OPT_GLOBAL, svar, &null_lex_str, NULL);
|
||||||
|
svar->session_save_default(NULL, &tmp);
|
||||||
|
server_tracker= new (std::nothrow) Session_sysvars_tracker();
|
||||||
|
result= server_tracker->server_init_check(NULL, char_set,
|
||||||
|
tmp.save_result.string_value);
|
||||||
|
delete server_tracker;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Store all change information in the specified buffer.
|
@brief Store all change information in the specified buffer.
|
||||||
|
|
||||||
|
@ -104,6 +104,12 @@ public:
|
|||||||
virtual void mark_as_changed(THD *thd, LEX_CSTRING *name)= 0;
|
virtual void mark_as_changed(THD *thd, LEX_CSTRING *name)= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool sysvartrack_validate_value(THD *thd, const char *str, size_t len);
|
||||||
|
bool sysvartrack_reprint_value(THD *thd, char *str, size_t len);
|
||||||
|
bool sysvartrack_update(THD *thd);
|
||||||
|
size_t sysvartrack_value_len(THD *thd);
|
||||||
|
bool sysvartrack_value_construct(THD *thd, char *val, size_t len);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Session_tracker
|
Session_tracker
|
||||||
@ -134,10 +140,22 @@ public:
|
|||||||
Session_tracker();
|
Session_tracker();
|
||||||
~Session_tracker()
|
~Session_tracker()
|
||||||
{
|
{
|
||||||
for (int i= 0; i <= SESSION_TRACKER_END; i ++)
|
deinit();
|
||||||
delete m_trackers[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* trick to make happy memory accounting system */
|
||||||
|
void deinit()
|
||||||
|
{
|
||||||
|
for (int i= 0; i <= SESSION_TRACKER_END; i ++)
|
||||||
|
{
|
||||||
|
if (m_trackers[i])
|
||||||
|
delete m_trackers[i];
|
||||||
|
m_trackers[i]= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void enable(THD *thd);
|
void enable(THD *thd);
|
||||||
|
bool server_boot_verify(const CHARSET_INFO *char_set);
|
||||||
|
|
||||||
/** Returns the pointer to the tracker object for the specified tracker. */
|
/** Returns the pointer to the tracker object for the specified tracker. */
|
||||||
inline State_tracker *get_tracker(enum_session_tracker tracker) const
|
inline State_tracker *get_tracker(enum_session_tracker tracker) const
|
||||||
|
@ -115,6 +115,9 @@ void sys_var_end()
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool static_test_load= TRUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
sys_var constructor
|
sys_var constructor
|
||||||
|
|
||||||
@ -184,6 +187,8 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
|
|||||||
else
|
else
|
||||||
chain->first= this;
|
chain->first= this;
|
||||||
chain->last= this;
|
chain->last= this;
|
||||||
|
|
||||||
|
test_load= &static_test_load;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sys_var::update(THD *thd, set_var *var)
|
bool sys_var::update(THD *thd, set_var *var)
|
||||||
@ -215,13 +220,14 @@ bool sys_var::update(THD *thd, set_var *var)
|
|||||||
*/
|
*/
|
||||||
if ((var->type == OPT_SESSION) && (!ret))
|
if ((var->type == OPT_SESSION) && (!ret))
|
||||||
{
|
{
|
||||||
|
thd->session_tracker.mark_as_changed(thd, SESSION_SYSVARS_TRACKER,
|
||||||
|
(LEX_CSTRING*)var->var);
|
||||||
/*
|
/*
|
||||||
Here MySQL sends variable name to avoid reporting change of
|
Here MySQL sends variable name to avoid reporting change of
|
||||||
the tracker itself, but we decided that it is not needed
|
the tracker itself, but we decided that it is not needed
|
||||||
*/
|
*/
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
|
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -995,7 +1001,30 @@ int set_var_collation_client::update(THD *thd)
|
|||||||
thd->update_charset(character_set_client, collation_connection,
|
thd->update_charset(character_set_client, collation_connection,
|
||||||
character_set_results);
|
character_set_results);
|
||||||
|
|
||||||
|
/* Mark client collation variables as changed */
|
||||||
|
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
|
||||||
|
{
|
||||||
|
sys_var *svar;
|
||||||
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
|
if ((svar= find_sys_var_ex(thd, "character_set_client",
|
||||||
|
sizeof("character_set_client") - 1,
|
||||||
|
false, true)))
|
||||||
|
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
|
||||||
|
mark_as_changed(thd, (LEX_CSTRING*)svar);
|
||||||
|
if ((svar= find_sys_var_ex(thd, "character_set_results",
|
||||||
|
sizeof("character_set_results") - 1,
|
||||||
|
false, true)))
|
||||||
|
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
|
||||||
|
mark_as_changed(thd, (LEX_CSTRING*)svar);
|
||||||
|
if ((svar= find_sys_var_ex(thd, "character_set_connection",
|
||||||
|
sizeof("character_set_connection") - 1,
|
||||||
|
false, true)))
|
||||||
|
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
|
||||||
|
mark_as_changed(thd, (LEX_CSTRING*)svar);
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
}
|
||||||
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
|
||||||
|
|
||||||
thd->protocol_text.init(thd);
|
thd->protocol_text.init(thd);
|
||||||
thd->protocol_binary.init(thd);
|
thd->protocol_binary.init(thd);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -48,6 +48,9 @@ struct sys_var_chain
|
|||||||
int mysql_add_sys_var_chain(sys_var *chain);
|
int mysql_add_sys_var_chain(sys_var *chain);
|
||||||
int mysql_del_sys_var_chain(sys_var *chain);
|
int mysql_del_sys_var_chain(sys_var *chain);
|
||||||
|
|
||||||
|
|
||||||
|
extern const LEX_CSTRING SESSION_TRACK_SYSTEM_VARIABLES_NAME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A class representing one system variable - that is something
|
A class representing one system variable - that is something
|
||||||
that can be accessed as @@global.variable_name or @@session.variable_name,
|
that can be accessed as @@global.variable_name or @@session.variable_name,
|
||||||
@ -60,6 +63,7 @@ class sys_var: protected Value_source // for double_from_string_with_check
|
|||||||
public:
|
public:
|
||||||
sys_var *next;
|
sys_var *next;
|
||||||
LEX_CSTRING name;
|
LEX_CSTRING name;
|
||||||
|
bool *test_load;
|
||||||
enum flag_enum { GLOBAL, SESSION, ONLY_SESSION, SCOPE_MASK=1023,
|
enum flag_enum { GLOBAL, SESSION, ONLY_SESSION, SCOPE_MASK=1023,
|
||||||
READONLY=1024, ALLOCATED=2048, PARSE_EARLY=4096,
|
READONLY=1024, ALLOCATED=2048, PARSE_EARLY=4096,
|
||||||
NO_SET_STATEMENT=8192, AUTO_SET=16384};
|
NO_SET_STATEMENT=8192, AUTO_SET=16384};
|
||||||
@ -240,6 +244,9 @@ protected:
|
|||||||
|
|
||||||
uchar *global_var_ptr()
|
uchar *global_var_ptr()
|
||||||
{ return ((uchar*)&global_system_variables) + offset; }
|
{ return ((uchar*)&global_system_variables) + offset; }
|
||||||
|
|
||||||
|
friend class Session_sysvars_tracker;
|
||||||
|
friend class Session_tracker;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "sql_plugin.h" /* SHOW_HA_ROWS, SHOW_MY_BOOL */
|
#include "sql_plugin.h" /* SHOW_HA_ROWS, SHOW_MY_BOOL */
|
||||||
|
@ -4064,21 +4064,21 @@ ER_LOCK_OR_ACTIVE_TRANSACTION
|
|||||||
swe "Kan inte utföra kommandot emedan du har en låst tabell eller an aktiv transaktion"
|
swe "Kan inte utföra kommandot emedan du har en låst tabell eller an aktiv transaktion"
|
||||||
ukr "Не можу виконати подану команду тому, що таблиця заблокована або виконується транзакція"
|
ukr "Не можу виконати подану команду тому, що таблиця заблокована або виконується транзакція"
|
||||||
ER_UNKNOWN_SYSTEM_VARIABLE
|
ER_UNKNOWN_SYSTEM_VARIABLE
|
||||||
cze "Neznámá systémová proměnná '%-.64s'"
|
cze "Neznámá systémová proměnná '%-.*s'"
|
||||||
dan "Ukendt systemvariabel '%-.64s'"
|
dan "Ukendt systemvariabel '%-.*s'"
|
||||||
nla "Onbekende systeem variabele '%-.64s'"
|
nla "Onbekende systeem variabele '%-.*s'"
|
||||||
eng "Unknown system variable '%-.64s'"
|
eng "Unknown system variable '%-.*s'"
|
||||||
est "Tundmatu süsteemne muutuja '%-.64s'"
|
est "Tundmatu süsteemne muutuja '%-.*s'"
|
||||||
fre "Variable système '%-.64s' inconnue"
|
fre "Variable système '%-.*s' inconnue"
|
||||||
ger "Unbekannte Systemvariable '%-.64s'"
|
ger "Unbekannte Systemvariable '%-.*s'"
|
||||||
ita "Variabile di sistema '%-.64s' sconosciuta"
|
ita "Variabile di sistema '%-.*s' sconosciuta"
|
||||||
jpn "'%-.64s' は不明なシステム変数です。"
|
jpn "'%-.*s' は不明なシステム変数です。"
|
||||||
por "Variável de sistema '%-.64s' desconhecida"
|
por "Variável de sistema '%-.*s' desconhecida"
|
||||||
rus "Неизвестная системная переменная '%-.64s'"
|
rus "Неизвестная системная переменная '%-.*s'"
|
||||||
serbian "Nepoznata sistemska promenljiva '%-.64s'"
|
serbian "Nepoznata sistemska promenljiva '%-.*s'"
|
||||||
spa "Desconocida variable de sistema '%-.64s'"
|
spa "Desconocida variable de sistema '%-.*s'"
|
||||||
swe "Okänd systemvariabel: '%-.64s'"
|
swe "Okänd systemvariabel: '%-.*s'"
|
||||||
ukr "Невідома системна змінна '%-.64s'"
|
ukr "Невідома системна змінна '%-.*s'"
|
||||||
ER_CRASHED_ON_USAGE
|
ER_CRASHED_ON_USAGE
|
||||||
cze "Tabulka '%-.192s' je označena jako porušená a měla by být opravena"
|
cze "Tabulka '%-.192s' je označena jako porušená a měla by být opravena"
|
||||||
dan "Tabellen '%-.192s' er markeret med fejl og bør repareres"
|
dan "Tabellen '%-.192s' er markeret med fejl og bør repareres"
|
||||||
|
@ -1766,6 +1766,10 @@ THD::~THD()
|
|||||||
lf_hash_put_pins(xid_hash_pins);
|
lf_hash_put_pins(xid_hash_pins);
|
||||||
/* Ensure everything is freed */
|
/* Ensure everything is freed */
|
||||||
status_var.local_memory_used-= sizeof(THD);
|
status_var.local_memory_used-= sizeof(THD);
|
||||||
|
|
||||||
|
/* trick to make happy memory accounting system */
|
||||||
|
session_tracker.deinit();
|
||||||
|
|
||||||
if (status_var.local_memory_used != 0)
|
if (status_var.local_memory_used != 0)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used));
|
DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used));
|
||||||
|
@ -691,6 +691,8 @@ typedef struct system_variables
|
|||||||
|
|
||||||
my_bool session_track_schema;
|
my_bool session_track_schema;
|
||||||
my_bool session_track_state_change;
|
my_bool session_track_state_change;
|
||||||
|
|
||||||
|
char *session_track_system_variables;
|
||||||
} SV;
|
} SV;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -269,6 +269,7 @@ struct st_bookmark
|
|||||||
uint name_len;
|
uint name_len;
|
||||||
int offset;
|
int offset;
|
||||||
uint version;
|
uint version;
|
||||||
|
bool loaded;
|
||||||
char key[1];
|
char key[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -322,6 +323,8 @@ static void unlock_variables(THD *thd, struct system_variables *vars);
|
|||||||
static void cleanup_variables(struct system_variables *vars);
|
static void cleanup_variables(struct system_variables *vars);
|
||||||
static void plugin_vars_free_values(sys_var *vars);
|
static void plugin_vars_free_values(sys_var *vars);
|
||||||
static void restore_ptr_backup(uint n, st_ptr_backup *backup);
|
static void restore_ptr_backup(uint n, st_ptr_backup *backup);
|
||||||
|
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B)
|
||||||
|
#define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B)
|
||||||
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
|
static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
|
||||||
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
|
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
|
||||||
static void reap_plugins(void);
|
static void reap_plugins(void);
|
||||||
@ -1175,6 +1178,13 @@ err:
|
|||||||
DBUG_RETURN(errs > 0 || oks + dupes == 0);
|
DBUG_RETURN(errs > 0 || oks + dupes == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void plugin_variables_deinit(struct st_plugin_int *plugin)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (sys_var *var= plugin->system_vars; var; var= var->next)
|
||||||
|
(*var->test_load)= FALSE;
|
||||||
|
mysql_del_sys_var_chain(plugin->system_vars);
|
||||||
|
}
|
||||||
|
|
||||||
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
|
static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
|
||||||
{
|
{
|
||||||
@ -1226,8 +1236,7 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
|
|||||||
if (ref_check && plugin->ref_count)
|
if (ref_check && plugin->ref_count)
|
||||||
sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
|
sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
|
||||||
plugin->name.str, plugin->ref_count);
|
plugin->name.str, plugin->ref_count);
|
||||||
|
plugin_variables_deinit(plugin);
|
||||||
mysql_del_sys_var_chain(plugin->system_vars);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_del(struct st_plugin_int *plugin)
|
static void plugin_del(struct st_plugin_int *plugin)
|
||||||
@ -1447,7 +1456,7 @@ static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin,
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
if (ret)
|
if (ret)
|
||||||
mysql_del_sys_var_chain(plugin->system_vars);
|
plugin_variables_deinit(plugin);
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
plugin->state= state;
|
plugin->state= state;
|
||||||
@ -2780,22 +2789,24 @@ static void update_func_double(THD *thd, struct st_mysql_sys_var *var,
|
|||||||
System Variables support
|
System Variables support
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length,
|
||||||
sys_var *find_sys_var(THD *thd, const char *str, size_t length)
|
bool throw_error, bool locked)
|
||||||
{
|
{
|
||||||
sys_var *var;
|
sys_var *var;
|
||||||
sys_var_pluginvar *pi= NULL;
|
sys_var_pluginvar *pi= NULL;
|
||||||
plugin_ref plugin;
|
plugin_ref plugin;
|
||||||
DBUG_ENTER("find_sys_var");
|
DBUG_ENTER("find_sys_var_ex");
|
||||||
|
DBUG_PRINT("enter", ("var '%.*s'", (int)length, str));
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
if (!locked)
|
||||||
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
mysql_rwlock_rdlock(&LOCK_system_variables_hash);
|
mysql_rwlock_rdlock(&LOCK_system_variables_hash);
|
||||||
if ((var= intern_find_sys_var(str, length)) &&
|
if ((var= intern_find_sys_var(str, length)) &&
|
||||||
(pi= var->cast_pluginvar()))
|
(pi= var->cast_pluginvar()))
|
||||||
{
|
{
|
||||||
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
||||||
LEX *lex= thd ? thd->lex : 0;
|
LEX *lex= thd ? thd->lex : 0;
|
||||||
if (!(plugin= intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
|
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
|
||||||
var= NULL; /* failed to lock it, it must be uninstalling */
|
var= NULL; /* failed to lock it, it must be uninstalling */
|
||||||
else
|
else
|
||||||
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
|
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
|
||||||
@ -2807,14 +2818,20 @@ sys_var *find_sys_var(THD *thd, const char *str, size_t length)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
if (!locked)
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
if (!var)
|
if (!throw_error && !var)
|
||||||
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
|
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (int)length, (char*) str);
|
||||||
DBUG_RETURN(var);
|
DBUG_RETURN(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sys_var *find_sys_var(THD *thd, const char *str, size_t length)
|
||||||
|
{
|
||||||
|
return find_sys_var_ex(thd, str, length, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
called by register_var, construct_options and test_plugin_options.
|
called by register_var, construct_options and test_plugin_options.
|
||||||
Returns the 'bookmark' for the named variable.
|
Returns the 'bookmark' for the named variable.
|
||||||
@ -3940,6 +3957,14 @@ my_bool mark_changed(int, const struct my_option *opt, char *)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
It is always false to mark global plugin variable unloaded just to be
|
||||||
|
safe because we have no way now to know truth about them.
|
||||||
|
|
||||||
|
TODO: make correct mechanism for global plugin variables
|
||||||
|
*/
|
||||||
|
static bool static_unload= FALSE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create and register system variables supplied from the plugin and
|
Create and register system variables supplied from the plugin and
|
||||||
assigns initial values from corresponding command line arguments.
|
assigns initial values from corresponding command line arguments.
|
||||||
@ -4017,9 +4042,13 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
|
|||||||
|
|
||||||
tmp_backup[tmp->nbackups++].save(&o->name);
|
tmp_backup[tmp->nbackups++].save(&o->name);
|
||||||
if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
|
if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
|
||||||
|
{
|
||||||
varname= var->key + 1;
|
varname= var->key + 1;
|
||||||
|
var->loaded= TRUE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var= NULL;
|
||||||
len= tmp->name.length + strlen(o->name) + 2;
|
len= tmp->name.length + strlen(o->name) + 2;
|
||||||
varname= (char*) alloc_root(mem_root, len);
|
varname= (char*) alloc_root(mem_root, len);
|
||||||
strxmov(varname, tmp->name.str, "-", o->name, NullS);
|
strxmov(varname, tmp->name.str, "-", o->name, NullS);
|
||||||
@ -4027,6 +4056,9 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
|
|||||||
convert_dash_to_underscore(varname, len-1);
|
convert_dash_to_underscore(varname, len-1);
|
||||||
}
|
}
|
||||||
v= new (mem_root) sys_var_pluginvar(&chain, varname, tmp, o);
|
v= new (mem_root) sys_var_pluginvar(&chain, varname, tmp, o);
|
||||||
|
v->test_load= (var ? &var->loaded : &static_unload);
|
||||||
|
DBUG_ASSERT(static_unload == FALSE);
|
||||||
|
|
||||||
if (!(o->flags & PLUGIN_VAR_NOCMDOPT))
|
if (!(o->flags & PLUGIN_VAR_NOCMDOPT))
|
||||||
{
|
{
|
||||||
// update app_type, used for I_S.SYSTEM_VARIABLES
|
// update app_type, used for I_S.SYSTEM_VARIABLES
|
||||||
|
@ -192,4 +192,6 @@ extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
|
|||||||
extern bool plugin_dl_foreach(THD *thd, const LEX_STRING *dl,
|
extern bool plugin_dl_foreach(THD *thd, const LEX_STRING *dl,
|
||||||
plugin_foreach_func *func, void *arg);
|
plugin_foreach_func *func, void *arg);
|
||||||
|
|
||||||
|
sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length,
|
||||||
|
bool throw_error, bool locked);
|
||||||
#endif
|
#endif
|
||||||
|
230
sql/sql_show.cc
230
sql/sql_show.cc
@ -3212,6 +3212,132 @@ void remove_status_vars(SHOW_VAR *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Returns the value of a system or a status variable.
|
||||||
|
|
||||||
|
@param thd [in] The handle of the current THD.
|
||||||
|
@param variable [in] Details of the variable.
|
||||||
|
@param value_type [in] Variable type.
|
||||||
|
@param show_type [in] Variable show type.
|
||||||
|
@param charset [out] Character set of the value.
|
||||||
|
@param buff [in,out] Buffer to store the value.
|
||||||
|
(Needs to have enough memory
|
||||||
|
to hold the value of variable.)
|
||||||
|
@param length [out] Length of the value.
|
||||||
|
|
||||||
|
@return Pointer to the value buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char* get_one_variable(THD *thd,
|
||||||
|
const SHOW_VAR *variable,
|
||||||
|
enum_var_type value_type, SHOW_TYPE show_type,
|
||||||
|
system_status_var *status_var,
|
||||||
|
const CHARSET_INFO **charset, char *buff,
|
||||||
|
size_t *length)
|
||||||
|
{
|
||||||
|
void *value= variable->value;
|
||||||
|
const char *pos= buff;
|
||||||
|
const char *end= buff;
|
||||||
|
|
||||||
|
|
||||||
|
if (show_type == SHOW_SYS)
|
||||||
|
{
|
||||||
|
sys_var *var= (sys_var *) value;
|
||||||
|
show_type= var->show_type();
|
||||||
|
value= var->value_ptr(thd, value_type, &null_lex_str);
|
||||||
|
*charset= var->charset(thd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
note that value may be == buff. All SHOW_xxx code below
|
||||||
|
should still work in this case
|
||||||
|
*/
|
||||||
|
switch (show_type) {
|
||||||
|
case SHOW_DOUBLE_STATUS:
|
||||||
|
value= ((char *) status_var + (intptr) value);
|
||||||
|
/* fall through */
|
||||||
|
case SHOW_DOUBLE:
|
||||||
|
/* 6 is the default precision for '%f' in sprintf() */
|
||||||
|
end= buff + my_fcvt(*(double *) value, 6, buff, NULL);
|
||||||
|
break;
|
||||||
|
case SHOW_LONG_STATUS:
|
||||||
|
value= ((char *) status_var + (intptr) value);
|
||||||
|
/* fall through */
|
||||||
|
case SHOW_ULONG:
|
||||||
|
case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
|
||||||
|
end= int10_to_str(*(long*) value, buff, 10);
|
||||||
|
break;
|
||||||
|
case SHOW_LONGLONG_STATUS:
|
||||||
|
value= ((char *) status_var + (intptr) value);
|
||||||
|
/* fall through */
|
||||||
|
case SHOW_ULONGLONG:
|
||||||
|
end= longlong10_to_str(*(longlong*) value, buff, 10);
|
||||||
|
break;
|
||||||
|
case SHOW_HA_ROWS:
|
||||||
|
end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
|
||||||
|
break;
|
||||||
|
case SHOW_BOOL:
|
||||||
|
end= strmov(buff, *(bool*) value ? "ON" : "OFF");
|
||||||
|
break;
|
||||||
|
case SHOW_MY_BOOL:
|
||||||
|
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
|
||||||
|
break;
|
||||||
|
case SHOW_UINT:
|
||||||
|
end= int10_to_str((long) *(uint*) value, buff, 10);
|
||||||
|
break;
|
||||||
|
case SHOW_SINT:
|
||||||
|
end= int10_to_str((long) *(int*) value, buff, -10);
|
||||||
|
break;
|
||||||
|
case SHOW_SLONG:
|
||||||
|
end= int10_to_str(*(long*) value, buff, -10);
|
||||||
|
break;
|
||||||
|
case SHOW_SLONGLONG:
|
||||||
|
end= longlong10_to_str(*(longlong*) value, buff, -10);
|
||||||
|
break;
|
||||||
|
case SHOW_HAVE:
|
||||||
|
{
|
||||||
|
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
|
||||||
|
pos= show_comp_option_name[(int) tmp];
|
||||||
|
end= strend(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHOW_CHAR:
|
||||||
|
{
|
||||||
|
if (!(pos= (char*)value))
|
||||||
|
pos= "";
|
||||||
|
end= strend(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHOW_CHAR_PTR:
|
||||||
|
{
|
||||||
|
if (!(pos= *(char**) value))
|
||||||
|
pos= "";
|
||||||
|
|
||||||
|
end= strend(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHOW_LEX_STRING:
|
||||||
|
{
|
||||||
|
LEX_STRING *ls=(LEX_STRING*)value;
|
||||||
|
if (!(pos= ls->str))
|
||||||
|
end= pos= "";
|
||||||
|
else
|
||||||
|
end= pos + ls->length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHOW_UNDEF:
|
||||||
|
break; // Return empty string
|
||||||
|
case SHOW_SYS: // Cannot happen
|
||||||
|
default:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*length= (size_t) (end - pos);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool show_status_array(THD *thd, const char *wild,
|
static bool show_status_array(THD *thd, const char *wild,
|
||||||
SHOW_VAR *variables,
|
SHOW_VAR *variables,
|
||||||
enum enum_var_type scope,
|
enum enum_var_type scope,
|
||||||
@ -3324,109 +3450,21 @@ static bool show_status_array(THD *thd, const char *wild,
|
|||||||
name_buffer, wild))) &&
|
name_buffer, wild))) &&
|
||||||
(!cond || cond->val_int()))
|
(!cond || cond->val_int()))
|
||||||
{
|
{
|
||||||
void *value=var->value;
|
const char *pos; // We assign a lot of const's
|
||||||
const char *pos, *end; // We assign a lot of const's
|
size_t length;
|
||||||
|
|
||||||
if (show_type == SHOW_SYS)
|
if (show_type == SHOW_SYS)
|
||||||
{
|
|
||||||
sys_var *var= (sys_var *) value;
|
|
||||||
show_type= var->show_type();
|
|
||||||
mysql_mutex_lock(&LOCK_global_system_variables);
|
mysql_mutex_lock(&LOCK_global_system_variables);
|
||||||
value= var->value_ptr(thd, scope, &null_lex_str);
|
pos= get_one_variable(thd, var, scope, show_type, status_var,
|
||||||
charset= var->charset(thd);
|
&charset, buff, &length);
|
||||||
}
|
|
||||||
|
|
||||||
pos= end= buff;
|
table->field[1]->store(pos, (uint32) length, charset);
|
||||||
/*
|
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||||
note that value may be == buff. All SHOW_xxx code below
|
|
||||||
should still work in this case
|
|
||||||
*/
|
|
||||||
switch (show_type) {
|
|
||||||
case SHOW_DOUBLE_STATUS:
|
|
||||||
value= ((char *) status_var + (intptr) value);
|
|
||||||
/* fall through */
|
|
||||||
case SHOW_DOUBLE:
|
|
||||||
/* 6 is the default precision for '%f' in sprintf() */
|
|
||||||
end= buff + my_fcvt(*(double *) value, 6, buff, NULL);
|
|
||||||
break;
|
|
||||||
case SHOW_LONG_STATUS:
|
|
||||||
value= ((char *) status_var + (intptr) value);
|
|
||||||
/* fall through */
|
|
||||||
case SHOW_ULONG:
|
|
||||||
case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
|
|
||||||
end= int10_to_str(*(long*) value, buff, 10);
|
|
||||||
break;
|
|
||||||
case SHOW_LONGLONG_STATUS:
|
|
||||||
value= ((char *) status_var + (intptr) value);
|
|
||||||
/* fall through */
|
|
||||||
case SHOW_ULONGLONG:
|
|
||||||
end= longlong10_to_str(*(longlong*) value, buff, 10);
|
|
||||||
break;
|
|
||||||
case SHOW_HA_ROWS:
|
|
||||||
end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
|
|
||||||
break;
|
|
||||||
case SHOW_BOOL:
|
|
||||||
end= strmov(buff, *(bool*) value ? "ON" : "OFF");
|
|
||||||
break;
|
|
||||||
case SHOW_MY_BOOL:
|
|
||||||
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
|
|
||||||
break;
|
|
||||||
case SHOW_UINT:
|
|
||||||
end= int10_to_str((long) *(uint*) value, buff, 10);
|
|
||||||
break;
|
|
||||||
case SHOW_SINT:
|
|
||||||
end= int10_to_str((long) *(int*) value, buff, -10);
|
|
||||||
break;
|
|
||||||
case SHOW_SLONG:
|
|
||||||
end= int10_to_str(*(long*) value, buff, -10);
|
|
||||||
break;
|
|
||||||
case SHOW_SLONGLONG:
|
|
||||||
end= longlong10_to_str(*(longlong*) value, buff, -10);
|
|
||||||
break;
|
|
||||||
case SHOW_HAVE:
|
|
||||||
{
|
|
||||||
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
|
|
||||||
pos= show_comp_option_name[(int) tmp];
|
|
||||||
end= strend(pos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHOW_CHAR:
|
|
||||||
{
|
|
||||||
if (!(pos= (char*)value))
|
|
||||||
pos= "";
|
|
||||||
end= strend(pos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHOW_CHAR_PTR:
|
|
||||||
{
|
|
||||||
if (!(pos= *(char**) value))
|
|
||||||
pos= "";
|
|
||||||
|
|
||||||
end= strend(pos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHOW_LEX_STRING:
|
|
||||||
{
|
|
||||||
LEX_STRING *ls=(LEX_STRING*)value;
|
|
||||||
if (!(pos= ls->str))
|
|
||||||
end= pos= "";
|
|
||||||
else
|
|
||||||
end= pos + ls->length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHOW_UNDEF:
|
|
||||||
break; // Return empty string
|
|
||||||
case SHOW_SYS: // Cannot happen
|
|
||||||
default:
|
|
||||||
DBUG_ASSERT(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
table->field[1]->store(pos, (uint32) (end - pos), charset);
|
|
||||||
table->field[1]->set_notnull();
|
table->field[1]->set_notnull();
|
||||||
|
if (show_type == SHOW_SYS)
|
||||||
if (var->type == SHOW_SYS)
|
|
||||||
mysql_mutex_unlock(&LOCK_global_system_variables);
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
||||||
|
|
||||||
|
|
||||||
if (schema_table_store_record(thd, table))
|
if (schema_table_store_record(thd, table))
|
||||||
{
|
{
|
||||||
res= TRUE;
|
res= TRUE;
|
||||||
|
@ -131,6 +131,12 @@ bool get_schema_tables_result(JOIN *join,
|
|||||||
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
|
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
|
||||||
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list);
|
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list);
|
||||||
|
|
||||||
|
const char* get_one_variable(THD *thd, const SHOW_VAR *variable,
|
||||||
|
enum_var_type value_type, SHOW_TYPE show_type,
|
||||||
|
system_status_var *status_var,
|
||||||
|
const CHARSET_INFO **charset, char *buff,
|
||||||
|
size_t *length);
|
||||||
|
|
||||||
/* These functions were under INNODB_COMPATIBILITY_HOOKS */
|
/* These functions were under INNODB_COMPATIBILITY_HOOKS */
|
||||||
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
|
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
|
||||||
THD *find_thread_by_id(longlong id, bool query_id= false);
|
THD *find_thread_by_id(longlong id, bool query_id= false);
|
||||||
|
@ -359,7 +359,9 @@ public:
|
|||||||
if (ALIGN_SIZE(arg_length+1) < Alloced_length)
|
if (ALIGN_SIZE(arg_length+1) < Alloced_length)
|
||||||
{
|
{
|
||||||
char *new_ptr;
|
char *new_ptr;
|
||||||
if (!(new_ptr=(char*) my_realloc(Ptr,arg_length,MYF(0))))
|
if (!(new_ptr=(char*)
|
||||||
|
my_realloc(Ptr, arg_length,MYF((thread_specific ?
|
||||||
|
MY_THREAD_SPECIFIC : 0)))))
|
||||||
{
|
{
|
||||||
Alloced_length = 0;
|
Alloced_length = 0;
|
||||||
real_alloc(arg_length);
|
real_alloc(arg_length);
|
||||||
|
@ -5375,6 +5375,16 @@ static Sys_var_ulong Sys_log_tc_size(
|
|||||||
BLOCK_SIZE(my_getpagesize()));
|
BLOCK_SIZE(my_getpagesize()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const LEX_CSTRING SESSION_TRACK_SYSTEM_VARIABLES_NAME=
|
||||||
|
{STRING_WITH_LEN("session_track_system_variables")};
|
||||||
|
|
||||||
|
static Sys_var_sesvartrack Sys_track_session_sys_vars(
|
||||||
|
SESSION_TRACK_SYSTEM_VARIABLES_NAME.str,
|
||||||
|
"Track changes in registered system variables.",
|
||||||
|
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
|
||||||
|
DEFAULT("autocommit,character_set_client,character_set_connection,"
|
||||||
|
"character_set_results,time_zone"),
|
||||||
|
NO_MUTEX_GUARD);
|
||||||
|
|
||||||
static bool update_session_track_schema(sys_var *self, THD *thd,
|
static bool update_session_track_schema(sys_var *self, THD *thd,
|
||||||
enum_var_type type)
|
enum_var_type type)
|
||||||
|
129
sql/sys_vars.ic
129
sql/sys_vars.ic
@ -438,10 +438,10 @@ public:
|
|||||||
does not destroy individual members of SV, there's no way to free
|
does not destroy individual members of SV, there's no way to free
|
||||||
allocated string variables for every thread.
|
allocated string variables for every thread.
|
||||||
*/
|
*/
|
||||||
class Sys_var_charptr: public sys_var
|
class Sys_var_charptr_base: public sys_var
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sys_var_charptr(const char *name_arg,
|
Sys_var_charptr_base(const char *name_arg,
|
||||||
const char *comment, int flag_args, ptrdiff_t off, size_t size,
|
const char *comment, int flag_args, ptrdiff_t off, size_t size,
|
||||||
CMD_LINE getopt,
|
CMD_LINE getopt,
|
||||||
enum charset_enum is_os_charset_arg,
|
enum charset_enum is_os_charset_arg,
|
||||||
@ -463,8 +463,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
|
option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
|
||||||
global_var(const char*)= def_val;
|
global_var(const char*)= def_val;
|
||||||
SYSVAR_ASSERT(scope() == GLOBAL);
|
|
||||||
SYSVAR_ASSERT(size == sizeof(char *));
|
|
||||||
}
|
}
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
@ -503,31 +501,35 @@ public:
|
|||||||
}
|
}
|
||||||
bool do_check(THD *thd, set_var *var)
|
bool do_check(THD *thd, set_var *var)
|
||||||
{ return do_string_check(thd, var, charset(thd)); }
|
{ return do_string_check(thd, var, charset(thd)); }
|
||||||
bool session_update(THD *thd, set_var *var)
|
bool session_update(THD *thd, set_var *var)= 0;
|
||||||
{
|
char *global_update_prepare(THD *thd, set_var *var)
|
||||||
DBUG_ASSERT(FALSE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool global_update(THD *thd, set_var *var)
|
|
||||||
{
|
{
|
||||||
char *new_val, *ptr= var->save_result.string_value.str;
|
char *new_val, *ptr= var->save_result.string_value.str;
|
||||||
size_t len=var->save_result.string_value.length;
|
size_t len=var->save_result.string_value.length;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME));
|
new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME));
|
||||||
if (!new_val) return true;
|
if (!new_val) return 0;
|
||||||
new_val[len]=0;
|
new_val[len]=0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
new_val= 0;
|
new_val= 0;
|
||||||
|
return new_val;
|
||||||
|
}
|
||||||
|
void global_update_finish(char *new_val)
|
||||||
|
{
|
||||||
if (flags & ALLOCATED)
|
if (flags & ALLOCATED)
|
||||||
my_free(global_var(char*));
|
my_free(global_var(char*));
|
||||||
flags|= ALLOCATED;
|
flags|= ALLOCATED;
|
||||||
global_var(char*)= new_val;
|
global_var(char*)= new_val;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
void session_save_default(THD *thd, set_var *var)
|
bool global_update(THD *thd, set_var *var)
|
||||||
{ DBUG_ASSERT(FALSE); }
|
{
|
||||||
|
char *new_val= global_update_prepare(thd, var);
|
||||||
|
global_update_finish(new_val);
|
||||||
|
return (new_val == 0 && var->save_result.string_value.str != 0);
|
||||||
|
}
|
||||||
|
void session_save_default(THD *thd, set_var *var)= 0;
|
||||||
void global_save_default(THD *thd, set_var *var)
|
void global_save_default(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
char *ptr= (char*)(intptr)option.def_value;
|
char *ptr= (char*)(intptr)option.def_value;
|
||||||
@ -536,6 +538,105 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Sys_var_charptr: public Sys_var_charptr_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sys_var_charptr(const char *name_arg,
|
||||||
|
const char *comment, int flag_args, ptrdiff_t off, size_t size,
|
||||||
|
CMD_LINE getopt,
|
||||||
|
enum charset_enum is_os_charset_arg,
|
||||||
|
const char *def_val, PolyLock *lock=0,
|
||||||
|
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
|
||||||
|
on_check_function on_check_func=0,
|
||||||
|
on_update_function on_update_func=0,
|
||||||
|
const char *substitute=0) :
|
||||||
|
Sys_var_charptr_base(name_arg, comment, flag_args, off, size, getopt,
|
||||||
|
is_os_charset_arg, def_val, lock, binlog_status_arg,
|
||||||
|
on_check_func, on_update_func, substitute)
|
||||||
|
{
|
||||||
|
SYSVAR_ASSERT(scope() == GLOBAL);
|
||||||
|
SYSVAR_ASSERT(size == sizeof(char *));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool session_update(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(FALSE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void session_save_default(THD *thd, set_var *var)
|
||||||
|
{ DBUG_ASSERT(FALSE); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sys_var_sesvartrack: public Sys_var_charptr_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sys_var_sesvartrack(const char *name_arg,
|
||||||
|
const char *comment,
|
||||||
|
CMD_LINE getopt,
|
||||||
|
enum charset_enum is_os_charset_arg,
|
||||||
|
const char *def_val, PolyLock *lock) :
|
||||||
|
Sys_var_charptr_base(name_arg, comment,
|
||||||
|
SESSION_VAR(session_track_system_variables),
|
||||||
|
getopt, is_os_charset_arg, def_val, lock,
|
||||||
|
VARIABLE_NOT_IN_BINLOG, 0, 0, 0)
|
||||||
|
{}
|
||||||
|
bool do_check(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
if (Sys_var_charptr_base::do_check(thd, var) ||
|
||||||
|
sysvartrack_validate_value(thd, var->save_result.string_value.str,
|
||||||
|
var->save_result.string_value.length))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
bool global_update(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
char *new_val= global_update_prepare(thd, var);
|
||||||
|
if (new_val)
|
||||||
|
{
|
||||||
|
if (sysvartrack_reprint_value(thd, new_val,
|
||||||
|
var->save_result.string_value.length))
|
||||||
|
new_val= 0;
|
||||||
|
}
|
||||||
|
global_update_finish(new_val);
|
||||||
|
return (new_val == 0 && var->save_result.string_value.str != 0);
|
||||||
|
}
|
||||||
|
bool session_update(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
return sysvartrack_update(thd);
|
||||||
|
}
|
||||||
|
void session_save_default(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
var->save_result.string_value.str= global_var(char*);
|
||||||
|
var->save_result.string_value.length=
|
||||||
|
strlen(var->save_result.string_value.str);
|
||||||
|
/* parse and feel list with default values */
|
||||||
|
if (thd)
|
||||||
|
{
|
||||||
|
bool res=
|
||||||
|
sysvartrack_validate_value(thd,
|
||||||
|
var->save_result.string_value.str,
|
||||||
|
var->save_result.string_value.length);
|
||||||
|
DBUG_ASSERT(res == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(thd != NULL);
|
||||||
|
size_t len= sysvartrack_value_len(thd);
|
||||||
|
char *res= 0;
|
||||||
|
char *buf= (char *)my_safe_alloca(len);
|
||||||
|
if (buf && !sysvartrack_value_construct(thd, buf, len))
|
||||||
|
{
|
||||||
|
size_t len= strlen(buf) + 1;
|
||||||
|
res= (char*) thd->alloc(len + sizeof(char *));
|
||||||
|
if (res)
|
||||||
|
memcpy((*((char**) res)= res + sizeof(char *)), buf, len);
|
||||||
|
my_safe_afree(buf, len);
|
||||||
|
}
|
||||||
|
return (uchar *)res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Sys_var_proxy_user: public sys_var
|
class Sys_var_proxy_user: public sys_var
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user