diff --git a/mysql-test/r/session_query_attrs.result b/mysql-test/r/session_query_attrs.result new file mode 100644 index 00000000000..0ce3f1c53b2 --- /dev/null +++ b/mysql-test/r/session_query_attrs.result @@ -0,0 +1,17 @@ +create database db1; +use db1; +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); +attr_name attr_value ordinal_position +a b 0 +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); +attr_name attr_value ordinal_position +b a 0 +a b 1 +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); +attr_name attr_value ordinal_position +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); +attr_name attr_value ordinal_position +b a 0 +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); +attr_name attr_value ordinal_position +drop database db1; diff --git a/mysql-test/suite/perfschema/r/all_tests.result b/mysql-test/suite/perfschema/r/all_tests.result index 780ef1f8939..6824db90c83 100644 --- a/mysql-test/suite/perfschema/r/all_tests.result +++ b/mysql-test/suite/perfschema/r/all_tests.result @@ -27,6 +27,7 @@ MISSING DDL/DML TESTS idx_log_status.test idx_replication_applier_filters.test idx_replication_applier_global_filters.test +idx_session_query_attrs.test idx_user_defined_functions.test drop table t1; drop table t2; diff --git a/mysql-test/suite/perfschema/r/dd_version_check.result b/mysql-test/suite/perfschema/r/dd_version_check.result index 61642d6f03d..815bbe3479d 100644 --- a/mysql-test/suite/perfschema/r/dd_version_check.result +++ b/mysql-test/suite/perfschema/r/dd_version_check.result @@ -1,6 +1,6 @@ "Checking the data dictionary properties ..." SUBSTRING_INDEX(SUBSTRING(properties, LOCATE('PS_VERSION', properties), 30), ';', 1) -PS_VERSION=80011 +PS_VERSION=80011001 "Checking the performance schema database structure ..." CHECK STATUS The tables in the performance_schema were last changed in MySQL 8.0.11 diff --git a/mysql-test/suite/perfschema/r/ddl_session_query_attrs.result b/mysql-test/suite/perfschema/r/ddl_session_query_attrs.result new file mode 100644 index 00000000000..444dea397b9 --- /dev/null +++ b/mysql-test/suite/perfschema/r/ddl_session_query_attrs.result @@ -0,0 +1,11 @@ +ALTER TABLE performance_schema.session_query_attrs +ADD COLUMN foo integer; +ERROR 42000: Access denied for user 'root'@'localhost' to database 'performance_schema' +TRUNCATE TABLE performance_schema.session_query_attrs; +ERROR 42000: DROP command denied to user 'root'@'localhost' for table 'session_query_attrs' +ALTER TABLE performance_schema.session_query_attrs +ADD INDEX test_index(PROCESSLIST_ID); +ERROR 42000: Access denied for user 'root'@'localhost' to database 'performance_schema' +CREATE UNIQUE INDEX test_index ON +performance_schema.session_query_attrs(PROCESSLIST_ID); +ERROR 42000: Access denied for user 'root'@'localhost' to database 'performance_schema' diff --git a/mysql-test/suite/perfschema/r/dml_handler.result b/mysql-test/suite/perfschema/r/dml_handler.result index ab5fe1524e3..03bf32b805a 100644 --- a/mysql-test/suite/perfschema/r/dml_handler.result +++ b/mysql-test/suite/perfschema/r/dml_handler.result @@ -9,78 +9,81 @@ SELECT COUNT(*) FROM table_list INTO @table_count; # For each table in the performance schema, attempt HANDLER...OPEN, # which should fail with an error 1031, ER_ILLEGAL_HA. -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=102; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=103; HANDLER performance_schema.variables_info OPEN; ERROR HY000: Table storage engine for 'variables_info' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=101; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=102; HANDLER performance_schema.variables_by_thread OPEN; ERROR HY000: Table storage engine for 'variables_by_thread' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=100; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=101; HANDLER performance_schema.users OPEN; ERROR HY000: Table storage engine for 'users' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=99; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=100; HANDLER performance_schema.user_variables_by_thread OPEN; ERROR HY000: Table storage engine for 'user_variables_by_thread' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=98; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=99; HANDLER performance_schema.user_defined_functions OPEN; ERROR HY000: Table storage engine for 'user_defined_functions' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=97; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=98; HANDLER performance_schema.threads OPEN; ERROR HY000: Table storage engine for 'threads' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=96; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=97; HANDLER performance_schema.table_lock_waits_summary_by_table OPEN; ERROR HY000: Table storage engine for 'table_lock_waits_summary_by_table' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=95; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=96; HANDLER performance_schema.table_io_waits_summary_by_table OPEN; ERROR HY000: Table storage engine for 'table_io_waits_summary_by_table' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=94; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=95; HANDLER performance_schema.table_io_waits_summary_by_index_usage OPEN; ERROR HY000: Table storage engine for 'table_io_waits_summary_by_index_usage' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=93; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=94; HANDLER performance_schema.table_handles OPEN; ERROR HY000: Table storage engine for 'table_handles' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=92; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=93; HANDLER performance_schema.status_by_user OPEN; ERROR HY000: Table storage engine for 'status_by_user' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=91; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=92; HANDLER performance_schema.status_by_thread OPEN; ERROR HY000: Table storage engine for 'status_by_thread' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=90; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=91; HANDLER performance_schema.status_by_host OPEN; ERROR HY000: Table storage engine for 'status_by_host' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=89; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=90; HANDLER performance_schema.status_by_account OPEN; ERROR HY000: Table storage engine for 'status_by_account' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=88; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=89; HANDLER performance_schema.socket_summary_by_instance OPEN; ERROR HY000: Table storage engine for 'socket_summary_by_instance' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=87; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=88; HANDLER performance_schema.socket_summary_by_event_name OPEN; ERROR HY000: Table storage engine for 'socket_summary_by_event_name' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=86; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=87; HANDLER performance_schema.socket_instances OPEN; ERROR HY000: Table storage engine for 'socket_instances' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=85; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=86; HANDLER performance_schema.setup_threads OPEN; ERROR HY000: Table storage engine for 'setup_threads' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=84; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=85; HANDLER performance_schema.setup_objects OPEN; ERROR HY000: Table storage engine for 'setup_objects' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=83; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=84; HANDLER performance_schema.setup_instruments OPEN; ERROR HY000: Table storage engine for 'setup_instruments' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=82; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=83; HANDLER performance_schema.setup_consumers OPEN; ERROR HY000: Table storage engine for 'setup_consumers' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=81; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=82; HANDLER performance_schema.setup_actors OPEN; ERROR HY000: Table storage engine for 'setup_actors' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=80; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=81; HANDLER performance_schema.session_variables OPEN; ERROR HY000: Table storage engine for 'session_variables' doesn't have this option -SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=79; +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=80; HANDLER performance_schema.session_status OPEN; ERROR HY000: Table storage engine for 'session_status' doesn't have this option +SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=79; +HANDLER performance_schema.session_query_attrs OPEN; +ERROR HY000: Table storage engine for 'session_query_attrs' doesn't have this option SELECT TABLE_NAME INTO @table_name FROM table_list WHERE id=78; HANDLER performance_schema.session_connect_attrs OPEN; ERROR HY000: Table storage engine for 'session_connect_attrs' doesn't have this option diff --git a/mysql-test/suite/perfschema/r/dml_session_query_attrs.result b/mysql-test/suite/perfschema/r/dml_session_query_attrs.result new file mode 100644 index 00000000000..b54b74a7237 --- /dev/null +++ b/mysql-test/suite/perfschema/r/dml_session_query_attrs.result @@ -0,0 +1,19 @@ +SELECT * FROM performance_schema.session_query_attrs +LIMIT 1; +INSERT INTO performance_schema.session_query_attrs +SET PROCESSLIST_ID=123; +ERROR 42000: INSERT command denied to user 'root'@'localhost' for table 'session_query_attrs' +UPDATE performance_schema.session_query_attrs +SET PROCESSLIST_ID=123 WHERE PROCESSLIST_ID=connection_id(); +ERROR 42000: UPDATE command denied to user 'root'@'localhost' for table 'session_query_attrs' +DELETE FROM performance_schema.session_query_attrs +WHERE PROCESSLIST_ID=connection_id(); +ERROR 42000: DELETE command denied to user 'root'@'localhost' for table 'session_query_attrs' +DELETE FROM performance_schema.session_query_attrs; +ERROR 42000: DELETE command denied to user 'root'@'localhost' for table 'session_query_attrs' +LOCK TABLES performance_schema.session_query_attrs READ; +ERROR 42000: SELECT, LOCK TABLES command denied to user 'root'@'localhost' for table 'session_query_attrs' +UNLOCK TABLES; +LOCK TABLES performance_schema.session_query_attrs WRITE; +ERROR 42000: SELECT, LOCK TABLES command denied to user 'root'@'localhost' for table 'session_query_attrs' +UNLOCK TABLES; diff --git a/mysql-test/suite/perfschema/r/information_schema.result b/mysql-test/suite/perfschema/r/information_schema.result index faa5f53ab66..b1a0df2ca5d 100644 --- a/mysql-test/suite/perfschema/r/information_schema.result +++ b/mysql-test/suite/perfschema/r/information_schema.result @@ -80,6 +80,7 @@ performance_schema replication_group_members def performance_schema rwlock_instances def performance_schema session_account_connect_attrs def performance_schema session_connect_attrs def +performance_schema session_query_attrs def performance_schema session_status def performance_schema session_variables def performance_schema setup_actors def @@ -186,6 +187,7 @@ replication_group_members BASE TABLE PERFORMANCE_SCHEMA rwlock_instances BASE TABLE PERFORMANCE_SCHEMA session_account_connect_attrs BASE TABLE PERFORMANCE_SCHEMA session_connect_attrs BASE TABLE PERFORMANCE_SCHEMA +session_query_attrs BASE TABLE PERFORMANCE_SCHEMA session_status BASE TABLE PERFORMANCE_SCHEMA session_variables BASE TABLE PERFORMANCE_SCHEMA setup_actors BASE TABLE PERFORMANCE_SCHEMA @@ -292,6 +294,7 @@ replication_group_members 10 Fixed rwlock_instances 10 Dynamic session_account_connect_attrs 10 Dynamic session_connect_attrs 10 Dynamic +session_query_attrs 10 Dynamic session_status 10 Dynamic session_variables 10 Dynamic setup_actors 10 Fixed @@ -396,6 +399,7 @@ replication_group_members 0 rwlock_instances 0 session_account_connect_attrs 0 session_connect_attrs 0 +session_query_attrs 0 setup_actors 0 setup_consumers 0 setup_instruments 0 @@ -510,6 +514,7 @@ replication_group_members 0 0 rwlock_instances 0 0 session_account_connect_attrs 0 0 session_connect_attrs 0 0 +session_query_attrs 0 0 session_status 0 0 session_variables 0 0 setup_actors 0 0 @@ -616,6 +621,7 @@ replication_group_members 0 0 NULL rwlock_instances 0 0 NULL session_account_connect_attrs 0 0 NULL session_connect_attrs 0 0 NULL +session_query_attrs 0 0 NULL session_status 0 0 NULL session_variables 0 0 NULL setup_actors 0 0 NULL @@ -722,6 +728,7 @@ replication_group_members NULL NULL NULL rwlock_instances NULL NULL NULL session_account_connect_attrs NULL NULL NULL session_connect_attrs NULL NULL NULL +session_query_attrs NULL NULL NULL session_status NULL NULL NULL session_variables NULL NULL NULL setup_actors NULL NULL NULL @@ -828,6 +835,7 @@ replication_group_members utf8mb4_0900_ai_ci NULL rwlock_instances utf8mb4_0900_ai_ci NULL session_account_connect_attrs utf8mb4_bin NULL session_connect_attrs utf8mb4_bin NULL +session_query_attrs utf8mb4_0900_ai_ci NULL session_status utf8mb4_0900_ai_ci NULL session_variables utf8mb4_0900_ai_ci NULL setup_actors utf8mb4_0900_ai_ci NULL @@ -934,6 +942,7 @@ replication_group_members rwlock_instances session_account_connect_attrs session_connect_attrs +session_query_attrs session_status session_variables setup_actors @@ -1040,6 +1049,7 @@ replication_group_members rwlock_instances session_account_connect_attrs session_connect_attrs +session_query_attrs session_status session_variables setup_actors diff --git a/mysql-test/suite/perfschema/r/schema.result b/mysql-test/suite/perfschema/r/schema.result index 8f51989ac5f..fff2af85922 100644 --- a/mysql-test/suite/perfschema/r/schema.result +++ b/mysql-test/suite/perfschema/r/schema.result @@ -85,6 +85,7 @@ replication_group_members rwlock_instances session_account_connect_attrs session_connect_attrs +session_query_attrs session_status session_variables setup_actors diff --git a/mysql-test/suite/perfschema/r/table_schema.result b/mysql-test/suite/perfschema/r/table_schema.result index 6a186d504c7..0f494e52f1e 100644 --- a/mysql-test/suite/perfschema/r/table_schema.result +++ b/mysql-test/suite/perfschema/r/table_schema.result @@ -1068,6 +1068,10 @@ def performance_schema session_connect_attrs PROCESSLIST_ID 1 NULL NO bigint NUL def performance_schema session_connect_attrs ATTR_NAME 2 NULL NO varchar 32 128 NULL NULL NULL utf8mb4 utf8mb4_bin varchar(32) PRI select,insert,update,references NULL def performance_schema session_connect_attrs ATTR_VALUE 3 NULL YES varchar 1024 4096 NULL NULL NULL utf8mb4 utf8mb4_bin varchar(1024) select,insert,update,references NULL def performance_schema session_connect_attrs ORDINAL_POSITION 4 NULL YES int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NULL +def performance_schema session_query_attrs PROCESSLIST_ID 1 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select,insert,update,references NULL +def performance_schema session_query_attrs ATTR_NAME 2 NULL NO varchar 256 1024 NULL NULL NULL utf8mb4 utf8mb4_0900_ai_ci varchar(256) select,insert,update,references NULL +def performance_schema session_query_attrs ATTR_VALUE 3 NULL NO varchar 256 1024 NULL NULL NULL utf8mb4 utf8mb4_0900_ai_ci varchar(256) select,insert,update,references NULL +def performance_schema session_query_attrs ORDINAL_POSITION 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select,insert,update,references NULL def performance_schema session_status VARIABLE_NAME 1 NULL NO varchar 64 256 NULL NULL NULL utf8mb4 utf8mb4_0900_ai_ci varchar(64) PRI select,insert,update,references NULL def performance_schema session_status VARIABLE_VALUE 2 NULL YES varchar 1024 4096 NULL NULL NULL utf8mb4 utf8mb4_0900_ai_ci varchar(1024) select,insert,update,references NULL def performance_schema session_variables VARIABLE_NAME 1 NULL NO varchar 64 256 NULL NULL NULL utf8mb4 utf8mb4_0900_ai_ci varchar(64) PRI select,insert,update,references NULL diff --git a/mysql-test/suite/perfschema/t/dd_version_check.test b/mysql-test/suite/perfschema/t/dd_version_check.test index 0a0cbcfaef5..60b3a49a070 100644 --- a/mysql-test/suite/perfschema/t/dd_version_check.test +++ b/mysql-test/suite/perfschema/t/dd_version_check.test @@ -61,7 +61,7 @@ create table test.pfs_published_schema insert into test.pfs_published_schema values("MySQL 8.0.11", - "1ea9bcf26f26adb1065907de189b1c6a2d90b1218ebe945013e0763fe10259bb"); + "19a1a8bf7fd499bd4cf34bf5036c4f9c07328e756a258a7bae2ef1c9a8d6ccdb"); create table test.pfs_check_table (id int(11) NOT NULL AUTO_INCREMENT, diff --git a/mysql-test/suite/perfschema/t/ddl_session_query_attrs.test b/mysql-test/suite/perfschema/t/ddl_session_query_attrs.test new file mode 100644 index 00000000000..edb480d5e99 --- /dev/null +++ b/mysql-test/suite/perfschema/t/ddl_session_query_attrs.test @@ -0,0 +1,21 @@ +# ==== Purpose ==== +# +# Tests for PERFORMANCE_SCHEMA +# +# This test verifies the correct behaviour in case of invalid +# usage of DDLs on the table session_query_attrs + +-- error ER_DBACCESS_DENIED_ERROR +ALTER TABLE performance_schema.session_query_attrs + ADD COLUMN foo integer; + +-- error ER_TABLEACCESS_DENIED_ERROR +TRUNCATE TABLE performance_schema.session_query_attrs; + +-- error ER_DBACCESS_DENIED_ERROR +ALTER TABLE performance_schema.session_query_attrs + ADD INDEX test_index(PROCESSLIST_ID); + +-- error ER_DBACCESS_DENIED_ERROR +CREATE UNIQUE INDEX test_index ON + performance_schema.session_query_attrs(PROCESSLIST_ID); diff --git a/mysql-test/suite/perfschema/t/dml_session_query_attrs.test b/mysql-test/suite/perfschema/t/dml_session_query_attrs.test new file mode 100644 index 00000000000..124e46bc6be --- /dev/null +++ b/mysql-test/suite/perfschema/t/dml_session_query_attrs.test @@ -0,0 +1,35 @@ +# ==== Purpose ==== +# +# Tests for PERFORMANCE_SCHEMA +# +# This test verifies the correct behaviour in case of invalid +# usage of DMLs on the table session_query_attrs. +# + +--disable_result_log +SELECT * FROM performance_schema.session_query_attrs + LIMIT 1; +--enable_result_log + +--error ER_TABLEACCESS_DENIED_ERROR +INSERT INTO performance_schema.session_query_attrs + SET PROCESSLIST_ID=123; + +--error ER_TABLEACCESS_DENIED_ERROR +UPDATE performance_schema.session_query_attrs + SET PROCESSLIST_ID=123 WHERE PROCESSLIST_ID=connection_id(); + +--error ER_TABLEACCESS_DENIED_ERROR +DELETE FROM performance_schema.session_query_attrs + WHERE PROCESSLIST_ID=connection_id(); + +--error ER_TABLEACCESS_DENIED_ERROR +DELETE FROM performance_schema.session_query_attrs; + +-- error ER_TABLEACCESS_DENIED_ERROR +LOCK TABLES performance_schema.session_query_attrs READ; +UNLOCK TABLES; + +-- error ER_TABLEACCESS_DENIED_ERROR +LOCK TABLES performance_schema.session_query_attrs WRITE; +UNLOCK TABLES; diff --git a/mysql-test/t/session_query_attrs.test b/mysql-test/t/session_query_attrs.test new file mode 100644 index 00000000000..b65c0fee063 --- /dev/null +++ b/mysql-test/t/session_query_attrs.test @@ -0,0 +1,25 @@ +create database db1; +use db1; + +connect (con,localhost,root,,db1); + +query_attrs_add a b; +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); + +query_attrs_add b a; +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); + +connection default; +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); + +connection con; +query_attrs_delete a; +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); + +query_attrs_reset; +select attr_name, attr_value, ordinal_position from performance_schema.session_query_attrs where PROCESSLIST_ID = connection_id(); + +connection default; +disconnect con; + +drop database db1; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 76e37f522bc..d2bcf5a1c6b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2788,6 +2788,7 @@ bool THD::sql_parser() { } return false; } + static std::string net_read_str(const char **ptr) { size_t len = net_field_length((uchar **)ptr); const char *str = *ptr; @@ -2814,35 +2815,53 @@ void THD::set_connection_attrs(const char *attrs, size_t length) { mysql_mutex_unlock(&LOCK_thd_data); } +static void set_attrs( + const char *ptr, size_t length, + std::vector> &query_attrs_list) { + const char *end = ptr + length; + + query_attrs_list.clear(); + while (ptr < end) { + std::string key = net_read_str(&ptr); + std::string value = net_read_str(&ptr); + auto kvp = std::make_pair(std::move(key), + std::move(value)); + query_attrs_list.emplace_back(std::move(kvp)); + } +} + void THD::set_query_attrs(const char *attrs, size_t length) { query_attrs_string = std::string(attrs, length); mysql_mutex_lock(&LOCK_thd_data); - set_attrs_map(query_attrs_string.c_str(), query_attrs_string.length(), - query_attrs_map); + set_attrs(query_attrs_string.c_str(), query_attrs_string.length(), + query_attrs_list); mysql_mutex_unlock(&LOCK_thd_data); } int THD::parse_query_info_attr() { static const std::string query_info_key = "query_info"; - auto it = this->query_attrs_map.find(query_info_key); - if (it == this->query_attrs_map.end()) return 0; - ptree root; - try { - std::istringstream query_info_attr(it->second); - boost::property_tree::read_json(query_info_attr, root); - } catch (const boost::property_tree::json_parser::json_parser_error &e) { - return -1; // invalid json - } - try { - boost::optional trace_id = - root.get_optional("traceid"); - if (trace_id) this->trace_id = *trace_id; - this->query_type = root.get("query_type"); - this->num_queries = root.get("num_queries"); - } catch (const boost::property_tree::ptree_error &e) { - return -1; // invalid key or value + for (const auto &kvp : query_attrs_list) { + if (kvp.first == query_info_key) { + ptree root; + try { + std::istringstream query_info_attr(kvp.second); + boost::property_tree::read_json(query_info_attr, root); + } catch (const boost::property_tree::json_parser::json_parser_error &e) { + return -1; // invalid json + } + try { + boost::optional trace_id = + root.get_optional("traceid"); + if (trace_id) this->trace_id = *trace_id; + this->query_type = root.get("query_type"); + this->num_queries = root.get("num_queries"); + } catch (const boost::property_tree::ptree_error &e) { + return -1; // invalid key or value + } + return 0; + } } return 0; } diff --git a/sql/sql_class.h b/sql/sql_class.h index bea03e826e1..4a6084c7154 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3733,7 +3733,7 @@ class THD : public MDL_context_owner, int parse_query_info_attr(); void reset_query_attrs() { mysql_mutex_lock(&LOCK_thd_data); - query_attrs_map.clear(); + query_attrs_list.clear(); mysql_mutex_unlock(&LOCK_thd_data); query_attrs_string.clear(); @@ -3745,7 +3745,7 @@ class THD : public MDL_context_owner, inline uint32 query_attrs_length() const { return query_attrs_string.length(); } - std::unordered_map query_attrs_map; + std::vector> query_attrs_list; std::unordered_map connection_attrs_map; uint64_t num_queries; std::string query_type; diff --git a/storage/perfschema/CMakeLists.txt b/storage/perfschema/CMakeLists.txt index b60f3bdc4d6..dd023ec6e43 100644 --- a/storage/perfschema/CMakeLists.txt +++ b/storage/perfschema/CMakeLists.txt @@ -154,6 +154,7 @@ cursor_by_thread_connect_attr.h table_session_connect.h table_session_connect_attrs.h table_session_account_connect_attrs.h +table_session_query_attrs.h table_replication_connection_configuration.h table_replication_group_members.h table_replication_connection_status.h @@ -292,6 +293,7 @@ cursor_by_thread_connect_attr.cc table_session_connect.cc table_session_connect_attrs.cc table_session_account_connect_attrs.cc +table_session_query_attrs.cc table_replication_connection_configuration.cc table_replication_group_members.cc table_replication_connection_status.cc diff --git a/storage/perfschema/pfs_dd_version.h b/storage/perfschema/pfs_dd_version.h index 8e588805469..d3efd58c08f 100644 --- a/storage/perfschema/pfs_dd_version.h +++ b/storage/perfschema/pfs_dd_version.h @@ -45,8 +45,8 @@ The numbering to use is the MySQL version number of the first MySQL version that published a given database schema. - The format is Mmmdd with M=Major, m=minor, d=dot, - so that MySQL 8.0.4 is encoded as 80004. + The format is Mmmdd with M=Major, m=minor, d=dot, and last three digits + for facebook specific schema changes so that MySQL 8.0.4 is encoded as 80004. In case of -dash version numbers, encode MySQL 8.12.34-56 as 8123456. @@ -85,8 +85,12 @@ performance_schema tables changed in MySQL 8.0.11 are - instance_log_resource was renamed to log_resource. - Version published is now 80011. + 80011001: + performance_schema tables changed: + - session_query_attrs added. + - The last three digits reprents Facebook specific MySQL Schema changes. + Version published is now 80011001. i.e. 8.0.11 facebook schema change no. 1. */ -static const uint PFS_DD_VERSION = 80011; +static const uint PFS_DD_VERSION = 80011001; #endif /* PFS_DD_VERSION_H */ diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc index 43af2111dce..c28b7aed8d3 100644 --- a/storage/perfschema/pfs_engine_table.cc +++ b/storage/perfschema/pfs_engine_table.cc @@ -120,6 +120,7 @@ #include "storage/perfschema/table_replication_group_members.h" #include "storage/perfschema/table_session_account_connect_attrs.h" #include "storage/perfschema/table_session_connect_attrs.h" +#include "storage/perfschema/table_session_query_attrs.h" #include "storage/perfschema/table_session_status.h" #include "storage/perfschema/table_session_variables.h" #include "storage/perfschema/table_setup_actors.h" @@ -627,6 +628,7 @@ static PFS_engine_table_share *all_shares[] = { &table_session_connect_attrs::m_share, &table_session_account_connect_attrs::m_share, + &table_session_query_attrs::m_share, &table_mems_global_by_event_name::m_share, &table_mems_by_account_by_event_name::m_share, diff --git a/storage/perfschema/table_session_query_attrs.cc b/storage/perfschema/table_session_query_attrs.cc new file mode 100644 index 00000000000..dbc35cc2327 --- /dev/null +++ b/storage/perfschema/table_session_query_attrs.cc @@ -0,0 +1,248 @@ +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + @file storage/perfschema/table_session_query_attrs.h + Performance schema query_attributes table. +*/ + +#include "storage/perfschema/table_session_query_attrs.h" + +#include "sql/field.h" +#include "sql/mysqld_thd_manager.h" +#include "sql/plugin_table.h" +#include "sql/sql_class.h" +#include "sql/table.h" +#include "storage/perfschema/pfs_buffer_container.h" +#include "storage/perfschema/table_helper.h" + +THR_LOCK table_session_query_attrs::m_table_lock; + +Plugin_table table_session_query_attrs::m_table_def( + /* Schema name */ + "performance_schema", + /* Name */ + "session_query_attrs", + /* Definition */ + " PROCESSLIST_ID BIGINT(21) unsigned NOT NULL DEFAULT '0',\n" + " ATTR_NAME VARCHAR(256) NOT NULL,\n" + " ATTR_VALUE VARCHAR(256) NOT NULL,\n" + " ORDINAL_POSITION BIGINT(21) unsigned NOT NULL\n", + /* Options */ + " ENGINE=PERFORMANCE_SCHEMA", + /* Tablespace */ + nullptr); + +PFS_engine_table_share table_session_query_attrs::m_share = { + &pfs_readonly_acl, + table_session_query_attrs::create, + NULL, /* write_row */ + NULL, /* delete_all_rows */ + table_session_query_attrs::get_row_count, + sizeof(PFS_simple_index), + &table_session_query_attrs::m_table_lock, + &table_session_query_attrs::m_table_def, + false, /* perpetual */ + PFS_engine_table_proxy(), + {0}, + false /* m_in_purgatory */ +}; + +class query_attribute_row { + public: + query_attribute_row(ulonglong processlist_id, const std::string &attr_name, + const std::string &attr_value, unsigned ordinal_position) + : m_processlist_id(processlist_id), + m_ordinal_position(ordinal_position), + m_attr_name(attr_name), + m_attr_value(attr_value) {} + + /* Disabled copy. */ + query_attribute_row(query_attribute_row &) = delete; + query_attribute_row &operator=(query_attribute_row &) = delete; + + /* Allow std::move copies. */ + query_attribute_row(query_attribute_row &&) = default; + query_attribute_row &operator=(query_attribute_row &&) = default; + + public: + ulonglong processlist_id() const { return m_processlist_id; } + const std::string &attr_name() const { return m_attr_name; } + const std::string &attr_value() const { return m_attr_value; } + unsigned ordinal_position() const { return m_ordinal_position; } + + private: + ulonglong m_processlist_id; + unsigned m_ordinal_position; + std::string m_attr_name; + std::string m_attr_value; +}; + +class All_THD_query_attrs_visitor : public Do_THD_Impl { + public: + virtual void operator()(THD *thd) { + mysql_mutex_lock(&thd->LOCK_thd_data); + auto thread_id = (ulonglong)thd->thread_id(); + unsigned ordinal_position = 0; + for (const auto &kvp : thd->query_attrs_list) { + const auto &attr_name = kvp.first; + const auto &attr_value = kvp.second; + m_query_attributes.emplace_back(thread_id, attr_name, attr_value, + ordinal_position++); + } + mysql_mutex_unlock(&thd->LOCK_thd_data); + } + + std::vector &query_attributes() { + return m_query_attributes; + } + + private: + std::vector m_query_attributes; +}; + +class table_session_query_attrs_impl { + public: + table_session_query_attrs_impl(PFS_simple_index *curr_pos); + + void reset_position(void); + int rnd_next(void); + int rnd_pos(void); + int read_row_values(TABLE *table, Field **fields, bool read_all); + + public: + std::vector m_all_rows; + /** Current position. */ + PFS_simple_index *m_curr_pos; + const query_attribute_row *m_current_row; +}; + +enum query_attr_field_offset { + FO_PROCESSLIST_ID, + FO_ATTR_NAME, + FO_ATTR_VALUE, + FO_ORDINAL_POSITION, +}; + +void table_session_query_attrs_impl::reset_position(void) { + m_curr_pos->set_at(0u); +} + +int table_session_query_attrs_impl::rnd_next(void) { + if (m_curr_pos->m_index >= m_all_rows.size()) { + m_current_row = nullptr; + return HA_ERR_END_OF_FILE; + } + m_current_row = &m_all_rows[m_curr_pos->m_index]; + m_curr_pos->next(); + return 0; +} + +int table_session_query_attrs_impl::rnd_pos(void) { + if (m_curr_pos->m_index >= m_all_rows.size()) { + m_current_row = nullptr; + return HA_ERR_RECORD_DELETED; + } + m_current_row = &m_all_rows[m_curr_pos->m_index]; + return 0; +} + +table_session_query_attrs_impl::table_session_query_attrs_impl( + PFS_simple_index *curr_pos) + : m_curr_pos(curr_pos) { + All_THD_query_attrs_visitor thd_query_attrs_visitor; + Global_THD_manager::get_instance()->do_for_all_thd(&thd_query_attrs_visitor); + m_all_rows.swap(thd_query_attrs_visitor.query_attributes()); + m_current_row = &m_all_rows[curr_pos->m_index]; +} + +int table_session_query_attrs_impl::read_row_values(TABLE *table, + Field **fields, + bool read_all) { + Field *f; + const auto &curr_row = *m_current_row; + + /* Set the null bits */ + DBUG_ASSERT(table->s->null_bytes == 0); + + for (; (f = *fields); fields++) { + if (read_all || bitmap_is_set(table->read_set, f->field_index)) { + switch (f->field_index) { + case FO_PROCESSLIST_ID: + set_field_ulonglong(f, curr_row.processlist_id()); + break; + case FO_ATTR_NAME: { + const auto &attr_name = curr_row.attr_name(); + set_field_varchar_utf8(f, attr_name.c_str(), attr_name.length()); + } break; + case FO_ATTR_VALUE: { + const auto &attr_value = curr_row.attr_value(); + set_field_varchar_utf8(f, attr_value.c_str(), attr_value.length()); + } break; + case FO_ORDINAL_POSITION: + set_field_ulonglong(f, curr_row.ordinal_position()); + break; + default: + DBUG_ASSERT(false); + } + } + } + + return 0; +} + +table_session_query_attrs::table_session_query_attrs() + : PFS_engine_table(&m_share, &m_pos), + m_pos(0), + m_query_attrs_impl(new table_session_query_attrs_impl(&m_pos)) {} + +PFS_engine_table *table_session_query_attrs::create(PFS_engine_table_share *) { + return new table_session_query_attrs(); +} + +ha_rows table_session_query_attrs::get_row_count(void) { + /* + The real number of attributes per thread does not matter, + we only need to hint the optimizer there are few (mostly one or less) + per thread. + */ + return global_thread_container.get_row_count(); +} + +void table_session_query_attrs::reset_position(void) { + m_query_attrs_impl->reset_position(); +} + +int table_session_query_attrs::rnd_next(void) { + return m_query_attrs_impl->rnd_next(); +} + +int table_session_query_attrs::rnd_pos(const void *pos) { + set_position(pos); + return m_query_attrs_impl->rnd_pos(); +} + +int table_session_query_attrs::read_row_values(TABLE *table, unsigned char *, + Field **fields, bool read_all) { + return m_query_attrs_impl->read_row_values(table, fields, read_all); +} diff --git a/storage/perfschema/table_session_query_attrs.h b/storage/perfschema/table_session_query_attrs.h new file mode 100644 index 00000000000..bc1a7f7a0a1 --- /dev/null +++ b/storage/perfschema/table_session_query_attrs.h @@ -0,0 +1,62 @@ +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + @file storage/perfschema/table_session_query_attrs.h + Performance schema query_attributes table. +*/ + +#include "storage/perfschema/pfs_engine_table.h" + +class table_session_query_attrs_impl; + +class table_session_query_attrs : public PFS_engine_table { + public: + /** Table share */ + static PFS_engine_table_share m_share; + static PFS_engine_table *create(PFS_engine_table_share *); + static ha_rows get_row_count(); + + virtual void reset_position(void); + virtual int rnd_next(); + virtual int rnd_pos(const void *pos); + + protected: + virtual int read_row_values(TABLE *table, unsigned char *buf, Field **fields, + bool read_all); + + private: + table_session_query_attrs(); + + private: + /** Current position. */ + PFS_simple_index m_pos; + + std::unique_ptr m_query_attrs_impl; + + /** Table share lock. */ + static THR_LOCK m_table_lock; + + /** Table definition. */ + static Plugin_table m_table_def; +};