diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2019-06-20 18:02:40 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2019-09-23 15:37:51 +0400 |
commit | 6ba5174b5b52bf6fa55f054278967db25f8cf6a9 (patch) | |
tree | b6cd0e25099ceafd6277cb568a87d6b7ddede1ca | |
parent | 36355060900611312c894d6726996cdd374a9554 (diff) | |
download | mariadb-git-bb-10.5-svoj-MDEV-16470.tar.gz |
MDEV-16470 - Session user variables trackerbb-10.5-svoj-MDEV-16470
Based on contribution by Dapeng Huang.
-rw-r--r-- | include/mysql.h.pp | 1 | ||||
-rw-r--r-- | include/mysql_com.h | 1 | ||||
-rw-r--r-- | mysql-test/main/mysqld--help.result | 3 | ||||
-rw-r--r-- | mysql-test/main/mysqltest_tracking_info.result | 10 | ||||
-rw-r--r-- | mysql-test/main/mysqltest_tracking_info.test | 11 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/session_track_system_variables_basic.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/t/session_track_system_variables_basic.test | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 6 | ||||
-rw-r--r-- | sql/session_tracker.cc | 33 | ||||
-rw-r--r-- | sql/session_tracker.h | 34 | ||||
-rw-r--r-- | sql/sql_base.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_hset.h | 18 | ||||
-rw-r--r-- | sql/sys_vars.cc | 16 |
16 files changed, 141 insertions, 21 deletions
diff --git a/include/mysql.h.pp b/include/mysql.h.pp index ed47b32d37a..4fcfab4aea4 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -108,6 +108,7 @@ enum enum_session_state_type SESSION_TRACK_GTIDS, SESSION_TRACK_TRANSACTION_CHARACTERISTICS, SESSION_TRACK_TRANSACTION_STATE, + SESSION_TRACK_USER_VARIABLES, SESSION_TRACK_always_at_the_end }; extern "C" { diff --git a/include/mysql_com.h b/include/mysql_com.h index 8b1f09e4703..4eafe148743 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -601,6 +601,7 @@ enum enum_session_state_type SESSION_TRACK_GTIDS, SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction chistics */ SESSION_TRACK_TRANSACTION_STATE, /* Transaction state */ + SESSION_TRACK_USER_VARIABLES, SESSION_TRACK_always_at_the_end /* must be last */ }; diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index de43900ed76..9d3f4198261 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1117,6 +1117,8 @@ The following specify which files/extra groups are read (specified before remain characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction). + --session-track-user-variables + Track changes to user variables. --show-slave-auth-info Show user and password in SHOW SLAVE HOSTS on this master. @@ -1712,6 +1714,7 @@ session-track-schema TRUE session-track-state-change FALSE session-track-system-variables autocommit,character_set_client,character_set_connection,character_set_results,time_zone session-track-transaction-info OFF +session-track-user-variables FALSE show-slave-auth-info FALSE silent-startup FALSE skip-grant-tables TRUE diff --git a/mysql-test/main/mysqltest_tracking_info.result b/mysql-test/main/mysqltest_tracking_info.result index df966ae1d39..d2eaa5afea8 100644 --- a/mysql-test/main/mysqltest_tracking_info.result +++ b/mysql-test/main/mysqltest_tracking_info.result @@ -29,3 +29,13 @@ SET NAMES 'utf8'; # tracking info off once SET NAMES 'big5'; SET @@session.session_track_system_variables= default; +# +# MDEV-16470 - Session user variables tracker +# +SET @@session.session_track_user_variables=1; +SET @a=1; +SET @b=NULL; +SELECT @c:=10; +@c:=10 +10 +SET @@session.session_track_user_variables=0; diff --git a/mysql-test/main/mysqltest_tracking_info.test b/mysql-test/main/mysqltest_tracking_info.test index d31f68b3cbd..405b920051a 100644 --- a/mysql-test/main/mysqltest_tracking_info.test +++ b/mysql-test/main/mysqltest_tracking_info.test @@ -23,3 +23,14 @@ SET NAMES 'big5'; --disable_session_track_info SET @@session.session_track_system_variables= default; + +--echo # +--echo # MDEV-16470 - Session user variables tracker +--echo # +SET @@session.session_track_user_variables=1; +--enable_session_track_info +SET @a=1; +SET @b=NULL; +SELECT @c:=10; +--disable_session_track_info +SET @@session.session_track_user_variables=0; diff --git a/mysql-test/suite/sys_vars/r/session_track_system_variables_basic.result b/mysql-test/suite/sys_vars/r/session_track_system_variables_basic.result index 78ca8ca4ad1..bb34436b4ec 100644 --- a/mysql-test/suite/sys_vars/r/session_track_system_variables_basic.result +++ b/mysql-test/suite/sys_vars/r/session_track_system_variables_basic.result @@ -12,19 +12,13 @@ SELECT @@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; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'session_track_system_variables' 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 -SESSION_TRACK_TRANSACTION_INFO OFF # 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_system_variables' 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 -SESSION_TRACK_TRANSACTION_INFO OFF SET @global_saved_tmp = @@global.session_track_system_variables; # Altering global variable's value diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 3e50dcb942f..cb4496ca9d7 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3453,6 +3453,16 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,STATE,CHARACTERISTICS READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SESSION_TRACK_USER_VARIABLES +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Track changes to user variables. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SKIP_EXTERNAL_LOCKING VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN diff --git a/mysql-test/suite/sys_vars/t/session_track_system_variables_basic.test b/mysql-test/suite/sys_vars/t/session_track_system_variables_basic.test index 90e6052947c..e58d405cf0a 100644 --- a/mysql-test/suite/sys_vars/t/session_track_system_variables_basic.test +++ b/mysql-test/suite/sys_vars/t/session_track_system_variables_basic.test @@ -12,10 +12,10 @@ SELECT @@session.session_track_system_variables; --echo --echo # 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_system_variables' ORDER BY VARIABLE_NAME; --echo # 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_system_variables' ORDER BY VARIABLE_NAME; # Save the global value to be used to restore the original value. SET @global_saved_tmp = @@global.session_track_system_variables; diff --git a/sql/item_func.cc b/sql/item_func.cc index 10ac0f74644..2eb7250ebc7 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4671,6 +4671,10 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, entry->unsigned_flag= unsigned_arg; } entry->type=type; +#ifndef EMBEDDED_LIBRARY + THD *thd= current_thd; + thd->session_tracker.user_variables.mark_as_changed(thd, entry); +#endif return 0; } @@ -4760,7 +4764,7 @@ longlong user_var_entry::val_int(bool *null_value) const /** Get the value of a variable as a string. */ String *user_var_entry::val_str(bool *null_value, String *str, - uint decimals) + uint decimals) const { if ((*null_value= (value == 0))) return (String*) 0; diff --git a/sql/session_tracker.cc b/sql/session_tracker.cc index fe5cd3a5d61..dc22d6dc9a3 100644 --- a/sql/session_tracker.cc +++ b/sql/session_tracker.cc @@ -16,7 +16,6 @@ #include "sql_plugin.h" -#include "hash.h" #include "table.h" #include "rpl_gtid.h" #include "sql_class.h" @@ -1182,6 +1181,38 @@ bool Session_state_change_tracker::store(THD *thd, String *buf) return false; } + +bool User_variables_tracker::update(THD *thd, set_var *) +{ + m_enabled= thd->variables.session_track_user_variables; + return false; +} + + +bool User_variables_tracker::store(THD *thd, String *buf) +{ + for (ulong i= 0; i < m_changed_user_variables.size(); i++) + { + auto var= m_changed_user_variables.at(i); + String value_str; + bool null_value; + + var->val_str(&null_value, &value_str, DECIMAL_MAX_SCALE); + buf->q_append(static_cast<char>(SESSION_TRACK_USER_VARIABLES)); + ulonglong length= net_length_size(var->name.length) + var->name.length; + if (!null_value) + length+= net_length_size(value_str.length()) + value_str.length(); + buf->q_net_store_length(length); + buf->q_net_store_data(reinterpret_cast<const uchar*>(var->name.str), + var->name.length); + if (!null_value) + buf->q_net_store_data(reinterpret_cast<const uchar*>(value_str.ptr()), + value_str.length()); + } + m_changed_user_variables.clear(); + return false; +} + /////////////////////////////////////////////////////////////////////////////// /** diff --git a/sql/session_tracker.h b/sql/session_tracker.h index 269b1bd2359..b91e588a34e 100644 --- a/sql/session_tracker.h +++ b/sql/session_tracker.h @@ -19,12 +19,14 @@ #include "m_string.h" #include "thr_lock.h" +#include "sql_hset.h" #ifndef EMBEDDED_LIBRARY /* forward declarations */ class THD; class set_var; class String; +class user_var_entry; enum enum_session_tracker @@ -33,6 +35,7 @@ enum enum_session_tracker CURRENT_SCHEMA_TRACKER, /* Current schema */ SESSION_STATE_CHANGE_TRACKER, TRANSACTION_INFO_TRACKER, /* Transaction state */ + USER_VARIABLES_TRACKER, SESSION_TRACKER_END /* must be the last */ }; @@ -388,6 +391,35 @@ private: /** + User_variables_tracker + + This is a tracker class that enables & manages the tracking of user variables. +*/ + +class User_variables_tracker: public State_tracker +{ + Hash_set<const user_var_entry> m_changed_user_variables; +public: + User_variables_tracker(): + m_changed_user_variables(&my_charset_bin, 0, 0, + sizeof(const user_var_entry*), 0, 0, + HASH_UNIQUE | (mysqld_server_initialized ? + HASH_THREAD_SPECIFIC : 0)) {} + bool update(THD *thd, set_var *var); + bool store(THD *thd, String *buf); + void mark_as_changed(THD *thd, const user_var_entry *var) + { + if (is_enabled()) + { + m_changed_user_variables.insert(var); + set_changed(thd); + } + } + void deinit() { m_changed_user_variables.~Hash_set(); } +}; + + +/** Session_tracker This class holds an object each for all tracker classes and provides @@ -415,6 +447,7 @@ public: Session_state_change_tracker state_change; Transaction_state_tracker transaction_info; Session_sysvars_tracker sysvars; + User_variables_tracker user_variables; Session_tracker() { @@ -422,6 +455,7 @@ public: m_trackers[CURRENT_SCHEMA_TRACKER]= ¤t_schema; m_trackers[SESSION_STATE_CHANGE_TRACKER]= &state_change; m_trackers[TRANSACTION_INFO_TRACKER]= &transaction_info; + m_trackers[USER_VARIABLES_TRACKER]= &user_variables; } void enable(THD *thd) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 54491c2362b..aa13f8a24db 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -56,7 +56,6 @@ #include "rpl_filter.h" #include "sql_table.h" // build_table_filename #include "datadict.h" // dd_frm_is_view() -#include "sql_hset.h" // Hash_set #include "rpl_rli.h" // rpl_group_info #ifdef __WIN__ #include <io.h> diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 91fc482978d..93f1ae7c1eb 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1750,6 +1750,7 @@ THD::~THD() /* trick to make happy memory accounting system */ #ifndef EMBEDDED_LIBRARY session_tracker.sysvars.deinit(); + session_tracker.user_variables.deinit(); #endif //EMBEDDED_LIBRARY if (status_var.local_memory_used != 0) diff --git a/sql/sql_class.h b/sql/sql_class.h index a3d4b4e87d4..f6434605a74 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -766,6 +766,7 @@ typedef struct system_variables ulong session_track_transaction_info; my_bool session_track_schema; my_bool session_track_state_change; + my_bool session_track_user_variables; my_bool tcp_nodelay; ulong threadpool_priority; @@ -6319,7 +6320,7 @@ class user_var_entry double val_real(bool *null_value); longlong val_int(bool *null_value) const; - String *val_str(bool *null_value, String *str, uint decimals); + String *val_str(bool *null_value, String *str, uint decimals) const; my_decimal *val_decimal(bool *null_value, my_decimal *result); CHARSET_INFO *charset() const { return m_charset; } void set_charset(CHARSET_INFO *cs) { m_charset= cs; } diff --git a/sql/sql_hset.h b/sql/sql_hset.h index 7834349a2f7..aaecef9f0d4 100644 --- a/sql/sql_hset.h +++ b/sql/sql_hset.h @@ -38,6 +38,13 @@ public: m_hash.get_key= (my_hash_get_key)K; m_hash.charset= cs; } + Hash_set(CHARSET_INFO *charset, ulong default_array_elements, + size_t key_offset, size_t key_length, my_hash_get_key get_key, + void (*free_element)(void*), uint flags) + { + my_hash_init(&m_hash, charset, default_array_elements, key_offset, + key_length, get_key, free_element, flags); + } /** Destroy the hash by freeing the buckets table. Does not call destructors for the elements. @@ -58,13 +65,8 @@ public: bool insert(T *value) { my_hash_init_opt(&m_hash, m_hash.charset, START_SIZE, 0, 0, - m_hash.get_key, 0, MYF(0)); - size_t key_len; - uchar *v= reinterpret_cast<uchar *>(value); - const uchar *key= m_hash.get_key(v, &key_len, FALSE); - if (find(key, key_len) == NULL) - return my_hash_insert(&m_hash, v); - return FALSE; + m_hash.get_key, 0, HASH_UNIQUE); + return my_hash_insert(&m_hash, reinterpret_cast<const uchar*>(value)); } bool remove(T *value) { @@ -78,6 +80,8 @@ public: bool is_empty() const { return m_hash.records == 0; } /** Returns the number of unique elements. */ size_t size() const { return static_cast<size_t>(m_hash.records); } + /** Erases all elements from the container */ + void clear() { my_hash_reset(&m_hash); } const T* at(size_t i) const { return reinterpret_cast<T*>(my_hash_element(const_cast<HASH*>(&m_hash), i)); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 1ba58bf71c4..1adc20af657 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -6378,6 +6378,22 @@ static Sys_var_mybool Sys_session_track_state_change( ON_CHECK(0), ON_UPDATE(update_session_track_state_change)); + +static bool update_session_track_user_variables(sys_var *self, THD *thd, + enum_var_type type) +{ + return thd->session_tracker.user_variables.update(thd, 0); +} + +static Sys_var_mybool Sys_session_track_user_variables( + "session_track_user_variables", + "Track changes to user variables.", + SESSION_VAR(session_track_user_variables), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(0), + ON_UPDATE(update_session_track_user_variables)); + #endif //EMBEDDED_LIBRARY static Sys_var_uint Sys_in_subquery_conversion_threshold( |