From 00e18f3b73da989b59b9e884db9cf443682c9da7 Mon Sep 17 00:00:00 2001 From: Phillip Vo Date: Fri, 5 May 2023 11:37:10 -0700 Subject: [PATCH] Log Thrift requests to Perf Schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Add instrumentation to log thrift request from bypass rpc workflow to performance schema (specifically the "esms_by_all" table). The changes made include: - adding a sysvar to control pfs logging (this is enabled by default) - adding statement/digest instrumentation to Bypass RPC path - computing the query's digest if the sysvar is enabled (needed to log to performance schema) Differential Revision: D46087826 ------------------------------------------------------------------------------------- Do not define static variables in a header file (#1409) Summary: Since they are used only once, move them to their respective use locations. This fixes a GCC compilation error: In file included from /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/rdb_nosql_digest.cc:1: /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:28:20: error: ‘myrocks::desc_tok’ defined but not used [-Werror=unused-variable] 28 | static LEX_CSTRING desc_tok{STRING_WITH_LEN("DESC")}; | ^~~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:27:20: error: ‘myrocks::asc_tok’ defined but not used [-Werror=unused-variable] 27 | static LEX_CSTRING asc_tok{STRING_WITH_LEN("ASC")}; | ^~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:26:20: error: ‘myrocks::limit_tok’ defined but not used [-Werror=unused-variable] 26 | static LEX_CSTRING limit_tok{STRING_WITH_LEN("LIMIT")}; | ^~~~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:25:20: error: ‘myrocks::by_tok’ defined but not used [-Werror=unused-variable] 25 | static LEX_CSTRING by_tok{STRING_WITH_LEN("BY")}; | ^~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:24:20: error: ‘myrocks::order_tok’ defined but not used [-Werror=unused-variable] 24 | static LEX_CSTRING order_tok{STRING_WITH_LEN("ORDER")}; | ^~~~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:23:20: error: ‘myrocks::index_tok’ defined but not used [-Werror=unused-variable] 23 | static LEX_CSTRING index_tok{STRING_WITH_LEN("INDEX")}; | ^~~~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:22:20: error: ‘myrocks::force_tok’ defined but not used [-Werror=unused-variable] 22 | static LEX_CSTRING force_tok{STRING_WITH_LEN("FORCE")}; | ^~~~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:21:20: error: ‘myrocks::where_tok’ defined but not used [-Werror=unused-variable] 21 | static LEX_CSTRING where_tok{STRING_WITH_LEN("WHERE")}; | ^~~~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:20:20: error: ‘myrocks::from_tok’ defined but not used [-Werror=unused-variable] 20 | static LEX_CSTRING from_tok{STRING_WITH_LEN("FROM")}; | ^~~~~~~~ /home/laurynas/vilniusdb/fb-mysql/storage/rocksdb/./rdb_nosql_digest.h:19:20: error: ‘myrocks::select_tok’ defined but not used [-Werror=unused-variable] 19 | static LEX_CSTRING select_tok{STRING_WITH_LEN("SELECT")}; | ^~~~~~~~~~ Pull Request resolved: https://github.com/facebook/mysql-5.6/pull/1409 Differential Revision: D52259043 fbshipit-source-id: 42a062a3b9b110b800c19e6ee5c297ba6930f925 ------------------------------------------------------------------------------------ [thrift] Fix bypass_pfs_logging test Summary: Fixed failing tests and other bugs that showed up while attempting to reproduce the issue - update digest from test results; this is likely from recording test results on an older iteration - set `thrift_server_bypass` to ON in thrift_server test initialization (this is needed after D52489280 sets this to `OFF` by default) - clean up state of `bypass_pfs_logging` sys var after tests Differential Revision: D52523295 fbshipit-source-id: eb5a1f893d57528d387bb2d1221c55f585998f56 --- mysql-test/r/mysqld--help-notwin.result | 4 + .../r/bypass_rpc_pfs_logging_basic.result | 85 +++++++++++++ .../t/bypass_rpc_pfs_logging_basic.test | 78 ++++++++++++ .../include/init_thrift_server_plugin.inc | 1 + .../thrift_server/r/bypass_pfs_logging.result | 119 ++++++++++++++++++ .../thrift_server/t/bypass_pfs_logging.test | 107 ++++++++++++++++ sql/mysqld.cc | 1 + sql/mysqld.h | 5 + sql/rpc_plugin.cc | 56 +++++++++ sql/sys_vars.cc | 6 + storage/rocksdb/CMakeLists.txt | 1 + storage/rocksdb/nosql_access.cc | 115 ++++++++++++++++- storage/rocksdb/rdb_datadic.h | 1 - storage/rocksdb/rdb_nosql_digest.cc | 26 ++++ storage/rocksdb/rdb_nosql_digest.h | 51 ++++++++ 15 files changed, 654 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/bypass_rpc_pfs_logging_basic.result create mode 100644 mysql-test/suite/sys_vars/t/bypass_rpc_pfs_logging_basic.test create mode 100644 mysql-test/suite/thrift_server/r/bypass_pfs_logging.result create mode 100644 mysql-test/suite/thrift_server/t/bypass_pfs_logging.test create mode 100644 storage/rocksdb/rdb_nosql_digest.cc create mode 100644 storage/rocksdb/rdb_nosql_digest.h diff --git a/mysql-test/r/mysqld--help-notwin.result b/mysql-test/r/mysqld--help-notwin.result index 54e70d2255e4..e08baaa8f545 100644 --- a/mysql-test/r/mysqld--help-notwin.result +++ b/mysql-test/r/mysqld--help-notwin.result @@ -307,6 +307,9 @@ The following options may be given as the first argument: --bulk-insert-buffer-size=# Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread! + --bypass-rpc-pfs-logging + Enables logging in from Bypass RPC path to the + events_statements_summary_by_all table --bypass-write-throttle-admin-check Bypass the check to avoid throttling write queries from admin users to prevent replication lag @@ -3219,6 +3222,7 @@ binlog-transaction-dependency-tracking COMMIT_ORDER binlog-trx-meta-data FALSE block-encryption-mode aes-128-ecb bulk-insert-buffer-size 8388608 +bypass-rpc-pfs-logging FALSE bypass-write-throttle-admin-check FALSE caching-sha2-password-digest-rounds 5000 caching-sha2-password-private-key-path private_key.pem diff --git a/mysql-test/suite/sys_vars/r/bypass_rpc_pfs_logging_basic.result b/mysql-test/suite/sys_vars/r/bypass_rpc_pfs_logging_basic.result new file mode 100644 index 000000000000..a2b40527a58c --- /dev/null +++ b/mysql-test/suite/sys_vars/r/bypass_rpc_pfs_logging_basic.result @@ -0,0 +1,85 @@ +SET @start_value = @@global.bypass_rpc_pfs_logging; +SELECT @start_value; +@start_value +0 +SET @@global.bypass_rpc_pfs_logging = DEFAULT; +SELECT @@global.bypass_rpc_pfs_logging = TRUE; +@@global.bypass_rpc_pfs_logging = TRUE +0 +SET @@global.bypass_rpc_pfs_logging = ON; +SELECT @@global.bypass_rpc_pfs_logging; +@@global.bypass_rpc_pfs_logging +1 +SET @@global.bypass_rpc_pfs_logging = OFF; +SELECT @@global.bypass_rpc_pfs_logging; +@@global.bypass_rpc_pfs_logging +0 +SET @@global.bypass_rpc_pfs_logging = 2; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of '2' +SET @@global.bypass_rpc_pfs_logging = -1; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of '-1' +SET @@global.bypass_rpc_pfs_logging = TRUEF; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of 'TRUEF' +SET @@global.bypass_rpc_pfs_logging = TRUE_F; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of 'TRUE_F' +SET @@global.bypass_rpc_pfs_logging = FALSE0; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of 'FALSE0' +SET @@global.bypass_rpc_pfs_logging = OON; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of 'OON' +SET @@global.bypass_rpc_pfs_logging = ONN; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of 'ONN' +SET @@global.bypass_rpc_pfs_logging = OOFF; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of 'OOFF' +SET @@global.bypass_rpc_pfs_logging = 0FF; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of '0FF' +SET @@global.bypass_rpc_pfs_logging = ' '; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of ' ' +SET @@global.bypass_rpc_pfs_logging = " "; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of ' ' +SET @@global.bypass_rpc_pfs_logging = ''; +ERROR 42000: Variable 'bypass_rpc_pfs_logging' can't be set to the value of '' +SET @@session.bypass_rpc_pfs_logging = OFF; +ERROR HY000: Variable 'bypass_rpc_pfs_logging' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@session.bypass_rpc_pfs_logging; +ERROR HY000: Variable 'bypass_rpc_pfs_logging' is a GLOBAL variable +SELECT IF(@@global.bypass_rpc_pfs_logging, "ON", "OFF") = VARIABLE_VALUE +FROM performance_schema.global_variables +WHERE VARIABLE_NAME='bypass_rpc_pfs_logging'; +IF(@@global.bypass_rpc_pfs_logging, "ON", "OFF") = VARIABLE_VALUE +1 +SET @@global.bypass_rpc_pfs_logging = 0; +SELECT @@global.bypass_rpc_pfs_logging; +@@global.bypass_rpc_pfs_logging +0 +SET @@global.bypass_rpc_pfs_logging = 1; +SELECT @@global.bypass_rpc_pfs_logging; +@@global.bypass_rpc_pfs_logging +1 +SET @@global.bypass_rpc_pfs_logging = TRUE; +SELECT @@global.bypass_rpc_pfs_logging; +@@global.bypass_rpc_pfs_logging +1 +SET @@global.bypass_rpc_pfs_logging = FALSE; +SELECT @@global.bypass_rpc_pfs_logging; +@@global.bypass_rpc_pfs_logging +0 +SET @@global.bypass_rpc_pfs_logging = ON; +SELECT @@bypass_rpc_pfs_logging = @@global.bypass_rpc_pfs_logging; +@@bypass_rpc_pfs_logging = @@global.bypass_rpc_pfs_logging +1 +SET bypass_rpc_pfs_logging = ON; +ERROR HY000: Variable 'bypass_rpc_pfs_logging' is a GLOBAL variable and should be set with SET GLOBAL +SET local.bypass_rpc_pfs_logging = OFF; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'local.bypass_rpc_pfs_logging = OFF' at line 1 +SELECT local.bypass_rpc_pfs_logging; +ERROR 42S02: Unknown table 'local' in field list +SET global.bypass_rpc_pfs_logging = ON; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'global.bypass_rpc_pfs_logging = ON' at line 1 +SELECT global.bypass_rpc_pfs_logging; +ERROR 42S02: Unknown table 'global' in field list +SELECT bypass_rpc_pfs_logging = @@session.bypass_rpc_pfs_logging; +ERROR HY000: Variable 'bypass_rpc_pfs_logging' is a GLOBAL variable +SET @@global.bypass_rpc_pfs_logging = @start_value; +SELECT @@global.bypass_rpc_pfs_logging; +@@global.bypass_rpc_pfs_logging +0 diff --git a/mysql-test/suite/sys_vars/t/bypass_rpc_pfs_logging_basic.test b/mysql-test/suite/sys_vars/t/bypass_rpc_pfs_logging_basic.test new file mode 100644 index 000000000000..5be2d5e5a7e9 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/bypass_rpc_pfs_logging_basic.test @@ -0,0 +1,78 @@ +SET @start_value = @@global.bypass_rpc_pfs_logging; +SELECT @start_value; + + +SET @@global.bypass_rpc_pfs_logging = DEFAULT; +SELECT @@global.bypass_rpc_pfs_logging = TRUE; + + +SET @@global.bypass_rpc_pfs_logging = ON; +SELECT @@global.bypass_rpc_pfs_logging; +SET @@global.bypass_rpc_pfs_logging = OFF; +SELECT @@global.bypass_rpc_pfs_logging; + +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = 2; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = -1; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = TRUEF; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = TRUE_F; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = FALSE0; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = OON; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = ONN; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = OOFF; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = 0FF; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = ' '; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = " "; +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.bypass_rpc_pfs_logging = ''; + + +--Error ER_GLOBAL_VARIABLE +SET @@session.bypass_rpc_pfs_logging = OFF; +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.bypass_rpc_pfs_logging; + + +SELECT IF(@@global.bypass_rpc_pfs_logging, "ON", "OFF") = VARIABLE_VALUE +FROM performance_schema.global_variables +WHERE VARIABLE_NAME='bypass_rpc_pfs_logging'; + + +SET @@global.bypass_rpc_pfs_logging = 0; +SELECT @@global.bypass_rpc_pfs_logging; +SET @@global.bypass_rpc_pfs_logging = 1; +SELECT @@global.bypass_rpc_pfs_logging; + +SET @@global.bypass_rpc_pfs_logging = TRUE; +SELECT @@global.bypass_rpc_pfs_logging; +SET @@global.bypass_rpc_pfs_logging = FALSE; +SELECT @@global.bypass_rpc_pfs_logging; + +SET @@global.bypass_rpc_pfs_logging = ON; +SELECT @@bypass_rpc_pfs_logging = @@global.bypass_rpc_pfs_logging; + +--Error ER_GLOBAL_VARIABLE +SET bypass_rpc_pfs_logging = ON; +--Error ER_PARSE_ERROR +SET local.bypass_rpc_pfs_logging = OFF; +--Error ER_UNKNOWN_TABLE +SELECT local.bypass_rpc_pfs_logging; +--Error ER_PARSE_ERROR +SET global.bypass_rpc_pfs_logging = ON; +--Error ER_UNKNOWN_TABLE +SELECT global.bypass_rpc_pfs_logging; +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT bypass_rpc_pfs_logging = @@session.bypass_rpc_pfs_logging; + +SET @@global.bypass_rpc_pfs_logging = @start_value; +SELECT @@global.bypass_rpc_pfs_logging; diff --git a/mysql-test/suite/thrift_server/include/init_thrift_server_plugin.inc b/mysql-test/suite/thrift_server/include/init_thrift_server_plugin.inc index 556fff9e0282..e60d475e5553 100644 --- a/mysql-test/suite/thrift_server/include/init_thrift_server_plugin.inc +++ b/mysql-test/suite/thrift_server/include/init_thrift_server_plugin.inc @@ -11,6 +11,7 @@ if (!$plugin_installed) set global thrift_server_vlog=1; set global thrift_server_on=on; SET GLOBAL THRIFT_SERVER_SQUIFT=ON; + SET GLOBAL THRIFT_SERVER_BYPASS=ON; } disable_warnings; diff --git a/mysql-test/suite/thrift_server/r/bypass_pfs_logging.result b/mysql-test/suite/thrift_server/r/bypass_pfs_logging.result new file mode 100644 index 000000000000..7a4933b70217 --- /dev/null +++ b/mysql-test/suite/thrift_server/r/bypass_pfs_logging.result @@ -0,0 +1,119 @@ +CREATE TABLE t1(c1 BIGINT NOT NULL, c2 VARCHAR(64), c3 int NOT NULL, PRIMARY KEY (c1)); +insert into t1 values (1, 'v1', 2), (2, 'v2', 3), (3, null, 4); +SELECT @@bypass_rpc_pfs_logging INTO @save_bypass_rpc_pfs_logging; +TRUNCATE TABLE performance_schema.events_statements_summary_by_all; + +TEST CASE performance_schema_esms_by_all=off. bypass_rpc_pfs_logging=off. No data in events_statements_summary_by_all + +set global performance_schema_esms_by_all = off; +set global bypass_rpc_pfs_logging = off; +select @@performance_schema_esms_by_all; +@@performance_schema_esms_by_all +0 +select @@bypass_rpc_pfs_logging; +@@bypass_rpc_pfs_logging +0 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +SEQ_NUMBER TYPE VALUE +0 header [{"type":2,"name":"c1"}, {"type":4,"name":"c2"}] +1 row [{"signedIntVal":2}, {"stringVal":"v2"}] +2 row [{"signedIntVal":3}, {"isNull":true}] +3 hlcTsLowerBound 0 +select schema_name, digest, user, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +schema_name digest user client_id plan_id count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; +schema_name digest count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +test 7ccb84550cd3166e3616468625636da4 1 0 0 0 +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; + +TEST CASE performance_schema_esms_by_all=off. bypass_rpc_pfs_logging=on. No data in events_statements_summary_by_all since +primary switch 'performance_schema.esms_by_all' is turned off. +echo +set global performance_schema_esms_by_all = off; +set global bypass_rpc_pfs_logging = on; +select @@performance_schema_esms_by_all; +@@performance_schema_esms_by_all +0 +select @@bypass_rpc_pfs_logging; +@@bypass_rpc_pfs_logging +1 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +SEQ_NUMBER TYPE VALUE +0 header [{"type":2,"name":"c1"}, {"type":4,"name":"c2"}] +1 row [{"signedIntVal":2}, {"stringVal":"v2"}] +2 row [{"signedIntVal":3}, {"isNull":true}] +3 hlcTsLowerBound 0 +select schema_name, digest, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +schema_name digest client_id plan_id count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; +schema_name digest count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +test e8f3d908aa6ac78634d186bb58579527 1 0 0 0 +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; + +TEST CASE performance_schema_esms_by_all=on. bypass_rpc_pfs_logging=off. Data will be stored in sql_statistics, but not bypass_rpc queries + +set global performance_schema_esms_by_all = on; +set global bypass_rpc_pfs_logging = off; +select @@performance_schema_esms_by_all; +@@performance_schema_esms_by_all +1 +select @@bypass_rpc_pfs_logging; +@@bypass_rpc_pfs_logging +0 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +SEQ_NUMBER TYPE VALUE +0 header [{"type":2,"name":"c1"}, {"type":4,"name":"c2"}] +1 row [{"signedIntVal":2}, {"stringVal":"v2"}] +2 row [{"signedIntVal":3}, {"isNull":true}] +3 hlcTsLowerBound 0 +select schema_name, digest, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +schema_name digest client_id plan_id count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; +schema_name digest count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; + +TEST CASE performance_schema_esms_by_all=on. bypass_rpc_pfs_logging=on. Data will be stored in sql_statistics + +set global performance_schema_esms_by_all = on; +set global bypass_rpc_pfs_logging = on; +select @@performance_schema_esms_by_all; +@@performance_schema_esms_by_all +1 +select @@bypass_rpc_pfs_logging; +@@bypass_rpc_pfs_logging +1 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +SEQ_NUMBER TYPE VALUE +0 header [{"type":2,"name":"c1"}, {"type":4,"name":"c2"}] +1 row [{"signedIntVal":2}, {"stringVal":"v2"}] +2 row [{"signedIntVal":3}, {"isNull":true}] +3 hlcTsLowerBound 0 +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":3}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +SEQ_NUMBER TYPE VALUE +0 header [{"type":2,"name":"c1"}, {"type":5,"name":"c2"}] +1 row [{"signedIntVal":3}, {"isNull":true}] +2 hlcTsLowerBound 0 +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}},{"column":"c3","op":1,"value":{"signedIntVal":4}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +SEQ_NUMBER TYPE VALUE +0 header [{"type":2,"name":"c1"}, {"type":4,"name":"c2"}] +1 row [{"signedIntVal":2}, {"stringVal":"v2"}] +2 hlcTsLowerBound 0 +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; +select schema_name, digest, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +schema_name digest client_id plan_id count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +test 5c3a390111f66b62dee3b0fca221c091 00000000000000000000000000000000 00000000000000000000000000000000 2 0 0 0 +test aac67466d0e9c28fa3daff45bf1c4d20 00000000000000000000000000000000 00000000000000000000000000000000 1 0 0 0 +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; +schema_name digest count_star sum_rows_deleted sum_rows_inserted sum_rows_updated +Cleanup +set global performance_schema_esms_by_all = DEFAULT; +SET GLOBAL bypass_rpc_pfs_logging = @save_bypass_rpc_pfs_logging; +drop table t1; diff --git a/mysql-test/suite/thrift_server/t/bypass_pfs_logging.test b/mysql-test/suite/thrift_server/t/bypass_pfs_logging.test new file mode 100644 index 000000000000..e6daf32ee6e2 --- /dev/null +++ b/mysql-test/suite/thrift_server/t/bypass_pfs_logging.test @@ -0,0 +1,107 @@ +source ../include/init_thrift_server_plugin.inc; + +disable_query_log; +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; +enable_query_log; + +CREATE TABLE t1(c1 BIGINT NOT NULL, c2 VARCHAR(64), c3 int NOT NULL, PRIMARY KEY (c1)); +insert into t1 values (1, 'v1', 2), (2, 'v2', 3), (3, null, 4); + +SELECT @@bypass_rpc_pfs_logging INTO @save_bypass_rpc_pfs_logging; + +TRUNCATE TABLE performance_schema.events_statements_summary_by_all; + +echo; +echo TEST CASE performance_schema_esms_by_all=off. bypass_rpc_pfs_logging=off. No data in events_statements_summary_by_all; +echo; + +set global performance_schema_esms_by_all = off; +set global bypass_rpc_pfs_logging = off; +select @@performance_schema_esms_by_all; +select @@bypass_rpc_pfs_logging; + +# select c1, c2 from t1 where c3 > 2 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; + +select schema_name, digest, user, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; + +# empty result set +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; + +echo; +echo TEST CASE performance_schema_esms_by_all=off. bypass_rpc_pfs_logging=on. No data in events_statements_summary_by_all since; +echo primary switch 'performance_schema.esms_by_all' is turned off. +echo; + +set global performance_schema_esms_by_all = off; +set global bypass_rpc_pfs_logging = on; +select @@performance_schema_esms_by_all; +select @@bypass_rpc_pfs_logging; + +# select c1, c2 from t1 where c3 > 2 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; + +select schema_name, digest, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; + +# empty result set +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; + +echo; +echo TEST CASE performance_schema_esms_by_all=on. bypass_rpc_pfs_logging=off. Data will be stored in sql_statistics, but not bypass_rpc queries; +echo; + +set global performance_schema_esms_by_all = on; +set global bypass_rpc_pfs_logging = off; +select @@performance_schema_esms_by_all; +select @@bypass_rpc_pfs_logging; + +# select c1, c2 from t1 where c3 > 2 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; + +select schema_name, digest, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; + +# empty result set +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; + +echo; +echo TEST CASE performance_schema_esms_by_all=on. bypass_rpc_pfs_logging=on. Data will be stored in sql_statistics; +echo; + +set global performance_schema_esms_by_all = on; +set global bypass_rpc_pfs_logging = on; +select @@performance_schema_esms_by_all; +select @@bypass_rpc_pfs_logging; + +# select c1, c2 from t1 where c3 > 2 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; +# select c1, c2 from t1 where c3 > 3 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":3}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; +# select c1, c2 from t1 where c3 > 2 and c3 < 4 +SET GLOBAL THRIFT_SERVER_TESTER_INPUT='bypass: {"db_name":"test","table_name":"t1","columns":["c1", "c2"],"where":[{"column":"c3","op":2,"value":{"signedIntVal":2}},{"column":"c3","op":1,"value":{"signedIntVal":4}}]}'; +SELECT SEQ_NUMBER, TYPE, VALUE FROM THRIFT_SERVER_PLUGIN_OUTPUT ORDER BY SEQ_NUMBER; +TRUNCATE TABLE THRIFT_SERVER_PLUGIN_OUTPUT; + +select schema_name, digest, client_id, plan_id, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_all where query_sample_text like '%bypass rpc%'; +select schema_name, digest, count_star, sum_rows_deleted, sum_rows_inserted, sum_rows_updated from performance_schema.events_statements_summary_by_digest where query_sample_text like '%bypass rpc%'; + +########### +### Cleanup +########### +--echo Cleanup +set global performance_schema_esms_by_all = DEFAULT; +SET GLOBAL bypass_rpc_pfs_logging = @save_bypass_rpc_pfs_logging; +drop table t1; + +source ../include/uninit_thrift_server_plugin.inc; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fec77846b3e2..fff4eca33a62 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1230,6 +1230,7 @@ char *opt_keyring_migration_source = nullptr; char *opt_keyring_migration_destination = nullptr; ulong opt_keyring_migration_port = 0; bool migrate_connect_options = false; +bool bypass_rpc_pfs_logging = false; uint host_cache_size; ulong log_error_verbosity = 3; // have a non-zero value during early start-up bool opt_keyring_migration_to_component = false; diff --git a/sql/mysqld.h b/sql/mysqld.h index e6fe32a7625b..d618df7d1cd2 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -735,6 +735,11 @@ extern ulonglong global_conn_mem_counter; */ extern bool migrate_connect_options; +/** + Variables for Bypass-specific features +*/ +extern bool bypass_rpc_pfs_logging; + extern LEX_CSTRING sql_statement_names[(uint)SQLCOM_END + 1]; extern thread_local MEM_ROOT **THR_MALLOC; diff --git a/sql/rpc_plugin.cc b/sql/rpc_plugin.cc index 73687529a617..a6d9ace8309e 100644 --- a/sql/rpc_plugin.cc +++ b/sql/rpc_plugin.cc @@ -3,6 +3,7 @@ #include #include +#include "mysqld.h" #include "sql/binlog.h" #include "sql/debug_sync.h" /* DEBUG_SYNC */ #include "sql/mysqld_thd_manager.h" @@ -218,6 +219,19 @@ void initialize_thd() { thd->set_query_formatter(formatter); Global_THD_manager::get_instance()->add_thd(thd); +#ifdef HAVE_PSI_THREAD_INTERFACE + { + PSI_thread *psi = PSI_THREAD_CALL(new_thread)(key_thread_one_connection, + 0 /* no sequence number */, + thd, thd->thread_id()); + PSI_THREAD_CALL(set_thread_os_id)(psi); + PSI_THREAD_CALL(set_thread)(psi); + thd->set_psi(psi); + PSI_THREAD_CALL(set_thread_id)(psi, thd->thread_id()); + PSI_THREAD_CALL(set_thread_THD)(psi, thd); + } +#endif + LEX *lex = new LEX(); thd->lex = lex; } @@ -235,6 +249,14 @@ bool check_hlc_bound(THD *thd, uint64_t requested_hlc, uint64_t applied_hlc) { return false; } +// return true if the incoming rpc request should be formatted to plain text +bool check_bypass_rpc_needs_formatting() { + // if pfs logging is enabled + if (pfs_param.m_esms_by_all_enabled && bypass_rpc_pfs_logging) + return true; + return false; +} + // return true if opening a table fails, otherwise return false bool rpc_open_table(THD *thd, const myrocks_select_from_rpc *param) { lex_start(thd); @@ -324,6 +346,9 @@ bypass_rpc_exception bypass_select(const myrocks_select_from_rpc *param) { THD *thd = current_thd; thd->release_resources(); Global_THD_manager::get_instance()->remove_thd(thd); +#ifdef HAVE_PSI_THREAD_INTERFACE + PSI_THREAD_CALL(delete_current_thread)(); +#endif delete thd; } bypass_rpc_exception ret; @@ -402,15 +427,46 @@ bypass_rpc_exception bypass_select(const myrocks_select_from_rpc *param) { assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); }); + /* PSI begin */ + assert(thd->m_statement_psi == nullptr); + thd->m_statement_psi = MYSQL_START_STATEMENT( + &thd->m_statement_state, com_statement_info[COM_QUERY].m_key, + param->db_name.c_str(), param->db_name.size(), thd->charset(), nullptr); + THD_STAGE_INFO(thd, stage_starting); + + thd->m_digest = &thd->m_digest_state; + thd->m_digest->reset(thd->m_token_array, max_digest_length); + + String buf; + if (check_bypass_rpc_needs_formatting()) { + formatter->format_query(buf); + } + + thd->set_query(buf.c_ptr(), buf.length()); + thd->set_query_for_display(buf.c_ptr(), buf.length()); + thd->set_query_id(next_query_id()); + thd->set_time(); + + auto m_digest_psi = MYSQL_DIGEST_START(thd->m_statement_psi); + auto ret = rocksdb_hton->bypass_select_by_key(thd, &columns, *param); ret.hlc_lower_bound_ts = applied_hlc; + /* PSI end */ + MYSQL_DIGEST_END(m_digest_psi, &thd->m_digest->m_digest_storage); + + MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); + thd->m_statement_psi = nullptr; + thd->m_digest = nullptr; + // clean up before returning back to the rpc plugin trans_commit_stmt(thd); // need to call this because we locked table close_thread_tables(thd); thd->lex->unit->cleanup(true); lex_end(thd->lex); thd->free_items(); + thd->reset_query(); + thd->reset_query_for_display(); thd->reset_query_attrs(); thd->mdl_context.release_transactional_locks(); thd->mem_root->ClearForReuse(); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 235ff9925f1a..f8cec2325176 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2730,6 +2730,12 @@ static bool transaction_write_set_check(sys_var *self, THD *thd, set_var *var) { return false; } +static Sys_var_bool Sys_bypass_rpc_pfs_logging( + "bypass_rpc_pfs_logging", + "Enables logging in from Bypass RPC path to the " + "events_statements_summary_by_all table", + GLOBAL_VAR(bypass_rpc_pfs_logging), CMD_LINE(OPT_ARG), DEFAULT(false)); + static Sys_var_enum Sys_extract_write_set( "transaction_write_set_extraction", "This option is used to let the server know when to " diff --git a/storage/rocksdb/CMakeLists.txt b/storage/rocksdb/CMakeLists.txt index 12bc963450ff..9633ab777969 100644 --- a/storage/rocksdb/CMakeLists.txt +++ b/storage/rocksdb/CMakeLists.txt @@ -179,6 +179,7 @@ SET(ROCKSDB_SE_SOURCES rdb_sst_info.cc rdb_sst_info.h rdb_utils.cc rdb_utils.h rdb_buff.h rdb_threads.cc rdb_threads.h + rdb_nosql_digest.cc rdb_nosql_digest.h nosql_access.cc nosql_access.h ha_rockspart.cc ha_rockspart.h sql_dd.cc sql_dd.h diff --git a/storage/rocksdb/nosql_access.cc b/storage/rocksdb/nosql_access.cc index 716c5a6d5317..31874d307df2 100644 --- a/storage/rocksdb/nosql_access.cc +++ b/storage/rocksdb/nosql_access.cc @@ -14,7 +14,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "rdb_utils.h" #define MYSQL_SERVER 1 /* This C++ file's header */ @@ -37,6 +36,7 @@ #include "./sql/item_func.h" #include "./sql/query_result.h" #include "./sql/sql_base.h" +#include "./sql/sql_lex_hash.h" #include "./sql/sql_select.h" #include "./sql/strfunc.h" #include "./sql/transaction.h" @@ -51,6 +51,7 @@ #include "./rdb_converter.h" #include "./rdb_datadic.h" #include "./rdb_iterator.h" +#include "./rdb_nosql_digest.h" static const size_t DEFAULT_FIELD_LIST_SIZE = 16; static const size_t MAX_NOSQL_COND_COUNT = 16; @@ -76,6 +77,17 @@ bool inline is_supported_item_func(Item_func::Functype type) { namespace { +LEX_CSTRING select_tok{STRING_WITH_LEN("SELECT")}; +LEX_CSTRING from_tok{STRING_WITH_LEN("FROM")}; +LEX_CSTRING where_tok{STRING_WITH_LEN("WHERE")}; +LEX_CSTRING force_tok{STRING_WITH_LEN("FORCE")}; +LEX_CSTRING index_tok{STRING_WITH_LEN("INDEX")}; +LEX_CSTRING order_tok{STRING_WITH_LEN("ORDER")}; +LEX_CSTRING by_tok{STRING_WITH_LEN("BY")}; +LEX_CSTRING limit_tok{STRING_WITH_LEN("LIMIT")}; +LEX_CSTRING asc_tok{STRING_WITH_LEN("ASC")}; +LEX_CSTRING desc_tok{STRING_WITH_LEN("DESC")}; + bool check_field_name_match(Field *field, const char *field_name) { return (field->field_name && !my_strcasecmp(system_charset_info, field->field_name, field_name)); @@ -1047,6 +1059,8 @@ class rpc_select_parser : public base_select_parser { m_columns(columns) { // initialize field_index m_field_index.assign(m_table->s->fields, -1); + // initialize digest_state + m_digest = m_thd->m_digest; } const base_cond *get_cond(uint index) const override { @@ -1065,9 +1079,73 @@ class rpc_select_parser : public base_select_parser { const myrocks_select_from_rpc *m_param; myrocks_columns *m_columns; std::vector m_field_index; + sql_digest_state *m_digest; rpc_cond m_cond_list[MAX_NOSQL_COND_COUNT]; int m_num_used_columns; + // TODO(ptgvo): move digest methods into rdb_nosql_digest.cc + bool check_digest_compute() { + return m_digest == nullptr || !pfs_param.m_esms_by_all_enabled || + !bypass_rpc_pfs_logging; + } + + void inline add_digest_token(uint token, Lexer_yystype *yylval) { + m_digest = digest_add_token(m_digest, token, yylval); + } + + bool add_digest_identifier(const std::string &ident) { + if (check_digest_compute()) { + return true; + } + + Lexer_yystype ident_token{}; + ident_token.lex_str.str = const_cast(ident.data()); + ident_token.lex_str.length = ident.length(); + + add_digest_token(nosql_ident_token(), &ident_token); + return false; + } + + bool add_digest_keyword(LEX_CSTRING key) { + if (check_digest_compute()) { + return true; + } + + const SYMBOL *symbol = + Lex_hash::sql_keywords.get_hash_symbol(key.str, key.length); + + if (symbol != nullptr) { + Lexer_yystype token{}; + token.keyword.symbol = symbol; + token.keyword.str = const_cast(key.str); + token.keyword.length = key.length; + + add_digest_token(symbol->tok, &token); + } + return false; + } + + bool add_digest_placeholder(myrocks_value_type val_type) { + if (check_digest_compute()) { + return true; + } + + Lexer_yystype val_token{.lex_str = NULL_STR}; + + add_digest_token(val_type == myrocks_value_type::UNSIGNED_INT + ? nosql_decimal_num_token() + : nosql_text_string_token(), + &val_token); + return false; + } + + bool add_digest_condition(const std::string &ident, Item_func::Functype op, + myrocks_value_type val_type) { + return add_digest_identifier(ident) || + add_digest_keyword(get_op_lex_string(op)) || + add_digest_placeholder(val_type); + } + bool parse_index() { if (!m_param->force_index.empty()) { uint pos = @@ -1080,6 +1158,12 @@ class rpc_select_parser : public base_select_parser { return true; } m_index = pos - 1; + + // FORCE INDEX keywords + add_digest_keyword(force_tok); + add_digest_keyword(index_tok); + + add_digest_identifier(m_param->force_index); } else { // Default to PRIMARY m_index = m_table->s->primary_key; @@ -1095,6 +1179,9 @@ class rpc_select_parser : public base_select_parser { return true; } + // SELECT keyword + add_digest_keyword(select_tok); + m_field_list.reserve(m_param->columns.size()); for (auto &fname : m_param->columns) { @@ -1107,7 +1194,13 @@ class rpc_select_parser : public base_select_parser { } add_field_list(field); + + add_digest_identifier(fname); } + + add_digest_keyword(from_tok); + add_digest_identifier(m_param->table_name); + return false; } @@ -1126,6 +1219,10 @@ class rpc_select_parser : public base_select_parser { return false; } + // ORDER BY keywords + add_digest_keyword(order_tok); + add_digest_keyword(by_tok); + bool is_first = true; KEY *key = &get_table()->key_info[get_index()]; uint cur_index = key->actual_key_parts; @@ -1135,6 +1232,11 @@ class rpc_select_parser : public base_select_parser { it.column.c_str(), is_first, cur_index)) { return true; } + + add_digest_identifier(it.column); + add_digest_keyword(it.op == myrocks_order_by_item::order_by_op::_DESC + ? desc_tok + : asc_tok); } return false; @@ -1248,6 +1350,8 @@ class rpc_select_parser : public base_select_parser { Item_func::IN_FUNC, found, more_values ? item.more_values : item.values.data(), item.num_values, &m_columns->at(idx)}; + add_digest_condition(item.column, Item_func::IN_FUNC, + desired_type); return false; } @@ -1295,12 +1399,16 @@ class rpc_select_parser : public base_select_parser { m_cond_list[m_cond_count++] = {op, found, &item.value, 1, &m_columns->at(idx)}; + add_digest_condition(item.column, op, desired_type); return false; } bool parse_where() { std::vector> fields; + // WHERE keyword + add_digest_keyword(where_tok); + for (const auto &item : m_param->where) { if (parse_cond(item)) { return true; @@ -1326,6 +1434,11 @@ class rpc_select_parser : public base_select_parser { m_select_limit = m_param->limit; m_offset_limit = m_param->limit_offset; + // LIMIT keyword + add_digest_keyword(limit_tok); + + add_digest_placeholder(myrocks_value_type::UNSIGNED_INT); + return false; } }; diff --git a/storage/rocksdb/rdb_datadic.h b/storage/rocksdb/rdb_datadic.h index 9ffe2ec46fa0..009ab154d05d 100644 --- a/storage/rocksdb/rdb_datadic.h +++ b/storage/rocksdb/rdb_datadic.h @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/storage/rocksdb/rdb_nosql_digest.cc b/storage/rocksdb/rdb_nosql_digest.cc new file mode 100644 index 000000000000..044504430d8d --- /dev/null +++ b/storage/rocksdb/rdb_nosql_digest.cc @@ -0,0 +1,26 @@ +#include "./rdb_nosql_digest.h" + +/* MySQL header files */ +#include "sql/lexer_yystype.h" +#include "sql/mysqld.h" +#include "sql/sql_lex_hash.h" +#include "sql/sql_yacc.h" + +/* PerfSchema header files */ +#include "storage/perfschema/pfs_server.h" + +namespace myrocks { + +uint nosql_ident_token() { + return IDENT; +} + +uint nosql_decimal_num_token() { + return DECIMAL_NUM; +} + +uint nosql_text_string_token() { + return TEXT_STRING; +} + +} // namespace myrocks diff --git a/storage/rocksdb/rdb_nosql_digest.h b/storage/rocksdb/rdb_nosql_digest.h new file mode 100644 index 000000000000..378588eaecea --- /dev/null +++ b/storage/rocksdb/rdb_nosql_digest.h @@ -0,0 +1,51 @@ +/* C++ standard header files */ +#include + +/* MySQL header files */ +#include "./lex_string.h" +#include "./m_string.h" +#include "sql/item_func.h" +#include "sql/sql_digest_stream.h" + +#pragma once + +/* + This file contains contains variables and functions that are used for digest + computation in nosql layer. +*/ + +namespace myrocks { + +// This should always be synced with rocksdb::convert_where_op +inline LEX_CSTRING get_op_lex_string(Item_func::Functype op) { + static LEX_CSTRING eq_tok{STRING_WITH_LEN("=")}; + static LEX_CSTRING lt_tok{STRING_WITH_LEN("<")}; + static LEX_CSTRING gt_tok{STRING_WITH_LEN(">")}; + static LEX_CSTRING le_tok{STRING_WITH_LEN("<=")}; + static LEX_CSTRING ge_tok{STRING_WITH_LEN(">=")}; + + switch (op) { + case Item_func::EQ_FUNC: + return eq_tok; + case Item_func::LT_FUNC: + return lt_tok; + case Item_func::GT_FUNC: + return gt_tok; + case Item_func::LE_FUNC: + return le_tok; + case Item_func::GE_FUNC: + return ge_tok; + default: + return eq_tok; + } +} + +/* + Wrappers around token id's found in sql_yacc.h header file. This is needed + because of macro collisions between sql_yacc.h and rocksdb headers. +*/ +uint nosql_ident_token(); +uint nosql_decimal_num_token(); +uint nosql_text_string_token(); + +} // namespace myrocks