mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-8931: (server part of) session state tracking
Postreview fixes. New MySQL tests fixes.
This commit is contained in:
@ -95,7 +95,7 @@ enum enum_session_state_type
|
|||||||
SESSION_TRACK_GTIDS,
|
SESSION_TRACK_GTIDS,
|
||||||
SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
|
SESSION_TRACK_TRANSACTION_CHARACTERISTICS,
|
||||||
SESSION_TRACK_TRANSACTION_STATE,
|
SESSION_TRACK_TRANSACTION_STATE,
|
||||||
SESSION_TRACK_END
|
SESSION_TRACK_always_at_the_end
|
||||||
};
|
};
|
||||||
my_bool my_net_init(NET *net, Vio* vio, void *thd, unsigned int my_flags);
|
my_bool my_net_init(NET *net, Vio* vio, void *thd, unsigned int my_flags);
|
||||||
void my_net_local_init(NET *net);
|
void my_net_local_init(NET *net);
|
||||||
|
@ -559,13 +559,13 @@ enum enum_session_state_type
|
|||||||
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 */
|
||||||
SESSION_TRACK_END /* must be last */
|
SESSION_TRACK_always_at_the_end /* must be last */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SESSION_TRACK_BEGIN SESSION_TRACK_SYSTEM_VARIABLES
|
#define SESSION_TRACK_BEGIN SESSION_TRACK_SYSTEM_VARIABLES
|
||||||
|
|
||||||
#define IS_SESSION_STATE_TYPE(T) \
|
#define IS_SESSION_STATE_TYPE(T) \
|
||||||
(((int)(T) >= SESSION_TRACK_BEGIN) && ((T) < SESSION_TRACK_END))
|
(((int)(T) >= SESSION_TRACK_BEGIN) && ((T) < SESSION_TRACK_always_at_the_end))
|
||||||
|
|
||||||
#define net_new_transaction(net) ((net)->pkt_nr=0)
|
#define net_new_transaction(net) ((net)->pkt_nr=0)
|
||||||
|
|
||||||
|
@ -1172,8 +1172,7 @@ bool
|
|||||||
net_send_ok(THD *thd,
|
net_send_ok(THD *thd,
|
||||||
uint server_status, uint statement_warn_count,
|
uint server_status, uint statement_warn_count,
|
||||||
ulonglong affected_rows, ulonglong id, const char *message,
|
ulonglong affected_rows, ulonglong id, const char *message,
|
||||||
bool unused1,
|
bool, bool)
|
||||||
bool unused2)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("emb_net_send_ok");
|
DBUG_ENTER("emb_net_send_ok");
|
||||||
MYSQL_DATA *data;
|
MYSQL_DATA *data;
|
||||||
|
@ -909,7 +909,11 @@ The following options may be given as the first argument:
|
|||||||
--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
|
--session-track-system-variables=name
|
||||||
Track changes in registered system variables.
|
Track changes in registered system variables. For
|
||||||
|
compatibility with MySQL defaults this variable should be
|
||||||
|
set to "autocommit, character_set_client,
|
||||||
|
character_set_connection, character_set_results,
|
||||||
|
time_zone"
|
||||||
--session-track-transaction-info=name
|
--session-track-transaction-info=name
|
||||||
Track changes to the transaction attributes. OFF to
|
Track changes to the transaction attributes. OFF to
|
||||||
disable; STATE to track just transaction state (Is there
|
disable; STATE to track just transaction state (Is there
|
||||||
@ -1403,7 +1407,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
|
session-track-system-variables
|
||||||
session-track-transaction-info OFF
|
session-track-transaction-info OFF
|
||||||
show-slave-auth-info FALSE
|
show-slave-auth-info FALSE
|
||||||
silent-startup FALSE
|
silent-startup FALSE
|
||||||
|
@ -5,25 +5,25 @@
|
|||||||
# Global - default
|
# Global - default
|
||||||
SELECT @@global.session_track_system_variables;
|
SELECT @@global.session_track_system_variables;
|
||||||
@@global.session_track_system_variables
|
@@global.session_track_system_variables
|
||||||
autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
|
||||||
# Session - default
|
# Session - default
|
||||||
SELECT @@session.session_track_system_variables;
|
SELECT @@session.session_track_system_variables;
|
||||||
@@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
|
# via INFORMATION_SCHEMA.GLOBAL_VARIABLES
|
||||||
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
VARIABLE_NAME VARIABLE_VALUE
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
SESSION_TRACK_SCHEMA ON
|
SESSION_TRACK_SCHEMA ON
|
||||||
SESSION_TRACK_STATE_CHANGE OFF
|
SESSION_TRACK_STATE_CHANGE OFF
|
||||||
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
SESSION_TRACK_SYSTEM_VARIABLES
|
||||||
SESSION_TRACK_TRANSACTION_INFO OFF
|
SESSION_TRACK_TRANSACTION_INFO OFF
|
||||||
# via INFORMATION_SCHEMA.SESSION_VARIABLES
|
# via INFORMATION_SCHEMA.SESSION_VARIABLES
|
||||||
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track%' ORDER BY VARIABLE_NAME;
|
||||||
VARIABLE_NAME VARIABLE_VALUE
|
VARIABLE_NAME VARIABLE_VALUE
|
||||||
SESSION_TRACK_SCHEMA ON
|
SESSION_TRACK_SCHEMA ON
|
||||||
SESSION_TRACK_STATE_CHANGE OFF
|
SESSION_TRACK_STATE_CHANGE OFF
|
||||||
SESSION_TRACK_SYSTEM_VARIABLES autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
SESSION_TRACK_SYSTEM_VARIABLES
|
||||||
SESSION_TRACK_TRANSACTION_INFO OFF
|
SESSION_TRACK_TRANSACTION_INFO OFF
|
||||||
SET @global_saved_tmp = @@global.session_track_system_variables;
|
SET @global_saved_tmp = @@global.session_track_system_variables;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ SELECT @@global.session_track_system_variables;
|
|||||||
autocommit
|
autocommit
|
||||||
SELECT @@session.session_track_system_variables;
|
SELECT @@session.session_track_system_variables;
|
||||||
@@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
|
# Altering session variable's value
|
||||||
SET @@session.session_track_system_variables='autocommit';
|
SET @@session.session_track_system_variables='autocommit';
|
||||||
@ -72,25 +72,25 @@ SET @@session.session_track_system_variables = DEFAULT;
|
|||||||
|
|
||||||
SELECT @@global.session_track_system_variables;
|
SELECT @@global.session_track_system_variables;
|
||||||
@@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;
|
SELECT @@session.session_track_system_variables;
|
||||||
@@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).
|
# Variables' values in a new session (con2).
|
||||||
connect con2,"127.0.0.1",root,,test,$MASTER_MYPORT,;
|
connect con2,"127.0.0.1",root,,test,$MASTER_MYPORT,;
|
||||||
SELECT @@global.session_track_system_variables;
|
SELECT @@global.session_track_system_variables;
|
||||||
@@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;
|
SELECT @@session.session_track_system_variables;
|
||||||
@@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.
|
# Altering session should not affect global.
|
||||||
SET @@session.session_track_system_variables = 'sql_mode';
|
SET @@session.session_track_system_variables = 'sql_mode';
|
||||||
SELECT @@global.session_track_system_variables;
|
SELECT @@global.session_track_system_variables;
|
||||||
@@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;
|
SELECT @@session.session_track_system_variables;
|
||||||
@@session.session_track_system_variables
|
@@session.session_track_system_variables
|
||||||
sql_mode
|
sql_mode
|
||||||
@ -104,7 +104,7 @@ SELECT @@global.session_track_system_variables;
|
|||||||
sql_mode
|
sql_mode
|
||||||
SELECT @@session.session_track_system_variables;
|
SELECT @@session.session_track_system_variables;
|
||||||
@@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.
|
# Switching to the default connection.
|
||||||
connection default;
|
connection default;
|
||||||
|
@ -3818,13 +3818,13 @@ 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
|
VARIABLE_NAME SESSION_TRACK_SYSTEM_VARIABLES
|
||||||
SESSION_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
SESSION_VALUE
|
||||||
GLOBAL_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
GLOBAL_VALUE
|
||||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
DEFAULT_VALUE autocommit,character_set_client,character_set_connection,character_set_results,time_zone
|
DEFAULT_VALUE
|
||||||
VARIABLE_SCOPE SESSION
|
VARIABLE_SCOPE SESSION
|
||||||
VARIABLE_TYPE VARCHAR
|
VARIABLE_TYPE VARCHAR
|
||||||
VARIABLE_COMMENT Track changes in registered system variables.
|
VARIABLE_COMMENT Track changes in registered system variables. For compatibility with MySQL defaults this variable should be set to "autocommit, character_set_client, character_set_connection, character_set_results, time_zone"
|
||||||
NUMERIC_MIN_VALUE NULL
|
NUMERIC_MIN_VALUE NULL
|
||||||
NUMERIC_MAX_VALUE NULL
|
NUMERIC_MAX_VALUE NULL
|
||||||
NUMERIC_BLOCK_SIZE NULL
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
|
@ -144,16 +144,18 @@ private:
|
|||||||
return res;
|
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);
|
bool insert(sysvar_node_st *node, const sys_var *svar, myf mem_flag);
|
||||||
|
void reinit();
|
||||||
void reset();
|
void reset();
|
||||||
|
inline bool is_enabled()
|
||||||
|
{
|
||||||
|
return track_all || m_registered_sysvars.records;
|
||||||
|
}
|
||||||
void copy(vars_list* from, THD *thd);
|
void copy(vars_list* from, THD *thd);
|
||||||
bool parse_var_list(THD *thd, LEX_STRING var_list, bool throw_error,
|
bool parse_var_list(THD *thd, LEX_STRING var_list, bool throw_error,
|
||||||
CHARSET_INFO *char_set, bool session_created);
|
CHARSET_INFO *char_set, bool take_mutex);
|
||||||
bool construct_var_list(char *buf, size_t buf_len);
|
bool construct_var_list(char *buf, size_t buf_len);
|
||||||
|
bool store(THD *thd, String *buf);
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
Two objects of vars_list type are maintained to manage
|
Two objects of vars_list type are maintained to manage
|
||||||
@ -217,9 +219,13 @@ public:
|
|||||||
static uchar *sysvars_get_key(const char *entry, size_t *length,
|
static uchar *sysvars_get_key(const char *entry, size_t *length,
|
||||||
my_bool not_used __attribute__((unused)));
|
my_bool not_used __attribute__((unused)));
|
||||||
|
|
||||||
|
// hash iterators
|
||||||
static my_bool name_array_filler(void *ptr, void *data_ptr);
|
static my_bool name_array_filler(void *ptr, void *data_ptr);
|
||||||
|
static my_bool store_variable(void *ptr, void *data_ptr);
|
||||||
|
static my_bool reset_variable(void *ptr, void *data_ptr);
|
||||||
|
|
||||||
static bool check_var_list(THD *thd, LEX_STRING var_list, bool throw_error,
|
static bool check_var_list(THD *thd, LEX_STRING var_list, bool throw_error,
|
||||||
CHARSET_INFO *char_set, bool session_created);
|
CHARSET_INFO *char_set, bool take_mutex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -284,7 +290,7 @@ public:
|
|||||||
static const unsigned int EXTRA_ALLOC= 1024;
|
static const unsigned int EXTRA_ALLOC= 1024;
|
||||||
|
|
||||||
|
|
||||||
void Session_sysvars_tracker::vars_list::reset()
|
void Session_sysvars_tracker::vars_list::reinit()
|
||||||
{
|
{
|
||||||
buffer_length= 0;
|
buffer_length= 0;
|
||||||
track_all= 0;
|
track_all= 0;
|
||||||
@ -304,7 +310,7 @@ void Session_sysvars_tracker::vars_list::reset()
|
|||||||
|
|
||||||
void Session_sysvars_tracker::vars_list::copy(vars_list* from, THD *thd)
|
void Session_sysvars_tracker::vars_list::copy(vars_list* from, THD *thd)
|
||||||
{
|
{
|
||||||
reset();
|
reinit();
|
||||||
track_all= from->track_all;
|
track_all= from->track_all;
|
||||||
free_hash();
|
free_hash();
|
||||||
buffer_length= from->buffer_length;
|
buffer_length= from->buffer_length;
|
||||||
@ -331,7 +337,7 @@ bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node,
|
|||||||
if (!(node= (sysvar_node_st *) my_malloc(sizeof(sysvar_node_st),
|
if (!(node= (sysvar_node_st *) my_malloc(sizeof(sysvar_node_st),
|
||||||
MYF(MY_WME | mem_flag))))
|
MYF(MY_WME | mem_flag))))
|
||||||
{
|
{
|
||||||
reset();
|
reinit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,7 +351,7 @@ bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node,
|
|||||||
if (!search((sys_var *)svar))
|
if (!search((sys_var *)svar))
|
||||||
{
|
{
|
||||||
//EOF (error is already reported)
|
//EOF (error is already reported)
|
||||||
reset();
|
reinit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,9 +373,7 @@ bool Session_sysvars_tracker::vars_list::insert(sysvar_node_st *node,
|
|||||||
in case of invalid/duplicate values.
|
in case of invalid/duplicate values.
|
||||||
@param char_set [IN] charecter set information used for string
|
@param char_set [IN] charecter set information used for string
|
||||||
manipulations.
|
manipulations.
|
||||||
@param session_created [IN] bool variable which says if the parse is
|
@param take_mutex [IN] take LOCK_plugin
|
||||||
already executed once. The mutex on variables
|
|
||||||
is not acquired if this variable is false.
|
|
||||||
|
|
||||||
@return
|
@return
|
||||||
true Error
|
true Error
|
||||||
@ -379,11 +383,12 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
|
|||||||
LEX_STRING var_list,
|
LEX_STRING var_list,
|
||||||
bool throw_error,
|
bool throw_error,
|
||||||
CHARSET_INFO *char_set,
|
CHARSET_INFO *char_set,
|
||||||
bool session_created)
|
bool take_mutex)
|
||||||
{
|
{
|
||||||
const char separator= ',';
|
const char separator= ',';
|
||||||
char *token, *lasts= NULL;
|
char *token, *lasts= NULL;
|
||||||
size_t rest= var_list.length;
|
size_t rest= var_list.length;
|
||||||
|
reinit();
|
||||||
|
|
||||||
if (!var_list.str || var_list.length == 0)
|
if (!var_list.str || var_list.length == 0)
|
||||||
{
|
{
|
||||||
@ -408,7 +413,7 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
|
|||||||
token value. Hence the mutex is handled here to avoid a performance
|
token value. Hence the mutex is handled here to avoid a performance
|
||||||
overhead.
|
overhead.
|
||||||
*/
|
*/
|
||||||
if (!thd || session_created)
|
if (!thd || take_mutex)
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -429,12 +434,17 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
|
|||||||
/* Remove leading/trailing whitespace. */
|
/* Remove leading/trailing whitespace. */
|
||||||
trim_whitespace(char_set, &var);
|
trim_whitespace(char_set, &var);
|
||||||
|
|
||||||
if ((svar= find_sys_var_ex(thd, var.str, var.length, throw_error, true)))
|
if(!strcmp(var.str,(const char *)"*"))
|
||||||
|
{
|
||||||
|
track_all= true;
|
||||||
|
}
|
||||||
|
else if ((svar=
|
||||||
|
find_sys_var_ex(thd, var.str, var.length, throw_error, true)))
|
||||||
{
|
{
|
||||||
if (insert(NULL, svar, m_mem_flag) == TRUE)
|
if (insert(NULL, svar, m_mem_flag) == TRUE)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
else if (throw_error && session_created && thd)
|
else if (throw_error && thd)
|
||||||
{
|
{
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||||
ER_WRONG_VALUE_FOR_VAR,
|
ER_WRONG_VALUE_FOR_VAR,
|
||||||
@ -449,13 +459,13 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
|
|||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!thd || session_created)
|
if (!thd || take_mutex)
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (!thd || session_created)
|
if (!thd || take_mutex)
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -465,7 +475,7 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
|
|||||||
LEX_STRING var_list,
|
LEX_STRING var_list,
|
||||||
bool throw_error,
|
bool throw_error,
|
||||||
CHARSET_INFO *char_set,
|
CHARSET_INFO *char_set,
|
||||||
bool session_created)
|
bool take_mutex)
|
||||||
{
|
{
|
||||||
const char separator= ',';
|
const char separator= ',';
|
||||||
char *token, *lasts= NULL;
|
char *token, *lasts= NULL;
|
||||||
@ -485,11 +495,10 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
|
|||||||
token value. Hence the mutex is handled here to avoid a performance
|
token value. Hence the mutex is handled here to avoid a performance
|
||||||
overhead.
|
overhead.
|
||||||
*/
|
*/
|
||||||
if (!thd || session_created)
|
if (!thd || take_mutex)
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
sys_var *svar;
|
|
||||||
LEX_STRING var;
|
LEX_STRING var;
|
||||||
|
|
||||||
lasts= (char *) memchr(token, separator, rest);
|
lasts= (char *) memchr(token, separator, rest);
|
||||||
@ -506,9 +515,10 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
|
|||||||
/* Remove leading/trailing whitespace. */
|
/* Remove leading/trailing whitespace. */
|
||||||
trim_whitespace(char_set, &var);
|
trim_whitespace(char_set, &var);
|
||||||
|
|
||||||
if (!(svar= find_sys_var_ex(thd, var.str, var.length, throw_error, true)))
|
if(!strcmp(var.str,(const char *)"*") &&
|
||||||
|
!find_sys_var_ex(thd, var.str, var.length, throw_error, true))
|
||||||
{
|
{
|
||||||
if (throw_error && session_created && thd)
|
if (throw_error && take_mutex && thd)
|
||||||
{
|
{
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||||
ER_WRONG_VALUE_FOR_VAR,
|
ER_WRONG_VALUE_FOR_VAR,
|
||||||
@ -517,7 +527,7 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!thd || session_created)
|
if (!thd || take_mutex)
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -528,7 +538,7 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
|
|||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!thd || session_created)
|
if (!thd || take_mutex)
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -605,7 +615,10 @@ bool Session_sysvars_tracker::vars_list::construct_var_list(char *buf,
|
|||||||
my_hash_iterate(&m_registered_sysvars, &name_array_filler, &data);
|
my_hash_iterate(&m_registered_sysvars, &name_array_filler, &data);
|
||||||
DBUG_ASSERT(data.idx <= m_registered_sysvars.records);
|
DBUG_ASSERT(data.idx <= m_registered_sysvars.records);
|
||||||
|
|
||||||
|
/*
|
||||||
|
We check number of records again here because number of variables
|
||||||
|
could be reduced in case of plugin unload.
|
||||||
|
*/
|
||||||
if (m_registered_sysvars.records == 0)
|
if (m_registered_sysvars.records == 0)
|
||||||
{
|
{
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
@ -710,7 +723,7 @@ bool Session_sysvars_tracker::update(THD *thd, set_var *var)
|
|||||||
We are doing via tool list because there possible errors with memory
|
We are doing via tool list because there possible errors with memory
|
||||||
in this case value will be unchanged.
|
in this case value will be unchanged.
|
||||||
*/
|
*/
|
||||||
tool_list->reset();
|
tool_list->reinit();
|
||||||
if (tool_list->parse_var_list(thd, var->save_result.string_value, true,
|
if (tool_list->parse_var_list(thd, var->save_result.string_value, true,
|
||||||
thd->charset(), true))
|
thd->charset(), true))
|
||||||
return true;
|
return true;
|
||||||
@ -719,6 +732,83 @@ bool Session_sysvars_tracker::update(THD *thd, set_var *var)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function and structure to support storing variables from hash to the buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct st_store_variable_param
|
||||||
|
{
|
||||||
|
THD *thd;
|
||||||
|
String *buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
my_bool Session_sysvars_tracker::store_variable(void *ptr, void *data_ptr)
|
||||||
|
{
|
||||||
|
Session_sysvars_tracker::sysvar_node_st *node=
|
||||||
|
(Session_sysvars_tracker::sysvar_node_st *)ptr;
|
||||||
|
if (node->m_changed)
|
||||||
|
{
|
||||||
|
THD *thd= ((st_store_variable_param *)data_ptr)->thd;
|
||||||
|
String *buf= ((st_store_variable_param *)data_ptr)->buf;
|
||||||
|
char val_buf[SHOW_VAR_FUNC_BUFF_SIZE];
|
||||||
|
SHOW_VAR show;
|
||||||
|
CHARSET_INFO *charset;
|
||||||
|
size_t val_length, length;
|
||||||
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
|
if (!*node->test_load)
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sys_var *svar= node->m_svar;
|
||||||
|
bool is_plugin= svar->cast_pluginvar();
|
||||||
|
if (!is_plugin)
|
||||||
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
|
/* As its always system variable. */
|
||||||
|
show.type= SHOW_SYS;
|
||||||
|
show.name= svar->name.str;
|
||||||
|
show.value= (char *) svar;
|
||||||
|
|
||||||
|
const char *value= get_one_variable(thd, &show, OPT_SESSION, SHOW_SYS, NULL,
|
||||||
|
&charset, val_buf, &val_length);
|
||||||
|
if (is_plugin)
|
||||||
|
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);
|
||||||
|
if (unlikely((1 + net_length_size(length) + length + buf->length() >=
|
||||||
|
MAX_PACKET_LENGTH) ||
|
||||||
|
buf->reserve(1 + net_length_size(length) + length,
|
||||||
|
EXTRA_ALLOC)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
/* Session state type (SESSION_TRACK_SYSTEM_VARIABLES) */
|
||||||
|
buf->q_append((char)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);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Session_sysvars_tracker::vars_list::store(THD *thd, String *buf)
|
||||||
|
{
|
||||||
|
st_store_variable_param data= {thd, buf};
|
||||||
|
return my_hash_iterate(&m_registered_sysvars, &store_variable, &data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Store the data for changed system variables in the specified buffer.
|
Store the data for changed system variables in the specified buffer.
|
||||||
Once the data is stored, we reset the flags related to state-change
|
Once the data is stored, we reset the flags related to state-change
|
||||||
@ -733,62 +823,11 @@ bool Session_sysvars_tracker::update(THD *thd, set_var *var)
|
|||||||
|
|
||||||
bool Session_sysvars_tracker::store(THD *thd, String *buf)
|
bool Session_sysvars_tracker::store(THD *thd, String *buf)
|
||||||
{
|
{
|
||||||
char val_buf[SHOW_VAR_FUNC_BUFF_SIZE];
|
if (!orig_list->is_enabled())
|
||||||
SHOW_VAR show;
|
return false;
|
||||||
const char *value;
|
|
||||||
sysvar_node_st *node;
|
|
||||||
CHARSET_INFO *charset;
|
|
||||||
size_t val_length, length;
|
|
||||||
int idx= 0;
|
|
||||||
|
|
||||||
/* As its always system variable. */
|
if (orig_list->store(thd, buf))
|
||||||
show.type= SHOW_SYS;
|
return true;
|
||||||
|
|
||||||
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);
|
|
||||||
if (unlikely((1 + net_length_size(length) + length + buf->length() >=
|
|
||||||
MAX_PACKET_LENGTH) ||
|
|
||||||
buf->prep_alloc(1 + net_length_size(length) + length,
|
|
||||||
EXTRA_ALLOC)))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
|
||||||
/* Session state type (SESSION_TRACK_SYSTEM_VARIABLES) */
|
|
||||||
buf->q_append((char)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();
|
reset();
|
||||||
|
|
||||||
@ -811,7 +850,8 @@ void Session_sysvars_tracker::mark_as_changed(THD *thd,
|
|||||||
Check if the specified system variable is being tracked, if so
|
Check if the specified system variable is being tracked, if so
|
||||||
mark it as changed and also set the class's m_changed flag.
|
mark it as changed and also set the class's m_changed flag.
|
||||||
*/
|
*/
|
||||||
if ((node= (sysvar_node_st *) (orig_list->insert_or_search(node, svar))))
|
if (orig_list->is_enabled() &&
|
||||||
|
(node= (sysvar_node_st *) (orig_list->insert_or_search(node, svar))))
|
||||||
{
|
{
|
||||||
node->m_changed= true;
|
node->m_changed= true;
|
||||||
State_tracker::mark_as_changed(thd, var);
|
State_tracker::mark_as_changed(thd, var);
|
||||||
@ -838,20 +878,28 @@ uchar *Session_sysvars_tracker::sysvars_get_key(const char *entry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Function to support resetting hash nodes for the variables */
|
||||||
|
|
||||||
|
my_bool Session_sysvars_tracker::reset_variable(void *ptr,
|
||||||
|
void *data_ptr)
|
||||||
|
{
|
||||||
|
((Session_sysvars_tracker::sysvar_node_st *)ptr)->m_changed= false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session_sysvars_tracker::vars_list::reset()
|
||||||
|
{
|
||||||
|
my_hash_iterate(&m_registered_sysvars, &reset_variable, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Prepare/reset the m_registered_sysvars hash for next statement.
|
Prepare/reset the m_registered_sysvars hash for next statement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Session_sysvars_tracker::reset()
|
void Session_sysvars_tracker::reset()
|
||||||
{
|
{
|
||||||
sysvar_node_st *node;
|
|
||||||
int idx= 0;
|
|
||||||
|
|
||||||
while ((node= (sysvar_node_st *) (*orig_list)[idx]))
|
orig_list->reset();
|
||||||
{
|
|
||||||
node->m_changed= false;
|
|
||||||
++ idx;
|
|
||||||
}
|
|
||||||
m_changed= false;
|
m_changed= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -931,7 +979,7 @@ bool Current_schema_tracker::store(THD *thd, String *buf)
|
|||||||
compile_time_assert(NAME_LEN < 251);
|
compile_time_assert(NAME_LEN < 251);
|
||||||
DBUG_ASSERT(length < 251);
|
DBUG_ASSERT(length < 251);
|
||||||
if (unlikely((1 + 1 + length + buf->length() >= MAX_PACKET_LENGTH) ||
|
if (unlikely((1 + 1 + length + buf->length() >= MAX_PACKET_LENGTH) ||
|
||||||
buf->prep_alloc(1 + 1 + length, EXTRA_ALLOC)))
|
buf->reserve(1 + 1 + length, EXTRA_ALLOC)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Session state type (SESSION_TRACK_SCHEMA) */
|
/* Session state type (SESSION_TRACK_SCHEMA) */
|
||||||
@ -1034,26 +1082,25 @@ bool Transaction_state_tracker::store(THD *thd, String *buf)
|
|||||||
/* STATE */
|
/* STATE */
|
||||||
if (tx_changed & TX_CHG_STATE)
|
if (tx_changed & TX_CHG_STATE)
|
||||||
{
|
{
|
||||||
uchar *to;
|
|
||||||
if (unlikely((11 + buf->length() >= MAX_PACKET_LENGTH) ||
|
if (unlikely((11 + buf->length() >= MAX_PACKET_LENGTH) ||
|
||||||
((to= (uchar *) buf->prep_append(11, EXTRA_ALLOC)) == NULL)))
|
buf->reserve(11, EXTRA_ALLOC)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
*(to++)= (char)SESSION_TRACK_TRANSACTION_STATE;
|
buf->q_append((char)SESSION_TRACK_TRANSACTION_STATE);
|
||||||
|
|
||||||
to= net_store_length((uchar *) to, (ulonglong) 9);
|
buf->q_append((char)9); // whole packet length
|
||||||
to= net_store_length((uchar *) to, (ulonglong) 8);
|
buf->q_append((char)8); // results length
|
||||||
|
|
||||||
*(to++)= (tx_curr_state & TX_EXPLICIT) ? 'T' :
|
buf->q_append((char)((tx_curr_state & TX_EXPLICIT) ? 'T' :
|
||||||
((tx_curr_state & TX_IMPLICIT) ? 'I' : '_');
|
((tx_curr_state & TX_IMPLICIT) ? 'I' : '_')));
|
||||||
*(to++)= (tx_curr_state & TX_READ_UNSAFE) ? 'r' : '_';
|
buf->q_append((char)((tx_curr_state & TX_READ_UNSAFE) ? 'r' : '_'));
|
||||||
*(to++)= ((tx_curr_state & TX_READ_TRX) ||
|
buf->q_append((char)(((tx_curr_state & TX_READ_TRX) ||
|
||||||
(tx_curr_state & TX_WITH_SNAPSHOT)) ? 'R' : '_';
|
(tx_curr_state & TX_WITH_SNAPSHOT)) ? 'R' : '_'));
|
||||||
*(to++)= (tx_curr_state & TX_WRITE_UNSAFE) ? 'w' : '_';
|
buf->q_append((char)((tx_curr_state & TX_WRITE_UNSAFE) ? 'w' : '_'));
|
||||||
*(to++)= (tx_curr_state & TX_WRITE_TRX) ? 'W' : '_';
|
buf->q_append((char)((tx_curr_state & TX_WRITE_TRX) ? 'W' : '_'));
|
||||||
*(to++)= (tx_curr_state & TX_STMT_UNSAFE) ? 's' : '_';
|
buf->q_append((char)((tx_curr_state & TX_STMT_UNSAFE) ? 's' : '_'));
|
||||||
*(to++)= (tx_curr_state & TX_RESULT_SET) ? 'S' : '_';
|
buf->q_append((char)((tx_curr_state & TX_RESULT_SET) ? 'S' : '_'));
|
||||||
*(to++)= (tx_curr_state & TX_LOCKED_TABLES) ? 'L' : '_';
|
buf->q_append((char)((tx_curr_state & TX_LOCKED_TABLES) ? 'L' : '_'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CHARACTERISTICS -- How to restart the transaction */
|
/* CHARACTERISTICS -- How to restart the transaction */
|
||||||
@ -1066,7 +1113,7 @@ bool Transaction_state_tracker::store(THD *thd, String *buf)
|
|||||||
|
|
||||||
/* 2 length by 1 byte and code */
|
/* 2 length by 1 byte and code */
|
||||||
if (unlikely((1 + 1 + 1 + 110 + buf->length() >= MAX_PACKET_LENGTH) ||
|
if (unlikely((1 + 1 + 1 + 110 + buf->length() >= MAX_PACKET_LENGTH) ||
|
||||||
buf->prep_alloc(1 + 1 + 1, EXTRA_ALLOC)))
|
buf->reserve(1 + 1 + 1, EXTRA_ALLOC)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
compile_time_assert(SESSION_TRACK_TRANSACTION_CHARACTERISTICS < 251);
|
compile_time_assert(SESSION_TRACK_TRANSACTION_CHARACTERISTICS < 251);
|
||||||
@ -1503,7 +1550,7 @@ bool Session_state_change_tracker::update(THD *thd, set_var *)
|
|||||||
bool Session_state_change_tracker::store(THD *thd, String *buf)
|
bool Session_state_change_tracker::store(THD *thd, String *buf)
|
||||||
{
|
{
|
||||||
if (unlikely((1 + 1 + 1 + buf->length() >= MAX_PACKET_LENGTH) ||
|
if (unlikely((1 + 1 + 1 + buf->length() >= MAX_PACKET_LENGTH) ||
|
||||||
buf->prep_alloc(1 + 1 + 1, EXTRA_ALLOC)))
|
buf->reserve(1 + 1 + 1, EXTRA_ALLOC)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
compile_time_assert(SESSION_TRACK_STATE_CHANGE < 251);
|
compile_time_assert(SESSION_TRACK_STATE_CHANGE < 251);
|
||||||
@ -1550,9 +1597,10 @@ bool Session_state_change_tracker::is_state_changed(THD *)
|
|||||||
Session_tracker::Session_tracker()
|
Session_tracker::Session_tracker()
|
||||||
{
|
{
|
||||||
/* track data ID fit into one byte in net coding */
|
/* track data ID fit into one byte in net coding */
|
||||||
compile_time_assert(SESSION_TRACK_END < 251);
|
compile_time_assert(SESSION_TRACK_always_at_the_end < 251);
|
||||||
/* one tracker could serv several tracking data */
|
/* one tracker could serv several tracking data */
|
||||||
compile_time_assert((uint)SESSION_TRACK_END >= (uint)SESSION_TRACKER_END);
|
compile_time_assert((uint)SESSION_TRACK_always_at_the_end >=
|
||||||
|
(uint)SESSION_TRACKER_END);
|
||||||
|
|
||||||
for (int i= 0; i < SESSION_TRACKER_END; i++)
|
for (int i= 0; i < SESSION_TRACKER_END; i++)
|
||||||
m_trackers[i]= NULL;
|
m_trackers[i]= NULL;
|
||||||
@ -1648,7 +1696,7 @@ void Session_tracker::store(THD *thd, String *buf)
|
|||||||
|
|
||||||
if ((size= net_length_size(length)) != 1)
|
if ((size= net_length_size(length)) != 1)
|
||||||
{
|
{
|
||||||
if (buf->prep_alloc(size - 1, EXTRA_ALLOC))
|
if (buf->reserve(size - 1, EXTRA_ALLOC))
|
||||||
{
|
{
|
||||||
buf->length(start); // it is safer to have 0-length block in case of error
|
buf->length(start); // it is safer to have 0-length block in case of error
|
||||||
return;
|
return;
|
||||||
|
@ -62,8 +62,8 @@ protected:
|
|||||||
/**
|
/**
|
||||||
Is tracking enabled for a particular session state type ?
|
Is tracking enabled for a particular session state type ?
|
||||||
|
|
||||||
@note: It is cache to avoid virtual functions and checking thd
|
@note: it is a cache of the corresponding thd->variables.session_track_xxx
|
||||||
when we want mark tracker as changed.
|
variable
|
||||||
*/
|
*/
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
|
|
||||||
|
@ -2981,8 +2981,10 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
/*
|
/*
|
||||||
if there was instruction which changed tracking state before, result
|
If there was instruction which changed tracking state,
|
||||||
can go with this command OK packet, so better do not cache the result.
|
the result of changed tracking state send to client in OK packed.
|
||||||
|
So it changes result sent to client and probably can be different
|
||||||
|
independent on query text. So we can't cache such results.
|
||||||
*/
|
*/
|
||||||
if ((thd->client_capabilities & CLIENT_SESSION_TRACK) &&
|
if ((thd->client_capabilities & CLIENT_SESSION_TRACK) &&
|
||||||
(thd->server_status & SERVER_SESSION_STATE_CHANGED))
|
(thd->server_status & SERVER_SESSION_STATE_CHANGED))
|
||||||
|
@ -566,16 +566,6 @@ public:
|
|||||||
return Ptr+ old_length; /* Area to use */
|
return Ptr+ old_length; /* Area to use */
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool prep_alloc(uint32 arg_length, uint32 step_alloc)
|
|
||||||
{
|
|
||||||
uint32 new_length= arg_length + str_length;
|
|
||||||
if (new_length > Alloced_length)
|
|
||||||
{
|
|
||||||
if (realloc(new_length + step_alloc))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool append(const char *s, uint32 arg_length, uint32 step_alloc)
|
inline bool append(const char *s, uint32 arg_length, uint32 step_alloc)
|
||||||
{
|
{
|
||||||
|
@ -5393,10 +5393,12 @@ static Sys_var_ulong Sys_log_tc_size(
|
|||||||
|
|
||||||
static Sys_var_sesvartrack Sys_track_session_sys_vars(
|
static Sys_var_sesvartrack Sys_track_session_sys_vars(
|
||||||
"session_track_system_variables",
|
"session_track_system_variables",
|
||||||
"Track changes in registered system variables.",
|
"Track changes in registered system variables. "
|
||||||
|
"For compatibility with MySQL defaults this variable should be set to "
|
||||||
|
"\"autocommit, character_set_client, character_set_connection, "
|
||||||
|
"character_set_results, time_zone\"",
|
||||||
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
|
CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
|
||||||
DEFAULT("autocommit,character_set_client,character_set_connection,"
|
DEFAULT(""),
|
||||||
"character_set_results,time_zone"),
|
|
||||||
NO_MUTEX_GUARD);
|
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,
|
||||||
|
Reference in New Issue
Block a user