Commit c8948b0d authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-8931: (server part of) session state tracking

System variables tracking
parent e7608a78
...@@ -908,6 +908,8 @@ The following options may be given as the first argument: ...@@ -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) ...@@ -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
......
#
# 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 ...@@ -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
......
--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) ...@@ -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; ...@@ -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() ...@@ -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; ...@@ -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, ...@@ -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);
} }
......
This diff is collapsed.
...@@ -104,6 +104,12 @@ class State_tracker ...@@ -104,6 +104,12 @@ class State_tracker
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
...@@ -133,11 +139,23 @@ class Session_tracker ...@@ -133,11 +139,23 @@ class Session_tracker
Session_tracker(); Session_tracker();
~Session_tracker() ~Session_tracker()
{
deinit();
}
/* trick to make happy memory accounting system */
void deinit()
{ {
for (int i= 0; i <= SESSION_TRACKER_END; i ++) for (int i= 0; i <= SESSION_TRACKER_END; i ++)
{
if (m_trackers[i])
delete 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() ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 @@ class sys_var: protected Value_source // for double_from_string_with_check ...@@ -240,6 +244,9 @@ class sys_var: protected Value_source // for double_from_string_with_check
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 ...@@ -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() ...@@ -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 ...@@ -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 ...@@ -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); ...@@ -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 @@ static bool plugin_add(MEM_ROOT *tmp_root, ...@@ -1175,6 +1178,13 @@ static bool plugin_add(MEM_ROOT *tmp_root,
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) ...@@ -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, ...@@ -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,14 +2789,16 @@ static void update_func_double(THD *thd, struct st_mysql_sys_var *var, ...@@ -2780,14 +2789,16 @@ 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));
if (!locked)
mysql_mutex_lock(&LOCK_plugin); 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)) &&
...@@ -2795,7 +2806,7 @@ sys_var *find_sys_var(THD *thd, const char *str, size_t length) ...@@ -2795,7 +2806,7 @@ sys_var *find_sys_var(THD *thd, const char *str, size_t length)
{ {
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) ...@@ -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);
if (!locked)
mysql_mutex_unlock(&LOCK_plugin); 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 *) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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
...@@ -3212,6 +3212,132 @@ void remove_status_vars(SHOW_VAR *list) ...@@ -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, ...@@ -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, ...@@ -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 @@ class String ...@@ -359,7 +359,9 @@ class String
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( ...@@ -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)
......
...@@ -438,10 +438,10 @@ public: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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
{ {
......
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