From 54ed3939f7fc8008aac72999b6c5fc5dae9c0467 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 22 Dec 2023 23:09:27 -0800 Subject: [PATCH 001/121] MDEV-31657 Crash on query using CTE with the same name as a base table If a query contained a CTE whose name coincided with the name of one of the base tables used in the specification of the CTE and the query had at least two references to this CTE in the specifications of other CTEs then processing of the query led to unlimited recursion that ultimately caused a crash of the server. Any secondary non-recursive reference to a CTE requires creation of a copy of the CTE specification. All the references to CTEs in this copy must be resolved. If the specification contains a reference to a base table whose name coincides with the name of then CTE then it should be ensured that this reference in no way can be resolved against the name of the CTE. --- mysql-test/main/cte_nonrecursive.result | 45 ++++++++++++++++++++++++ mysql-test/main/cte_nonrecursive.test | 46 +++++++++++++++++++++++++ sql/sql_acl.cc | 5 --- sql/sql_cte.cc | 34 ++++++++++++------ sql/sql_cte.h | 6 ++-- sql/sql_lex.h | 6 ++-- sql/sql_view.cc | 3 +- 7 files changed, 124 insertions(+), 21 deletions(-) diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result index e86c101686c..f499b7a5321 100644 --- a/mysql-test/main/cte_nonrecursive.result +++ b/mysql-test/main/cte_nonrecursive.result @@ -2624,4 +2624,49 @@ a 1 1 DROP TABLE t1; +# +# MDEV-31657: CTE with the same name as base table used twice +# in another CTE +# +create table t (a int); +insert into t values (3), (7), (1); +with +t as (select * from t), +cte as (select t1.a as t1a, t2.a as t2a from t as t1, t as t2 where t1.a=t2.a) +select * from cte; +t1a t2a +3 3 +7 7 +1 1 +create table s (a int); +insert into s values (1), (4), (7); +with +t as (select * from t), +s as (select a-1 as a from s), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a +union +select t.a+1, s.a+1 from t, s where t.a=s.a+1) +select * from cte; +ta sa +3 3 +2 1 +8 7 +with +t as (select * from t), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a +union +select t.a+1, s.a+1 from t, s where t.a=s.a), +s as (select a+10 as a from s) +select * from cte; +ta sa +1 1 +7 7 +2 2 +8 8 +drop table t,s; +with +t as (select * from t), +cte as (select t1.a as t1a, t2.a as t2a from t as t1, t as t2 where t1.a=t2.a) +select * from cte; +ERROR 42S02: Table 'test.t' doesn't exist # End of 10.4 tests diff --git a/mysql-test/main/cte_nonrecursive.test b/mysql-test/main/cte_nonrecursive.test index a666ed3a25f..0d342edf97d 100644 --- a/mysql-test/main/cte_nonrecursive.test +++ b/mysql-test/main/cte_nonrecursive.test @@ -1967,4 +1967,50 @@ SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-31657: CTE with the same name as base table used twice +--echo # in another CTE +--echo # + +create table t (a int); +insert into t values (3), (7), (1); + +let $q1= +with +t as (select * from t), +cte as (select t1.a as t1a, t2.a as t2a from t as t1, t as t2 where t1.a=t2.a) +select * from cte; + +eval $q1; + +create table s (a int); +insert into s values (1), (4), (7); + +let $q2= +with +t as (select * from t), +s as (select a-1 as a from s), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a + union + select t.a+1, s.a+1 from t, s where t.a=s.a+1) +select * from cte; + +eval $q2; + +let $q3= +with +t as (select * from t), +cte as (select t.a as ta, s.a as sa from t, s where t.a=s.a + union + select t.a+1, s.a+1 from t, s where t.a=s.a), +s as (select a+10 as a from s) +select * from cte; + +eval $q3; + +drop table t,s; + +--ERROR ER_NO_SUCH_TABLE +eval $q1; + --echo # End of 10.4 tests diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 82f8101e929..6a6a6b3984d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8137,11 +8137,6 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, INSERT_ACL : SELECT_ACL); } - if (tl->with || !tl->db.str || - (tl->select_lex && - (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl)))) - continue; - const ACL_internal_table_access *access= get_cached_table_access(&t_ref->grant.m_internal, t_ref->get_db_name(), diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 0e422b30216..ce735ba26d1 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -105,6 +105,7 @@ bool LEX::check_dependencies_in_with_clauses() @param tables Points to the beginning of the sub-chain @param tables_last Points to the address with the sub-chain barrier + @param excl_spec Ignore the definition with this spec @details The method resolves tables references to CTE from the chain of @@ -146,7 +147,8 @@ bool LEX::check_dependencies_in_with_clauses() */ bool LEX::resolve_references_to_cte(TABLE_LIST *tables, - TABLE_LIST **tables_last) + TABLE_LIST **tables_last, + st_select_lex_unit *excl_spec) { With_element *with_elem= 0; @@ -155,7 +157,8 @@ bool LEX::resolve_references_to_cte(TABLE_LIST *tables, if (tbl->derived) continue; if (!tbl->db.str && !tbl->with) - tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl); + tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl, + excl_spec); if (!tbl->with) // no CTE matches table reference tbl { if (only_cte_resolution) @@ -243,7 +246,7 @@ LEX::check_cte_dependencies_and_resolve_references() return true; if (!with_cte_resolution) return false; - if (resolve_references_to_cte(query_tables, query_tables_last)) + if (resolve_references_to_cte(query_tables, query_tables_last, NULL)) return true; return false; } @@ -387,6 +390,7 @@ bool With_element::check_dependencies_in_spec() @param table The reference to the table that is looked for @param barrier The barrier with element for the search + @param excl_spec Ignore the definition with this spec @details The function looks through the elements of this with clause trying to find @@ -400,12 +404,15 @@ bool With_element::check_dependencies_in_spec() */ With_element *With_clause::find_table_def(TABLE_LIST *table, - With_element *barrier) + With_element *barrier, + st_select_lex_unit *excl_spec) { for (With_element *with_elem= with_list.first; with_elem != barrier; with_elem= with_elem->next) { + if (excl_spec && with_elem->spec == excl_spec) + continue; if (my_strcasecmp(system_charset_info, with_elem->get_name_str(), table->table_name.str) == 0 && !table->is_fqtn) @@ -465,7 +472,7 @@ With_element *find_table_def_in_with_clauses(TABLE_LIST *tbl, top_unit->with_element && top_unit->with_element->get_owner() == with_clause) barrier= top_unit->with_element; - found= with_clause->find_table_def(tbl, barrier); + found= with_clause->find_table_def(tbl, barrier, NULL); if (found) break; } @@ -520,10 +527,11 @@ void With_element::check_dependencies_in_select(st_select_lex *sl, { With_clause *with_clause= sl->master_unit()->with_clause; if (with_clause) - tbl->with= with_clause->find_table_def(tbl, NULL); + tbl->with= with_clause->find_table_def(tbl, NULL, NULL); if (!tbl->with) tbl->with= owner->find_table_def(tbl, - owner->with_recursive ? NULL : this); + owner->with_recursive ? NULL : this, + NULL); } if (!tbl->with) tbl->with= find_table_def_in_with_clauses(tbl, ctxt); @@ -1098,7 +1106,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex, */ lex->only_cte_resolution= old_lex->only_cte_resolution; if (lex->resolve_references_to_cte(lex->query_tables, - lex->query_tables_last)) + lex->query_tables_last, + spec)) { res= NULL; goto err; @@ -1264,6 +1273,7 @@ bool With_element::is_anchor(st_select_lex *sel) Search for the definition of the given table referred in this select node @param table reference to the table whose definition is searched for + @param excl_spec ignore the definition with this spec @details The method looks for the definition of the table whose reference is occurred @@ -1276,7 +1286,8 @@ bool With_element::is_anchor(st_select_lex *sel) NULL - otherwise */ -With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) +With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table, + st_select_lex_unit *excl_spec) { With_element *found= NULL; With_clause *containing_with_clause= NULL; @@ -1293,7 +1304,7 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) With_clause *attached_with_clause= sl->get_with_clause(); if (attached_with_clause && attached_with_clause != containing_with_clause && - (found= attached_with_clause->find_table_def(table, NULL))) + (found= attached_with_clause->find_table_def(table, NULL, excl_spec))) break; master_unit= sl->master_unit(); outer_sl= master_unit->outer_select(); @@ -1303,7 +1314,8 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) containing_with_clause= with_elem->get_owner(); With_element *barrier= containing_with_clause->with_recursive ? NULL : with_elem; - if ((found= containing_with_clause->find_table_def(table, barrier))) + if ((found= containing_with_clause->find_table_def(table, barrier, + excl_spec))) break; if (outer_sl && !outer_sl->get_with_element()) break; diff --git a/sql/sql_cte.h b/sql/sql_cte.h index 4bc3ed69582..4d56672e3cc 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -322,7 +322,8 @@ public: friend bool LEX::resolve_references_to_cte(TABLE_LIST *tables, - TABLE_LIST **tables_last); + TABLE_LIST **tables_last, + st_select_lex_unit *excl_spec); }; const uint max_number_of_elements_in_with_clause= sizeof(table_map)*8; @@ -422,7 +423,8 @@ public: void move_anchors_ahead(); - With_element *find_table_def(TABLE_LIST *table, With_element *barrier); + With_element *find_table_def(TABLE_LIST *table, With_element *barrier, + st_select_lex_unit *excl_spec); With_element *find_table_def_in_with_clauses(TABLE_LIST *table); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 0f2e096fdc6..2305616d5b3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1531,7 +1531,8 @@ public: master_unit()->cloned_from->with_element : master_unit()->with_element; } - With_element *find_table_def_in_with_clauses(TABLE_LIST *table); + With_element *find_table_def_in_with_clauses(TABLE_LIST *table, + st_select_lex_unit * excl_spec); bool check_unrestricted_recursive(bool only_standard_compliant); bool check_subqueries_with_recursive_references(); void collect_grouping_fields_for_derived(THD *thd, ORDER *grouping_list); @@ -4708,7 +4709,8 @@ public: bool check_dependencies_in_with_clauses(); bool check_cte_dependencies_and_resolve_references(); bool resolve_references_to_cte(TABLE_LIST *tables, - TABLE_LIST **tables_last); + TABLE_LIST **tables_last, + st_select_lex_unit *excl_spec); }; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 9f9a9716982..0dca5f7c226 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -295,7 +295,8 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) { if (!tbl->with && tbl->select_lex) - tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl); + tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl, + NULL); /* Ensure that we have some privileges on this table, more strict check will be done on column level after preparation, From 613d0194979849fb5b3dd752f13b14672a2409e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 4 Jan 2024 12:50:05 +0200 Subject: [PATCH 002/121] MDEV-33160 show_status_array() calls various functions via incompatible pointer In commit b4ff64568c88ab3ce559e7bd39853d9cbf86704a the signature of mysql_show_var_func was changed, but not all functions of that type were adjusted. When the server is configured with `cmake -DWITH_ASAN=ON` and compiled with clang, runtime errors would be flagged for invoking functions through an incompatible function pointer. Reviewed by: Michael 'Monty' Widenius --- sql/mysqld.cc | 144 +++++++++++++++++------------------- sql/sql_acl.cc | 8 +- sql/table_cache.cc | 4 +- sql/table_cache.h | 4 +- sql/threadpool.h | 3 - storage/sphinx/ha_sphinx.cc | 19 +++-- storage/sphinx/ha_sphinx.h | 6 -- storage/spider/spd_param.cc | 18 +++-- 8 files changed, 102 insertions(+), 104 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a1a8a862a8e..5713045056d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7180,8 +7180,8 @@ struct my_option my_long_options[]= MYSQL_TO_BE_IMPLEMENTED_OPTION("validate-user-plugins") // NO_EMBEDDED_ACCESS_CHECKS }; -static int show_queries(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_queries(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { var->type= SHOW_LONGLONG; var->value= &thd->query_id; @@ -7189,16 +7189,16 @@ static int show_queries(THD *thd, SHOW_VAR *var, char *buff, } -static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_net_compression(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { var->type= SHOW_MY_BOOL; var->value= &thd->net.compress; return 0; } -static int show_starttime(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_starttime(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7207,8 +7207,8 @@ static int show_starttime(THD *thd, SHOW_VAR *var, char *buff, } #ifdef ENABLED_PROFILING -static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_flushstatustime(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7218,32 +7218,28 @@ static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff, #endif #ifdef HAVE_REPLICATION -static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_rpl_status(THD *, SHOW_VAR *var, void *, system_status_var *, + enum_var_type) { var->type= SHOW_CHAR; var->value= const_cast(rpl_status_type[(int)rpl_status]); return 0; } -static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_slave_running(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { - Master_info *mi= NULL; - bool UNINIT_VAR(tmp); - - var->type= SHOW_MY_BOOL; - var->value= buff; - - if ((mi= get_master_info(&thd->variables.default_master_connection, - Sql_condition::WARN_LEVEL_NOTE))) + if (Master_info *mi= + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE)) { - tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING && - mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN); + *((my_bool*) buff)= + (mi->slave_running == MYSQL_SLAVE_RUN_READING && + mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN); mi->release(); + var->type= SHOW_MY_BOOL; + var->value= buff; } - if (mi) - *((my_bool *)buff)= tmp; else var->type= SHOW_UNDEF; return 0; @@ -7253,7 +7249,8 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff, /* How many masters this slave is connected to */ -static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff) +static int show_slaves_running(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONGLONG; var->value= buff; @@ -7264,19 +7261,17 @@ static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff) } -static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { - Master_info *mi; - - var->type= SHOW_LONGLONG; - var->value= buff; - - if ((mi= get_master_info(&thd->variables.default_master_connection, - Sql_condition::WARN_LEVEL_NOTE))) + if (Master_info *mi= + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE)) { *((longlong *)buff)= mi->received_heartbeats; mi->release(); + var->type= SHOW_LONGLONG; + var->value= buff; } else var->type= SHOW_UNDEF; @@ -7284,19 +7279,17 @@ static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff, } -static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_heartbeat_period(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { - Master_info *mi; - - var->type= SHOW_CHAR; - var->value= buff; - - if ((mi= get_master_info(&thd->variables.default_master_connection, - Sql_condition::WARN_LEVEL_NOTE))) + if (Master_info *mi= + get_master_info(&thd->variables.default_master_connection, + Sql_condition::WARN_LEVEL_NOTE)) { - sprintf(buff, "%.3f", mi->heartbeat_period); + sprintf(static_cast(buff), "%.3f", mi->heartbeat_period); mi->release(); + var->type= SHOW_CHAR; + var->value= buff; } else var->type= SHOW_UNDEF; @@ -7306,8 +7299,8 @@ static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff, #endif /* HAVE_REPLICATION */ -static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_open_tables(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7315,8 +7308,8 @@ static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_prepared_stmt_count(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7326,8 +7319,8 @@ static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_table_definitions(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7336,8 +7329,8 @@ static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff, } -static int show_flush_commands(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_flush_commands(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONGLONG; var->value= buff; @@ -7356,8 +7349,8 @@ static int show_flush_commands(THD *thd, SHOW_VAR *var, char *buff, inside an Event. */ -static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_version(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if( thd->vio_ok() && thd->net.vio->ssl_arg ) @@ -7367,8 +7360,8 @@ static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7379,8 +7372,8 @@ static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7395,8 +7388,8 @@ static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_LONG; var->value= buff; @@ -7408,8 +7401,8 @@ static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if( thd->vio_ok() && thd->net.vio->ssl_arg ) @@ -7419,9 +7412,10 @@ static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, void *buf, + system_status_var *, enum_var_type) { + char *buff= static_cast(buf); var->type= SHOW_CHAR; var->value= buff; if (thd->vio_ok() && thd->net.vio->ssl_arg) @@ -7506,8 +7500,8 @@ end: */ static int -show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if(thd->vio_ok() && thd->net.vio->ssl_arg) @@ -7516,7 +7510,7 @@ show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff, X509 *cert= SSL_get_certificate(ssl); const ASN1_TIME *not_before= X509_get0_notBefore(cert); - var->value= my_asn1_time_to_string(not_before, buff, + var->value= my_asn1_time_to_string(not_before, static_cast(buff), SHOW_VAR_FUNC_BUFF_SIZE); if (!var->value) return 1; @@ -7540,8 +7534,8 @@ show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff, */ static int -show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_CHAR; if(thd->vio_ok() && thd->net.vio->ssl_arg) @@ -7550,7 +7544,7 @@ show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff, X509 *cert= SSL_get_certificate(ssl); const ASN1_TIME *not_after= X509_get0_notAfter(cert); - var->value= my_asn1_time_to_string(not_after, buff, + var->value= my_asn1_time_to_string(not_after, static_cast(buff), SHOW_VAR_FUNC_BUFF_SIZE); if (!var->value) return 1; @@ -7604,7 +7598,7 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, void *buff, } -static int show_memory_used(THD *thd, SHOW_VAR *var, char *buff, +static int show_memory_used(THD *thd, SHOW_VAR *var, void *buff, struct system_status_var *status_var, enum enum_var_type scope) { @@ -7660,8 +7654,8 @@ static int debug_status_func(THD *thd, SHOW_VAR *var, void *buff, #endif #ifdef HAVE_POOL_OF_THREADS -int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +int show_threadpool_idle_threads(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_INT; var->value= buff; @@ -7670,8 +7664,8 @@ int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff, } -static int show_threadpool_threads(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_threadpool_threads(THD *, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_INT; var->value= buff; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6a6a6b3984d..1949a0c02b6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -11869,8 +11869,8 @@ static my_bool count_column_grants(void *grant_table, This must be performed under the mutex in order to make sure the iteration does not fail. */ -static int show_column_grants(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_column_grants(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope) { var->type= SHOW_ULONG; var->value= buff; @@ -11886,8 +11886,8 @@ static int show_column_grants(THD *thd, SHOW_VAR *var, char *buff, return 0; } -static int show_database_grants(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_database_grants(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope) { var->type= SHOW_UINT; var->value= buff; diff --git a/sql/table_cache.cc b/sql/table_cache.cc index 9b28e7b7b0f..ca7c25ae552 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -1345,8 +1345,8 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, } -int show_tc_active_instances(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +int show_tc_active_instances(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope) { var->type= SHOW_UINT; var->value= buff; diff --git a/sql/table_cache.h b/sql/table_cache.h index 3be7b5fe413..ee738eb8ba6 100644 --- a/sql/table_cache.h +++ b/sql/table_cache.h @@ -97,8 +97,8 @@ extern int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, bool no_dups= false); extern uint tc_records(void); -int show_tc_active_instances(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope); +int show_tc_active_instances(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope); extern void tc_purge(bool mark_flushed= false); extern void tc_add_table(THD *thd, TABLE *table); extern void tc_release_table(TABLE *table); diff --git a/sql/threadpool.h b/sql/threadpool.h index ea6c93b4a65..e4321327163 100644 --- a/sql/threadpool.h +++ b/sql/threadpool.h @@ -64,9 +64,6 @@ extern int tp_get_thread_count(); /* Activate threadpool scheduler */ extern void tp_scheduler(void); -extern int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope); - enum TP_PRIORITY { TP_PRIORITY_HIGH, TP_PRIORITY_LOW, diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index f2bc24c47d4..4549e8dccb6 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -3548,7 +3548,8 @@ CSphSEStats * sphinx_get_stats ( THD * thd, SHOW_VAR * out ) return 0; } -int sphinx_showfunc_total ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_total ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3559,7 +3560,8 @@ int sphinx_showfunc_total ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_total_found ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_total_found ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3570,7 +3572,8 @@ int sphinx_showfunc_total_found ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_time ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_time ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3581,7 +3584,8 @@ int sphinx_showfunc_time ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_word_count ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_word_count ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); if ( pStats ) @@ -3592,9 +3596,11 @@ int sphinx_showfunc_word_count ( THD * thd, SHOW_VAR * out, char * ) return 0; } -int sphinx_showfunc_words ( THD * thd, SHOW_VAR * out, char * sBuffer ) +static int sphinx_showfunc_words ( THD * thd, SHOW_VAR * out, void * buf, + system_status_var *, enum_var_type ) { #if MYSQL_VERSION_ID>50100 + char *sBuffer = static_cast(buf); if ( sphinx_hton_ptr ) { CSphTLS * pTls = (CSphTLS *) *thd_ha_data ( thd, sphinx_hton_ptr ); @@ -3649,7 +3655,8 @@ int sphinx_showfunc_words ( THD * thd, SHOW_VAR * out, char * sBuffer ) return 0; } -int sphinx_showfunc_error ( THD * thd, SHOW_VAR * out, char * ) +static int sphinx_showfunc_error ( THD * thd, SHOW_VAR * out, void *, + system_status_var *, enum_var_type ) { CSphSEStats * pStats = sphinx_get_stats ( thd, out ); out->type = SHOW_CHAR; diff --git a/storage/sphinx/ha_sphinx.h b/storage/sphinx/ha_sphinx.h index decd88bad5a..ddc1567328f 100644 --- a/storage/sphinx/ha_sphinx.h +++ b/storage/sphinx/ha_sphinx.h @@ -164,12 +164,6 @@ private: bool sphinx_show_status ( THD * thd ); #endif -int sphinx_showfunc_total_found ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_total ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_time ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_word_count ( THD *, SHOW_VAR *, char * ); -int sphinx_showfunc_words ( THD *, SHOW_VAR *, char * ); - // // $Id: ha_sphinx.h 4818 2014-09-24 08:53:38Z tomat $ // diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index 5eaf9518048..5c86af68c0a 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -115,7 +115,8 @@ extern volatile ulonglong spider_mon_table_cache_version_req; } #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS -static int spider_direct_update(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_update(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { int error_num = 0; SPIDER_TRX *trx; @@ -126,7 +127,8 @@ static int spider_direct_update(THD *thd, SHOW_VAR *var, char *buff) DBUG_RETURN(error_num); } -static int spider_direct_delete(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_delete(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { int error_num = 0; SPIDER_TRX *trx; @@ -138,7 +140,8 @@ static int spider_direct_delete(THD *thd, SHOW_VAR *var, char *buff) } #endif -static int spider_direct_order_limit(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_order_limit(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { int error_num = 0; SPIDER_TRX *trx; @@ -149,7 +152,8 @@ static int spider_direct_order_limit(THD *thd, SHOW_VAR *var, char *buff) DBUG_RETURN(error_num); } -static int spider_direct_aggregate(THD *thd, SHOW_VAR *var, char *buff) +static int spider_direct_aggregate(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { int error_num = 0; SPIDER_TRX *trx; @@ -160,7 +164,8 @@ static int spider_direct_aggregate(THD *thd, SHOW_VAR *var, char *buff) DBUG_RETURN(error_num); } -static int spider_parallel_search(THD *thd, SHOW_VAR *var, char *buff) +static int spider_parallel_search(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { int error_num = 0; SPIDER_TRX *trx; @@ -172,7 +177,8 @@ static int spider_parallel_search(THD *thd, SHOW_VAR *var, char *buff) } #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) -static int spider_hs_result_free(THD *thd, SHOW_VAR *var, char *buff) +static int spider_hs_result_free(THD *thd, SHOW_VAR *var, void *, + system_status_var *, enum_var_type) { int error_num = 0; SPIDER_TRX *trx; From ac0ce4451958a5c95c9b2ede242586c600836f81 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 3 Jan 2024 12:04:50 +0100 Subject: [PATCH 003/121] ./mtr --skip-not-found should skip combinations too With the result like encryption.innochecksum 'debug' [ skipped ] combination not found instead of *** ERROR: Could not run encryption.innochecksum with 'debug' combination(s) --- mysql-test/lib/mtr_cases.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index a4473a07e81..666ac74791e 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -892,6 +892,12 @@ sub collect_one_test_case { } my @no_combs = grep { $test_combs{$_} == 1 } keys %test_combs; if (@no_combs) { + if ($::opt_skip_not_found) { + push @{$tinfo->{combinations}}, @no_combs; + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= "combination not found"; + return $tinfo; + } mtr_error("Could not run $name with '".( join(',', sort @no_combs))."' combination(s)"); } From 8172d07785245ad129dfaa9fecca4da206fd3e07 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 3 Jan 2024 18:36:36 +0100 Subject: [PATCH 004/121] MDEV-33090 plugin/auth_pam/testing/pam_mariadb_mtr.c doesn't compile on Solaris Fix by Rainer Orth --- plugin/auth_pam/testing/pam_mariadb_mtr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/auth_pam/testing/pam_mariadb_mtr.c b/plugin/auth_pam/testing/pam_mariadb_mtr.c index d4c79f31330..dc2bc150dc9 100644 --- a/plugin/auth_pam/testing/pam_mariadb_mtr.c +++ b/plugin/auth_pam/testing/pam_mariadb_mtr.c @@ -10,8 +10,8 @@ #include #include -#include #include +#include #define N 3 From f7573e7a837af75768b518936f99c4df634e1b79 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 3 Jan 2024 18:55:16 +0100 Subject: [PATCH 005/121] MDEV-33093 plugin/disks/information_schema_disks.cc doesn't compile on Solaris Fix by Rainer Orth --- plugin/disks/information_schema_disks.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugin/disks/information_schema_disks.cc b/plugin/disks/information_schema_disks.cc index 01c6c0e173f..1be8fce37fa 100644 --- a/plugin/disks/information_schema_disks.cc +++ b/plugin/disks/information_schema_disks.cc @@ -19,10 +19,14 @@ #include #if defined(HAVE_GETMNTENT) #include +#elif defined(HAVE_SYS_MNTENT) +#include #elif !defined(HAVE_GETMNTINFO_TAKES_statvfs) /* getmntinfo (the not NetBSD variants) */ #include +#if defined(HAVE_SYS_UCRED) #include +#endif #include #endif #if defined(HAVE_GETMNTENT_IN_SYS_MNTAB) From ca276a0f3fcb45ff0abc011e334c700e0c5d4315 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 5 Jan 2024 09:35:57 +1100 Subject: [PATCH 006/121] MDEV-33169 Reset sequence used fields after check in alter sequence The bitmap is temporarily flipped to ~0 for the sake of checking all fields. It needs to be restored because it will be reused in second and subsequent ps execution. --- mysql-test/suite/sql_sequence/alter.result | 49 ++++++++++++++++++++++ mysql-test/suite/sql_sequence/alter.test | 35 ++++++++++++++++ sql/sql_sequence.cc | 2 + 3 files changed, 86 insertions(+) diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index 68d42e52784..d4e930ebb92 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -252,3 +252,52 @@ SELECT NEXTVAL(s); NEXTVAL(s) 1 DROP SEQUENCE s; +# +# MDEV-33169 Alter sequence 2nd ps fails while alter sequence 2nd time (no ps) succeeds +# +create sequence s; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM +alter sequence s maxvalue 123; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +alter sequence s maxvalue 123; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +drop sequence s; +create sequence s; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM +prepare stmt from 'alter sequence s maxvalue 123'; +execute stmt; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +execute stmt; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +deallocate prepare stmt; +drop sequence s; +create sequence s; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM +create procedure p() alter sequence s maxvalue 123; +call p; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +call p; +show create sequence s; +Table Create Table +s CREATE SEQUENCE `s` start with 1 minvalue 1 maxvalue 123 increment by 1 cache 1000 nocycle ENGINE=MyISAM +drop procedure p; +drop sequence s; +# +# End of 10.4 tests +# diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index a771c9bba2f..015aba22af6 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -167,3 +167,38 @@ ALTER TABLE s ORDER BY cache_size; SELECT NEXTVAL(s); DROP SEQUENCE s; --enable_ps2_protocol + +--echo # +--echo # MDEV-33169 Alter sequence 2nd ps fails while alter sequence 2nd time (no ps) succeeds +--echo # +create sequence s; +show create sequence s; +alter sequence s maxvalue 123; +show create sequence s; +alter sequence s maxvalue 123; +show create sequence s; +drop sequence s; + +create sequence s; +show create sequence s; +prepare stmt from 'alter sequence s maxvalue 123'; +execute stmt; +show create sequence s; +execute stmt; +show create sequence s; +deallocate prepare stmt; +drop sequence s; + +create sequence s; +show create sequence s; +create procedure p() alter sequence s maxvalue 123; +call p; +show create sequence s; +call p; +show create sequence s; +drop procedure p; +drop sequence s; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index ab77eabfa28..405b2d5b003 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -924,6 +924,7 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) TABLE_LIST *first_table= lex->query_tables; TABLE *table; sequence_definition *new_seq= lex->create_info.seq_create_info; + uint saved_used_fields= new_seq->used_fields; SEQUENCE *seq; No_such_table_error_handler no_such_table_handler; DBUG_ENTER("Sql_cmd_alter_sequence::execute"); @@ -1043,5 +1044,6 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) my_ok(thd); end: + new_seq->used_fields= saved_used_fields; DBUG_RETURN(error); } From 9322ef03e339ee8fcea25231c73c2f63d56c0d49 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 Nov 2023 11:18:16 +0400 Subject: [PATCH 007/121] MDEV-32645 CAST(AS UNSIGNED) fails with --view-protocol Item_float::neg() did not preserve the "presentation" from "this". So CAST(-1e0 AS UNSIGNED) -- cast from double to unsigned changes its meaning to: CAST(-1 AS UNSIGNED) -- cast signed to undigned Fixing Item_float::neg() to construct the new value for Item_float::presentation as follows: - if the old value starts with minus, then the minus is truncated: '-2e0' -> '2e0' - otherwise, minus sign followed by its old value: '1e0' -> '-1e0' --- mysql-test/main/cast.test | 3 --- mysql-test/main/type_float.result | 37 +++++++++++++++++++++++++++++++ mysql-test/main/type_float.test | 26 ++++++++++++++++++++++ sql/item.cc | 20 ++++++++++++++++- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/cast.test b/mysql-test/main/cast.test index ce4b1f6a574..5a0f87beb69 100644 --- a/mysql-test/main/cast.test +++ b/mysql-test/main/cast.test @@ -768,14 +768,11 @@ INSERT INTO t1 VALUES (-1.0); SELECT * FROM t1; DROP TABLE t1; -#enable after MDEV-32645 is fixed ---disable_view_protocol SELECT CAST(-1e0 AS UNSIGNED); CREATE TABLE t1 (a BIGINT UNSIGNED); INSERT INTO t1 VALUES (-1e0); SELECT * FROM t1; DROP TABLE t1; ---enable_view_protocol SELECT CAST(-1e308 AS UNSIGNED); CREATE TABLE t1 (a BIGINT UNSIGNED); diff --git a/mysql-test/main/type_float.result b/mysql-test/main/type_float.result index 500f906642d..fa850cf9b34 100644 --- a/mysql-test/main/type_float.result +++ b/mysql-test/main/type_float.result @@ -1167,5 +1167,42 @@ d 50 fdbl 123.456.789,12345678000000000000000000000000000000 fdec 123.456.789,12345678900000000000000000000000000000 # +# MDEV-32645 CAST(AS UNSIGNED) fails with --view-protocol +# +SELECT +CAST(-1e0 AS UNSIGNED), +CAST(--2e0 AS UNSIGNED), +CAST(---3e0 AS UNSIGNED), +CAST(----4e0 AS UNSIGNED); +CAST(-1e0 AS UNSIGNED) CAST(--2e0 AS UNSIGNED) CAST(---3e0 AS UNSIGNED) CAST(----4e0 AS UNSIGNED) +0 2 0 4 +Warnings: +Note 1916 Got overflow when converting '-1' to UNSIGNED BIGINT. Value truncated +Note 1916 Got overflow when converting '-3' to UNSIGNED BIGINT. Value truncated +EXPLAIN EXTENDED SELECT +CAST(-1e0 AS UNSIGNED), +CAST(--2e0 AS UNSIGNED), +CAST(---3e0 AS UNSIGNED), +CAST(----4e0 AS UNSIGNED); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select cast(-1e0 as unsigned) AS `CAST(-1e0 AS UNSIGNED)`,cast(2e0 as unsigned) AS `CAST(--2e0 AS UNSIGNED)`,cast(-3e0 as unsigned) AS `CAST(---3e0 AS UNSIGNED)`,cast(4e0 as unsigned) AS `CAST(----4e0 AS UNSIGNED)` +CREATE VIEW v1 AS SELECT +CAST(-1e0 AS UNSIGNED), +CAST(--2e0 AS UNSIGNED), +CAST(---3e0 AS UNSIGNED), +CAST(----4e0 AS UNSIGNED); +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(-1e0 as unsigned) AS `CAST(-1e0 AS UNSIGNED)`,cast(2e0 as unsigned) AS `CAST(--2e0 AS UNSIGNED)`,cast(-3e0 as unsigned) AS `CAST(---3e0 AS UNSIGNED)`,cast(4e0 as unsigned) AS `CAST(----4e0 AS UNSIGNED)` latin1 latin1_swedish_ci +SELECT * FROM v1; +CAST(-1e0 AS UNSIGNED) CAST(--2e0 AS UNSIGNED) CAST(---3e0 AS UNSIGNED) CAST(----4e0 AS UNSIGNED) +0 2 0 4 +Warnings: +Note 1916 Got overflow when converting '-1' to UNSIGNED BIGINT. Value truncated +Note 1916 Got overflow when converting '-3' to UNSIGNED BIGINT. Value truncated +DROP VIEW v1; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_float.test b/mysql-test/main/type_float.test index f1041080e26..f1d74f2f8d7 100644 --- a/mysql-test/main/type_float.test +++ b/mysql-test/main/type_float.test @@ -713,6 +713,32 @@ $$ DELIMITER ;$$ --horizontal_results +--echo # +--echo # MDEV-32645 CAST(AS UNSIGNED) fails with --view-protocol +--echo # + +SELECT + CAST(-1e0 AS UNSIGNED), + CAST(--2e0 AS UNSIGNED), + CAST(---3e0 AS UNSIGNED), + CAST(----4e0 AS UNSIGNED); + +EXPLAIN EXTENDED SELECT + CAST(-1e0 AS UNSIGNED), + CAST(--2e0 AS UNSIGNED), + CAST(---3e0 AS UNSIGNED), + CAST(----4e0 AS UNSIGNED); + +CREATE VIEW v1 AS SELECT + CAST(-1e0 AS UNSIGNED), + CAST(--2e0 AS UNSIGNED), + CAST(---3e0 AS UNSIGNED), + CAST(----4e0 AS UNSIGNED); + +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 21190b38e1a..6d30d63bc11 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6896,7 +6896,25 @@ Item *Item_float::neg(THD *thd) else if (value < 0 && max_length) max_length--; value= -value; - presentation= 0; + if (presentation) + { + if (*presentation == '-') + { + // Strip double minus: -(-1) -> '1' instead of '--1' + presentation++; + } + else + { + size_t presentation_length= strlen(presentation); + if (char *tmp= (char*) thd->alloc(presentation_length + 2)) + { + tmp[0]= '-'; + // Copy with the trailing '\0' + memcpy(tmp + 1, presentation, presentation_length + 1); + presentation= tmp; + } + } + } name= null_clex_str; return this; } From c6e1ffd1a07fc451e7211b0d00edbace78137276 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 31 Dec 2023 23:30:48 +0100 Subject: [PATCH 008/121] MDEV-33148 A connection can control RAND() in following connection initialize THD::rand in THD::init() not in THD::THD(), because the former is also called when a THD is reused - in COM_CHANGE_USER and in taking a THD from the cache. Also use current cycle timer for more unpreditability --- sql/sql_class.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b4893581e1a..179e2a1a9a5 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -684,7 +684,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) wsrep_wfc() #endif /*WITH_WSREP */ { - ulong tmp; bzero(&variables, sizeof(variables)); /* @@ -834,14 +833,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) tablespace_op=FALSE; - /* - Initialize the random generator. We call my_rnd() without a lock as - it's not really critical if two threads modifies the structure at the - same time. We ensure that we have an unique number foreach thread - by adding the address of the stack. - */ - tmp= (ulong) (my_rnd(&sql_rand) * 0xffffffff); - my_rnd_init(&rand, tmp + (ulong)((size_t) &rand), tmp + (ulong) ::global_query_id); substitute_null_with_insert_id = FALSE; lock_info.mysql_thd= (void *)this; @@ -1297,6 +1288,17 @@ void THD::init() /* Set to handle counting of aborted connections */ userstat_running= opt_userstat_running; last_global_update_time= current_connect_time= time(NULL); + + /* + Initialize the random generator. We call my_rnd() without a lock as + it's not really critical if two threads modify the structure at the + same time. We ensure that we have a unique number for each thread + by adding the address of this THD. + */ + ulong tmp= (ulong) (my_rnd(&sql_rand) * 0xffffffff); + my_rnd_init(&rand, tmp + (ulong)(intptr) this, + (ulong)(my_timer_cycles() + global_query_id)); + #if defined(ENABLED_DEBUG_SYNC) /* Initialize the Debug Sync Facility. See debug_sync.cc. */ debug_sync_init_thread(this); From 2310f659f528a189bb9c2a8e70a63e7ee7702780 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Wed, 10 Jan 2024 10:11:43 +1100 Subject: [PATCH 009/121] MDEV-8941 Compile on Solaris (SPARC) fails with errors in filamvct.cpp There are a large number of uses of `strerror` in the codebase, the local declaration in `storage/connect/tabvct.cpp` is the only one. Given that none is needed elsewhere, I conclude that this instance can simply be removed. --- storage/connect/tabvct.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp index 9cf5f41d1fe..f5710688d3c 100644 --- a/storage/connect/tabvct.cpp +++ b/storage/connect/tabvct.cpp @@ -71,11 +71,6 @@ #include "tabvct.h" #include "valblk.h" -#if defined(UNIX) -//add dummy strerror (NGC) -char *strerror(int num); -#endif // UNIX - /***********************************************************************/ /* External function. */ /***********************************************************************/ From eabc74aaef472cb415f4ead502559ca1c27efbc8 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 10 Jan 2024 16:36:39 +1100 Subject: [PATCH 010/121] MDEV-33008 Fix spider table discovery A new column was introduced to the show index output in 10.6 in f691d9865becfd242ba44cc632034433336af1e7 Thus we update the check of the number of columns to be at least 13, rather than exactly 13. Also backport an err number and format from 10.5 for better error messages when the column number is wrong. --- .../spider/bugfix/r/mdev_33008.result | 25 +++++++++++++++++++ .../spider/bugfix/t/mdev_33008.test | 24 ++++++++++++++++++ storage/spider/spd_db_mysql.cc | 9 ++++--- storage/spider/spd_err.h | 2 ++ 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_33008.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_33008.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33008.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33008.result new file mode 100644 index 00000000000..3bcb4bb038a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33008.result @@ -0,0 +1,25 @@ +for master_1 +for child2 +for child3 +set spider_same_server_link=on; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 ( +`id` int(11) NOT NULL AUTO_INCREMENT, +`code` varchar(10) DEFAULT NULL, +PRIMARY KEY (`id`) +); +create table t1 ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `code` varchar(10) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=SPIDER DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"' +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33008.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33008.test new file mode 100644 index 00000000000..48d9a4f01ec --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33008.test @@ -0,0 +1,24 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +set spider_same_server_link=on; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `code` varchar(10) DEFAULT NULL, + PRIMARY KEY (`id`) +); +create table t1 ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +show create table t1; +drop table t1, t2; + +drop server srv; +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index e689c9d93f0..d2e9dc1f0ee 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1566,10 +1566,13 @@ int spider_db_mbase_result::fetch_index_for_discover_table_structure( } DBUG_RETURN(0); } - if (num_fields() != 13) + if (num_fields() < 13) { - DBUG_PRINT("info",("spider num_fields != 13")); - my_printf_error(ER_SPIDER_UNKNOWN_NUM, ER_SPIDER_UNKNOWN_STR, MYF(0)); + DBUG_PRINT("info",("spider num_fields < 13")); + my_printf_error(ER_SPIDER_CANT_NUM, ER_SPIDER_CANT_STR1, MYF(0), + "fetch index for table structure discovery because of " + "wrong number of columns in SHOW INDEX FROM output: ", + num_fields()); DBUG_RETURN(ER_SPIDER_UNKNOWN_NUM); } bool first = TRUE; diff --git a/storage/spider/spd_err.h b/storage/spider/spd_err.h index 9889fcfa7fb..d8f11e18f26 100644 --- a/storage/spider/spd_err.h +++ b/storage/spider/spd_err.h @@ -127,6 +127,8 @@ #define ER_SPIDER_SAME_SERVER_LINK_NUM 12720 #define ER_SPIDER_SAME_SERVER_LINK_STR1 "Host:%s and Socket:%s aim self server. Please change spider_same_server_link parameter if this link is required." #define ER_SPIDER_SAME_SERVER_LINK_STR2 "Host:%s and Port:%ld aim self server. Please change spider_same_server_link parameter if this link is required." +#define ER_SPIDER_CANT_NUM 12721 +#define ER_SPIDER_CANT_STR1 "Can't %s%d" #define ER_SPIDER_COND_SKIP_NUM 12801 #define ER_SPIDER_UNKNOWN_NUM 12500 From bc3d416a17c9d35382f2db6387e51619e80c59da Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 10 Jan 2024 16:37:36 +1100 Subject: [PATCH 011/121] MDEV-29718 Fix spider detection of same data node server When the host is not specified, it defaults to localhost. --- storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result | 4 ++++ .../mysql-test/spider/bugfix/r/mdev_28739_simple.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result | 1 + storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result | 1 + .../spider/bugfix/r/spider_join_with_non_spider.result | 1 + storage/spider/mysql-test/spider/bugfix/r/subquery.result | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test | 5 +++++ .../spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test | 1 + storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test | 1 + .../spider/bugfix/t/spider_join_with_non_spider.test | 1 + storage/spider/mysql-test/spider/bugfix/t/subquery.test | 1 + storage/spider/spd_db_mysql.cc | 4 ++-- 33 files changed, 41 insertions(+), 2 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result index b0a430e0e21..326b84a030e 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_26151.result @@ -6,6 +6,9 @@ for child2 for child3 set @old_spider_bgs_mode= @@spider_bgs_mode; set session spider_bgs_mode=1; +set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table td (a int, PRIMARY KEY (a)); create table ts (a int, PRIMARY KEY (a)) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv_mdev_26151",TABLE "td", casual_read "3"'; @@ -26,6 +29,7 @@ min(a) drop table td, ts; drop server srv_mdev_26151; set session spider_bgs_mode=@old_spider_bgs_mode; +set global spider_same_server_link=@old_spider_same_server_link; for master_1 for child2 for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result index db232f8a6d3..1c337c3d2dd 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28739_simple.result @@ -5,6 +5,7 @@ for master_1 for child2 for child3 set global query_cache_type= on; +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result index fae3cc6b6ce..7e4fd3cd084 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); # testing monitoring_* diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result index edac80d9761..e92fb199575 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28998.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result index af4bef1efa9..f58ab605e11 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); CREATE TABLE t2 (b INT); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result index 4d9095830d1..365c3d6373a 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29456.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result index 17390346a99..604515964f3 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29963.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t (a INT) ENGINE=Spider; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result index e1dca495047..ee53009e3f2 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30014.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result index 58873d2c6e5..cefa5248d44 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result index 62b06336ff6..f156cf38a15 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31338.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t (c BLOB) ENGINE=InnoDB; CREATE TABLE ts (c BLOB) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result index 645fc62862d..b3a4c752565 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31524.result @@ -5,6 +5,7 @@ for master_1 for child2 for child3 SET @old_spider_read_only_mode = @@session.spider_read_only_mode; +set spider_same_server_link=1; CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); set session spider_read_only_mode = default; create table t2 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result index 94b76de7df4..5197abd3fb6 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)); CREATE TABLE t2 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)) ENGINE=SPIDER COMMENT='srv "srv", WRAPPER "mysql", TABLE "t1"'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result index 04d7e884676..cbc91432dbc 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31996.result @@ -1,6 +1,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); set session spider_delete_all_rows_type=0; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result index bdc580d421a..c3bdef9870d 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c varchar(16)); diff --git a/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result b/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result index b9c1c5c9de5..420ca657a33 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result +++ b/storage/spider/mysql-test/spider/bugfix/r/spider_join_with_non_spider.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); create table t2 (d int); diff --git a/storage/spider/mysql-test/spider/bugfix/r/subquery.result b/storage/spider/mysql-test/spider/bugfix/r/subquery.result index c6ea45e2dc0..280f57155bd 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/subquery.result +++ b/storage/spider/mysql-test/spider/bugfix/r/subquery.result @@ -4,6 +4,7 @@ for master_1 for child2 for child3 +set spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c1 int); create table t2 (c2 int); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test index f9e157d33e6..dcf1438fb80 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26151.test @@ -14,6 +14,10 @@ --let $srv=srv_mdev_26151 set @old_spider_bgs_mode= @@spider_bgs_mode; set session spider_bgs_mode=1; +set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; + evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); # casual_read != 0 && casual_read != 1 @@ -42,6 +46,7 @@ drop table td, ts; eval drop server $srv; set session spider_bgs_mode=@old_spider_bgs_mode; +set global spider_same_server_link=@old_spider_same_server_link; --disable_query_log --disable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test index 7a011520bb6..feff85df6b3 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28739_simple.test @@ -12,6 +12,7 @@ #set @@global.debug_dbug="d:t:i:o,mysqld.trace"; set global query_cache_type= on; +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t2 (c int); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test index 4f23168ec1b..a1642f7a9cd 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test @@ -9,6 +9,7 @@ # This test covers some table params under consideration for inclusion # in the engine-defined options to be implemented in MDEV-28856. +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test index e1735706341..66e3a15addb 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test @@ -12,6 +12,7 @@ if (`select not(count(*)) from information_schema.system_variables where variabl --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test index ac116fd0e4f..2e56583d831 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29163.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test index 16291f82075..89d53227c6c 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29456.test @@ -8,6 +8,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test index ab7a4ded07c..93b38c7963c 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29963.test @@ -7,6 +7,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test index 4dc3dafab24..9c59adc80dd 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30014.test @@ -7,6 +7,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test index 03417013b07..36e06f3f3c4 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30392.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 (a INT); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test index e628c3b921d..a3698c97717 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31338.test @@ -9,6 +9,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t (c BLOB) ENGINE=InnoDB; CREATE TABLE ts (c BLOB) ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"'; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test index 64cbf4154aa..a5942fad2b3 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31524.test @@ -10,6 +10,7 @@ --let $srv=srv_mdev_31524 SET @old_spider_read_only_mode = @@session.spider_read_only_mode; +set spider_same_server_link=1; evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); # when the user does not set var nor the table option, the default diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test index bec9dd6c316..4dfe3b57e50 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31645.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); CREATE TABLE t1 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test index 3e823790c82..93b004a06eb 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31996.test @@ -4,6 +4,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test index 94081d24ad8..144387452f7 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); diff --git a/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test b/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test index 7b5d38014ed..294b469a8a5 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test +++ b/storage/spider/mysql-test/spider/bugfix/t/spider_join_with_non_spider.test @@ -8,6 +8,7 @@ --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c int); create table t2 (d int); diff --git a/storage/spider/mysql-test/spider/bugfix/t/subquery.test b/storage/spider/mysql-test/spider/bugfix/t/subquery.test index 7a50719603d..70238a524a6 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/subquery.test +++ b/storage/spider/mysql-test/spider/bugfix/t/subquery.test @@ -6,6 +6,7 @@ --source ../../t/test_init.inc --enable_result_log --enable_query_log +set spider_same_server_link=1; evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); create table t1 (c1 int); create table t2 (c2 int); diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index d2e9dc1f0ee..fe83c652260 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1985,7 +1985,7 @@ int spider_db_mbase::connect( if (!spider_param_same_server_link(thd)) { - if (!strcmp(tgt_host, my_localhost)) + if (!strcmp(tgt_host, my_localhost) || !tgt_host || !tgt_host[0]) { if (!strcmp(tgt_socket, *spd_mysqld_unix_port)) { @@ -1995,7 +1995,7 @@ int spider_db_mbase::connect( DBUG_RETURN(ER_SPIDER_SAME_SERVER_LINK_NUM); } } else if (!strcmp(tgt_host, "127.0.0.1") || - !strcmp(tgt_host, glob_hostname)) + !strcmp(tgt_host, glob_hostname) || !tgt_host || !tgt_host[0]) { if (tgt_port == (long) *spd_mysqld_port) { From 8b0fb154f767daf0870d751957a402fe12622848 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 10 Jan 2024 00:32:50 +0100 Subject: [PATCH 012/121] MDEV-33093 plugin/disks/information_schema_disks.cc doesn't compile on Solaris second part of the fix by Rainer Orth --- config.h.cmake | 1 + plugin/disks/CMakeLists.txt | 2 ++ plugin/disks/information_schema_disks.cc | 9 ++++----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/config.h.cmake b/config.h.cmake index da2fc539bab..56c2bc3bcdc 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -72,6 +72,7 @@ #cmakedefine HAVE_SYS_IPC_H 1 #cmakedefine HAVE_SYS_MALLOC_H 1 #cmakedefine HAVE_SYS_MMAN_H 1 +#cmakedefine HAVE_SYS_MNTENT_H 1 #cmakedefine HAVE_SYS_NDIR_H 1 #cmakedefine HAVE_SYS_PTE_H 1 #cmakedefine HAVE_SYS_PTEM_H 1 diff --git a/plugin/disks/CMakeLists.txt b/plugin/disks/CMakeLists.txt index e4cf0dc1de3..408a4324d1b 100644 --- a/plugin/disks/CMakeLists.txt +++ b/plugin/disks/CMakeLists.txt @@ -5,6 +5,8 @@ CHECK_SYMBOL_EXISTS (getmntent "sys/mnttab.h" HAVE_GETMNTENT_IN_SYS_MNTAB) CHECK_SYMBOL_EXISTS (setmntent "mntent.h" HAVE_SETMNTENT) CHECK_SYMBOL_EXISTS (getmntinfo "sys/types.h;sys/mount.h" HAVE_GETMNTINFO) +CHECK_INCLUDE_FILES (sys/mntent.h HAVE_SYS_MNTENT_H) + IF (HAVE_GETMNTINFO) CHECK_CXX_SOURCE_COMPILES(" #include diff --git a/plugin/disks/information_schema_disks.cc b/plugin/disks/information_schema_disks.cc index 1be8fce37fa..cbc749ff603 100644 --- a/plugin/disks/information_schema_disks.cc +++ b/plugin/disks/information_schema_disks.cc @@ -19,19 +19,18 @@ #include #if defined(HAVE_GETMNTENT) #include -#elif defined(HAVE_SYS_MNTENT) -#include -#elif !defined(HAVE_GETMNTINFO_TAKES_statvfs) +#elif defined(HAVE_GETMNTINFO) && !defined(HAVE_GETMNTINFO_TAKES_statvfs) /* getmntinfo (the not NetBSD variants) */ #include -#if defined(HAVE_SYS_UCRED) #include -#endif #include #endif #if defined(HAVE_GETMNTENT_IN_SYS_MNTAB) #include #define HAVE_GETMNTENT +#if defined(HAVE_SYS_MNTENT_H) +#include +#endif #endif #include #include From c4ebf87f862ad6ab610e553a94dfa385a94a116c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Dec 2023 21:02:44 +0100 Subject: [PATCH 013/121] MDEV-32984 Update federated table and column privileges mark auto-inc columns for read/write on INSERT, but only for read on UPDATE --- mysql-test/suite/federated/update.result | 36 ++++++++++++++++++++++++ mysql-test/suite/federated/update.test | 32 +++++++++++++++++++++ sql/log_event_server.cc | 2 +- sql/table.cc | 9 +++--- sql/table.h | 2 +- 5 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/federated/update.result create mode 100644 mysql-test/suite/federated/update.test diff --git a/mysql-test/suite/federated/update.result b/mysql-test/suite/federated/update.result new file mode 100644 index 00000000000..1905f80ed71 --- /dev/null +++ b/mysql-test/suite/federated/update.result @@ -0,0 +1,36 @@ +connect master,127.0.0.1,root,,test,$MASTER_MYPORT,; +connect slave,127.0.0.1,root,,test,$SLAVE_MYPORT,; +connection master; +CREATE DATABASE federated; +connection slave; +CREATE DATABASE federated; +# +# MDEV-32984 Update federated table and column privileges +# +connection slave; +create database db1; +create user my@localhost identified by '1qaz2wsx'; +create table db1.t1 ( +f1 int auto_increment primary key, +f2 varchar(50), +f3 varchar(50), +unique (f2) +); +grant insert, select (f1, f2, f3), update (f3) on db1.t1 to my@localhost; +connection master; +create table tt1 engine=federated connection='mysql://my:1qaz2wsx@localhost:$SLAVE_MYPORT/db1/t1'; +insert into tt1 (f2,f3) values ('test','123'); +select * from tt1; +f1 f2 f3 +1 test 123 +update tt1 set f3='123456' where f2='test'; +drop table tt1; +connection slave; +drop database db1; +drop user my@localhost; +connection master; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; +connection slave; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/update.test b/mysql-test/suite/federated/update.test new file mode 100644 index 00000000000..5a0414f1e1a --- /dev/null +++ b/mysql-test/suite/federated/update.test @@ -0,0 +1,32 @@ +source include/federated.inc; +source have_federatedx.inc; + +--echo # +--echo # MDEV-32984 Update federated table and column privileges +--echo # +connection slave; +create database db1; +create user my@localhost identified by '1qaz2wsx'; +create table db1.t1 ( + f1 int auto_increment primary key, + f2 varchar(50), + f3 varchar(50), + unique (f2) +); +grant insert, select (f1, f2, f3), update (f3) on db1.t1 to my@localhost; + +connection master; +evalp create table tt1 engine=federated connection='mysql://my:1qaz2wsx@localhost:$SLAVE_MYPORT/db1/t1'; +insert into tt1 (f2,f3) values ('test','123'); +select * from tt1; +update tt1 set f3='123456' where f2='test'; + +drop table tt1; + +connection slave; +drop database db1; +drop user my@localhost; + +source include/federated_cleanup.inc; + + diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index f7a8a1db574..13a981d4381 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -7103,7 +7103,7 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability indexed and it cannot have a DEFAULT value). */ m_table->auto_increment_field_not_null= FALSE; - m_table->mark_auto_increment_column(); + m_table->mark_auto_increment_column(true); } return error; diff --git a/sql/table.cc b/sql/table.cc index 5ed8022da22..a5e33052d3f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -7320,7 +7320,7 @@ inline void TABLE::mark_index_columns_for_read(uint index) always set and sometimes read. */ -void TABLE::mark_auto_increment_column() +void TABLE::mark_auto_increment_column(bool is_insert) { DBUG_ASSERT(found_next_number_field); /* @@ -7328,7 +7328,8 @@ void TABLE::mark_auto_increment_column() store() to check overflow of auto_increment values */ bitmap_set_bit(read_set, found_next_number_field->field_index); - bitmap_set_bit(write_set, found_next_number_field->field_index); + if (is_insert) + bitmap_set_bit(write_set, found_next_number_field->field_index); if (s->next_number_keypart) mark_index_columns_for_read(s->next_number_index); file->column_bitmaps_signal(); @@ -7453,7 +7454,7 @@ void TABLE::mark_columns_needed_for_update() else { if (found_next_number_field) - mark_auto_increment_column(); + mark_auto_increment_column(false); } if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) @@ -7527,7 +7528,7 @@ void TABLE::mark_columns_needed_for_insert() triggers->mark_fields_used(TRG_EVENT_INSERT); } if (found_next_number_field) - mark_auto_increment_column(); + mark_auto_increment_column(true); if (default_field) mark_default_fields_for_write(TRUE); /* Mark virtual columns for insert */ diff --git a/sql/table.h b/sql/table.h index 45095a8d137..9d659bb71ed 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1585,7 +1585,7 @@ public: void mark_index_columns_no_reset(uint index, MY_BITMAP *bitmap); void mark_index_columns_for_read(uint index); void restore_column_maps_after_keyread(MY_BITMAP *backup); - void mark_auto_increment_column(void); + void mark_auto_increment_column(bool insert_fl); void mark_columns_needed_for_update(void); void mark_columns_needed_for_delete(void); void mark_columns_needed_for_insert(void); From 761d5c8987f1770767591ea3bf43f4048ffba8c1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 10 Jan 2024 00:56:19 +0100 Subject: [PATCH 014/121] MDEV-33092 Undefined reference to concurrency on Solaris remove thr_setconcurrency() followup for 8bbcaab160c Fix by Rainer Orth --- cmake/os/WindowsCache.cmake | 1 - config.h.cmake | 1 - configure.cmake | 1 - include/my_pthread.h | 6 ------ libmysqld/lib_sql.cc | 2 -- mysys/thr_alarm.c | 1 - mysys/thr_lock.c | 3 --- mysys/thr_timer.c | 1 - sql/mysqld.cc | 2 -- storage/maria/unittest/ma_pagecache_consist.c | 4 ---- storage/maria/unittest/ma_pagecache_rwconsist.c | 4 ---- storage/maria/unittest/ma_pagecache_rwconsist2.c | 4 ---- storage/maria/unittest/ma_pagecache_single.c | 4 ---- storage/maria/unittest/ma_test_loghandler_multithread-t.c | 4 ---- 14 files changed, 38 deletions(-) diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index 4a3b3383393..628b1728747 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -243,7 +243,6 @@ SET(HAVE_TERMCAP_H CACHE INTERNAL "") SET(HAVE_TERMIOS_H CACHE INTERNAL "") SET(HAVE_TERMIO_H CACHE INTERNAL "") SET(HAVE_TERM_H CACHE INTERNAL "") -SET(HAVE_THR_SETCONCURRENCY CACHE INTERNAL "") SET(HAVE_THR_YIELD CACHE INTERNAL "") SET(HAVE_TIME 1 CACHE INTERNAL "") SET(HAVE_TIMES CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index a8154bb18d1..652b95a1ed2 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -231,7 +231,6 @@ #cmakedefine HAVE_STRTOUL 1 #cmakedefine HAVE_STRTOULL 1 #cmakedefine HAVE_TELL 1 -#cmakedefine HAVE_THR_SETCONCURRENCY 1 #cmakedefine HAVE_THR_YIELD 1 #cmakedefine HAVE_TIME 1 #cmakedefine HAVE_TIMES 1 diff --git a/configure.cmake b/configure.cmake index c7266cdef81..fcfce85edb9 100644 --- a/configure.cmake +++ b/configure.cmake @@ -417,7 +417,6 @@ CHECK_FUNCTION_EXISTS (strtoul HAVE_STRTOUL) CHECK_FUNCTION_EXISTS (strtoull HAVE_STRTOULL) CHECK_FUNCTION_EXISTS (strcasecmp HAVE_STRCASECMP) CHECK_FUNCTION_EXISTS (tell HAVE_TELL) -CHECK_FUNCTION_EXISTS (thr_setconcurrency HAVE_THR_SETCONCURRENCY) CHECK_FUNCTION_EXISTS (thr_yield HAVE_THR_YIELD) CHECK_FUNCTION_EXISTS (vasprintf HAVE_VASPRINTF) CHECK_FUNCTION_EXISTS (vsnprintf HAVE_VSNPRINTF) diff --git a/include/my_pthread.h b/include/my_pthread.h index a95e6f77b13..10cc2301ea6 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -148,9 +148,6 @@ int pthread_cancel(pthread_t thread); #ifndef _REENTRANT #define _REENTRANT #endif -#ifdef HAVE_THR_SETCONCURRENCY -#include /* Probably solaris */ -#endif #ifdef HAVE_SCHED_H #include #endif @@ -619,9 +616,6 @@ extern int my_rw_trywrlock(my_rw_lock_t *); #define GETHOSTBYADDR_BUFF_SIZE 2048 -#ifndef HAVE_THR_SETCONCURRENCY -#define thr_setconcurrency(A) pthread_dummy(0) -#endif #if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize) #define pthread_attr_setstacksize(A,B) pthread_dummy(0) #endif diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 8f772ac8122..41eee607d23 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -635,8 +635,6 @@ int init_embedded_server(int argc, char **argv, char **groups) udf_init(); #endif - (void) thr_setconcurrency(concurrency); // 10 by default - if (flush_time && flush_time != ~(ulong) 0L) start_handle_manager(); diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 90429f72823..d2b542ee9b6 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -786,7 +786,6 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("signal thread created")); - thr_setconcurrency(3); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); printf("Main thread: %s\n",my_thread_name()); for (i=0 ; i < 2 ; i++) diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 168ec035e79..c9bc3a2d9fb 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1783,9 +1783,6 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) error,errno); exit(1); } -#endif -#ifdef HAVE_THR_SETCONCURRENCY - (void) thr_setconcurrency(2); #endif for (i=0 ; i < array_elements(lock_counts) ; i++) { diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c index f87c1f75555..d3627fea983 100644 --- a/mysys/thr_timer.c +++ b/mysys/thr_timer.c @@ -533,7 +533,6 @@ static void run_test() mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST); mysql_cond_init(0, &COND_thread_count, NULL); - thr_setconcurrency(3); pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); printf("Main thread: %s\n",my_thread_name()); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b698928c5f7..05545a1f4fb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5490,8 +5490,6 @@ int mysqld_main(int argc, char **argv) SYSVAR_AUTOSIZE(my_thread_stack_size, new_thread_stack_size); } - (void) thr_setconcurrency(concurrency); // 10 by default - select_thread=pthread_self(); select_thread_in_use=1; diff --git a/storage/maria/unittest/ma_pagecache_consist.c b/storage/maria/unittest/ma_pagecache_consist.c index 29fa29ca035..4a9056e66c2 100644 --- a/storage/maria/unittest/ma_pagecache_consist.c +++ b/storage/maria/unittest/ma_pagecache_consist.c @@ -403,10 +403,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, 0)) == 0) { diff --git a/storage/maria/unittest/ma_pagecache_rwconsist.c b/storage/maria/unittest/ma_pagecache_rwconsist.c index a3303eb65a4..c4a2148175d 100644 --- a/storage/maria/unittest/ma_pagecache_rwconsist.c +++ b/storage/maria/unittest/ma_pagecache_rwconsist.c @@ -272,10 +272,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, 0)) == 0) { diff --git a/storage/maria/unittest/ma_pagecache_rwconsist2.c b/storage/maria/unittest/ma_pagecache_rwconsist2.c index 2a0f76b478f..e1a80ac495b 100644 --- a/storage/maria/unittest/ma_pagecache_rwconsist2.c +++ b/storage/maria/unittest/ma_pagecache_rwconsist2.c @@ -268,10 +268,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, 0)) == 0) { diff --git a/storage/maria/unittest/ma_pagecache_single.c b/storage/maria/unittest/ma_pagecache_single.c index b0a259c85a4..a8aecc10a42 100644 --- a/storage/maria/unittest/ma_pagecache_single.c +++ b/storage/maria/unittest/ma_pagecache_single.c @@ -795,10 +795,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, TEST_PAGE_SIZE, 0, MYF(MY_WME))) == 0) { diff --git a/storage/maria/unittest/ma_test_loghandler_multithread-t.c b/storage/maria/unittest/ma_test_loghandler_multithread-t.c index cb4d2bc70ba..e07f8d56e32 100644 --- a/storage/maria/unittest/ma_test_loghandler_multithread-t.c +++ b/storage/maria/unittest/ma_test_loghandler_multithread-t.c @@ -331,10 +331,6 @@ int main(int argc __attribute__((unused)), exit(1); } -#ifdef HAVE_THR_SETCONCURRENCY - thr_setconcurrency(2); -#endif - if (ma_control_file_open(TRUE, TRUE, TRUE)) { fprintf(stderr, "Can't init control file (%d)\n", errno); From 7801c6d22dce546e9661be909dd0302000933f0b Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 15 Dec 2023 17:37:28 +1100 Subject: [PATCH 015/121] MDEV-29002 Spider: remove SPIDER_CONN::loop_check_meraged_last The field is assigned but unused, and it causes heap-use-after-free. --- .../spider/bugfix/r/mdev_29002.result | 34 +++++++++++++++++++ .../spider/bugfix/t/mdev_29002.test | 32 +++++++++++++++++ storage/spider/spd_conn.cc | 6 ---- storage/spider/spd_include.h | 1 - 4 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_29002.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_29002.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29002.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29002.result new file mode 100644 index 00000000000..894f51c5e36 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29002.result @@ -0,0 +1,34 @@ +for master_1 +for child2 +for child3 +SET spider_same_server_link= on; +CREATE SERVER s FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t (a INT); +CREATE TABLE t1_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +CREATE TABLE t2_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +SELECT * FROM t1_spider, t2_spider; +a a +SELECT table_name, index_name, cardinality FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name IN ('t1_spider','t2_spider'); +table_name index_name cardinality +RENAME TABLE t1_spider TO t3_spider; +SELECT * FROM t3_spider; +a +DROP TABLE t3_spider, t2_spider, t; +drop server s; +CREATE TABLE t1 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t3 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +SHOW TABLE STATUS; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary +t1 SPIDER 10 NULL 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL Unable to connect to foreign data source: srv 0 +t2 SPIDER 10 NULL 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL Unable to connect to foreign data source: srv 0 +t3 SPIDER 10 NULL 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL Unable to connect to foreign data source: srv 0 +Warnings: +Warning 1429 Unable to connect to foreign data source: srv +Warning 1429 Unable to connect to foreign data source: srv +Warning 1429 Unable to connect to foreign data source: srv +drop table t1, t2, t3; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29002.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29002.test new file mode 100644 index 00000000000..51620a5a23c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29002.test @@ -0,0 +1,32 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +SET spider_same_server_link= on; +evalp CREATE SERVER s FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +CREATE TABLE t (a INT); +CREATE TABLE t1_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +CREATE TABLE t2_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't'"; +SELECT * FROM t1_spider, t2_spider; +SELECT table_name, index_name, cardinality FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name IN ('t1_spider','t2_spider'); +RENAME TABLE t1_spider TO t3_spider; +SELECT * FROM t3_spider; + +DROP TABLE t3_spider, t2_spider, t; +drop server s; + +# case by roel +CREATE TABLE t1 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t2 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +CREATE TABLE t3 (c INT) ENGINE=Spider COMMENT='WRAPPER "mysql",HOST "srv",TABLE "t"'; +SHOW TABLE STATUS; +drop table t1, t2, t3; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 5ca3bb06fec..9897e495c83 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -1783,13 +1783,7 @@ int spider_conn_queue_and_merge_loop_check( lcptr->flag = SPIDER_LOP_CHK_MERAGED; lcptr->next = NULL; if (!conn->loop_check_meraged_first) - { conn->loop_check_meraged_first = lcptr; - conn->loop_check_meraged_last = lcptr; - } else { - conn->loop_check_meraged_last->next = lcptr; - conn->loop_check_meraged_last = lcptr; - } } DBUG_RETURN(0); diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 59c3a181780..8bf44d094b2 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -940,7 +940,6 @@ typedef struct st_spider_conn SPIDER_CONN_LOOP_CHECK *loop_check_ignored_first; SPIDER_CONN_LOOP_CHECK *loop_check_ignored_last; SPIDER_CONN_LOOP_CHECK *loop_check_meraged_first; - SPIDER_CONN_LOOP_CHECK *loop_check_meraged_last; } SPIDER_CONN; typedef struct st_spider_lgtm_tblhnd_share From 9e9e0b99ade0e6ccd34abc3bc3abaf7bbd5ecf4e Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 19 Dec 2023 12:18:13 +1100 Subject: [PATCH 016/121] MDEV-30170 ha_spider::delete_table() should report table not exist All Spider tables are recorded in the system table mysql.spider_tables. Deleting a spider table removes the corresponding rows from the system table, among other things. This patch makes it so that if spider could not find any record in the system table to delete for a given table, it should correctly report that no such Spider table exists. --- storage/spider/ha_spider.cc | 9 +++++++- .../spider/bugfix/r/mdev_30170.result | 7 ++++++ .../spider/bugfix/t/mdev_30170.test | 8 +++++++ storage/spider/spd_sys_table.cc | 22 ++++++++++++++++++- 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_30170.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_30170.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 08d3fc40f05..5011f86c044 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -11371,7 +11371,10 @@ int ha_spider::create( if ( thd->lex->create_info.or_replace() && (error_num = spider_delete_tables( - table_tables, tmp_share.table_name, &dummy)) + table_tables, tmp_share.table_name, &dummy)) && + /* In this context, no key found in mysql.spider_tables means + the Spider table does not exist */ + error_num != HA_ERR_KEY_NOT_FOUND ) { goto error; } @@ -11842,6 +11845,10 @@ int ha_spider::delete_table( (error_num = spider_delete_tables( table_tables, name, &old_link_count)) ) { + /* In this context, no key found in mysql.spider_tables means + the Spider table does not exist */ + if (error_num == HA_ERR_KEY_NOT_FOUND) + error_num= HA_ERR_NO_SUCH_TABLE; goto error; } spider_close_sys_table(current_thd, table_tables, diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_30170.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_30170.result new file mode 100644 index 00000000000..2183447bfa3 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_30170.result @@ -0,0 +1,7 @@ +install soname 'ha_spider'; +DROP TABLE non_existing_table; +ERROR 42S02: Unknown table 'test.non_existing_table' +create or replace table non_existing_table (c int) engine=Spider; +drop table non_existing_table; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30170.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30170.test new file mode 100644 index 00000000000..690268432d3 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30170.test @@ -0,0 +1,8 @@ +install soname 'ha_spider'; +--error ER_BAD_TABLE_ERROR +DROP TABLE non_existing_table; +# Test that create or replace a non existing spider table work +create or replace table non_existing_table (c int) engine=Spider; +drop table non_existing_table; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index b3a45b73af7..a8549d5467d 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -1865,6 +1865,16 @@ int spider_delete_xa_member( DBUG_RETURN(0); } +/** + Delete a Spider table from mysql.spider_tables. + + @param table The table mysql.spider_tables + @param name The name of the Spider table to delete + @param old_link_count The number of links in the deleted table + + @retval 0 Success + @retval nonzero Failure +*/ int spider_delete_tables( TABLE *table, const char *name, @@ -1880,10 +1890,20 @@ int spider_delete_tables( { spider_store_tables_link_idx(table, roop_count); if ((error_num = spider_check_sys_table(table, table_key))) - break; + { + /* There's a problem with finding the first record for the + spider table, likely because it does not exist. Fail */ + if (roop_count == 0) + DBUG_RETURN(error_num); + /* At least one row has been deleted for the Spider table. + Success */ + else + break; + } else { if ((error_num = spider_delete_sys_table_row(table))) { + /* There's a problem deleting the row. Fail */ DBUG_RETURN(error_num); } } From d277a63c749bd49c9025da4efdd3008d22180dc0 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 28 Nov 2023 14:56:23 +1100 Subject: [PATCH 017/121] MDEV-31101 Re-enable spider/bugfix.mdev_29904 The spider init bug fixes remove any race conditions during spider init. Also remove the add_suppressions in spider/bugfix.mdev_27575 which is a similar issue. --- storage/spider/mysql-test/spider/bugfix/disabled.def | 1 - storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result | 2 -- storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test | 4 ---- 3 files changed, 7 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/disabled.def b/storage/spider/mysql-test/spider/bugfix/disabled.def index 99443c854e5..e19ea07b76b 100644 --- a/storage/spider/mysql-test/spider/bugfix/disabled.def +++ b/storage/spider/mysql-test/spider/bugfix/disabled.def @@ -1,2 +1 @@ wait_timeout : MDEV-26045 -mdev_29904 : MDEV-31101 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result index 4899f191ada..91af2c8f1e0 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27575.result @@ -4,8 +4,6 @@ for master_1 for child2 for child3 -call mtr.add_suppression("\\[ERROR\\] Table 'mysql.spider_table_sts' doesn't exist"); -call mtr.add_suppression("\\[ERROR\\] Server shutdown in progress"); SET GLOBAL default_tmp_storage_engine=spider; # restart SET GLOBAL default_storage_engine=Spider; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test index 6f291c6f690..79a08489bae 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27575.test @@ -7,10 +7,6 @@ --enable_result_log --enable_query_log -# These suppressions are a workaround and should not be needed once -# MDEV-29870 is done. -call mtr.add_suppression("\\[ERROR\\] Table 'mysql.spider_table_sts' doesn't exist"); -call mtr.add_suppression("\\[ERROR\\] Server shutdown in progress"); SET GLOBAL default_tmp_storage_engine=spider; --source include/restart_mysqld.inc From 88c46aba753c0094ea16dc707bb76cc5254806c8 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Thu, 11 Jan 2024 12:32:26 +1100 Subject: [PATCH 018/121] MDEV-32997 Disable spider/bugfix.mdev_27575 until we find a solution The failure described in MDEV-32997 is happening a bit too often and polluting the CI results. --- storage/spider/mysql-test/spider/bugfix/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/spider/mysql-test/spider/bugfix/disabled.def b/storage/spider/mysql-test/spider/bugfix/disabled.def index e19ea07b76b..559feeff4bd 100644 --- a/storage/spider/mysql-test/spider/bugfix/disabled.def +++ b/storage/spider/mysql-test/spider/bugfix/disabled.def @@ -1 +1,2 @@ wait_timeout : MDEV-26045 +mdev_27575 : MDEV-32997 From f807a9f874a8079d95bc71c9f27216e4d952f157 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 11 Jan 2024 11:21:32 +0100 Subject: [PATCH 019/121] MDEV-31523 Using two temporary tables in OPTIMIZE TABLE lead to crash Fixed typo in mysql_admin_table which cused call of close_unused_temporary_table_instances alwas for the first table instead of the current table. Added ASSERT that close_unused_temporary_table_instances should not remove all instances of user created temporary table. --- mysql-test/main/temp_table.result | 16 ++++++++++++++++ mysql-test/main/temp_table.test | 16 ++++++++++++++++ sql/sql_admin.cc | 2 +- sql/temporary_tables.cc | 5 +++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/temp_table.result b/mysql-test/main/temp_table.result index e5bb0d54306..33ea1700474 100644 --- a/mysql-test/main/temp_table.result +++ b/mysql-test/main/temp_table.result @@ -602,3 +602,19 @@ DROP TEMPORARY TABLE t1; # # End of 10.2 tests # +# +# MDEV-31523: Using two temporary tables in OPTIMIZE TABLE lead to crash +# +CREATE TEMPORARY TABLE t1 (c INT) ENGINE=MyISAM; +CREATE TEMPORARY TABLE t2 (c INT) ENGINE=MyISAM; +optimize TABLE t1,t2; +Table Op Msg_type Msg_text +test.t1 optimize status Table is already up to date +test.t2 optimize status Table is already up to date +SHOW TABLES; +Tables_in_test +# in 11.2 and above here should be listed above used temporary tables +DROP TEMPORARY TABLE t1, t2; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/temp_table.test b/mysql-test/main/temp_table.test index 9e639ffce2c..e1e671f5ae9 100644 --- a/mysql-test/main/temp_table.test +++ b/mysql-test/main/temp_table.test @@ -661,3 +661,19 @@ DROP TEMPORARY TABLE t1; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # MDEV-31523: Using two temporary tables in OPTIMIZE TABLE lead to crash +--echo # + +CREATE TEMPORARY TABLE t1 (c INT) ENGINE=MyISAM; +CREATE TEMPORARY TABLE t2 (c INT) ENGINE=MyISAM; +optimize TABLE t1,t2; +SHOW TABLES; +--echo # in 11.2 and above here should be listed above used temporary tables + +DROP TEMPORARY TABLE t1, t2; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 66dfc93f45d..09deef9f590 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -776,7 +776,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (lock_type == TL_WRITE && table->mdl_request.type > MDL_SHARED_WRITE) { if (table->table->s->tmp_table) - thd->close_unused_temporary_table_instances(tables); + thd->close_unused_temporary_table_instances(table); else { if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED)) diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 05e32d78b7f..4ffae3d53bf 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -1577,6 +1577,11 @@ void THD::close_unused_temporary_table_instances(const TABLE_LIST *tl) { /* Note: removing current list element doesn't invalidate iterator. */ share->all_tmp_tables.remove(table); + /* + At least one instance should be left (guaratead by calling this + function for table which is opened and the table is under processing) + */ + DBUG_ASSERT(share->all_tmp_tables.front()); free_temporary_table(table); } } From 9a5f85dcbe12dd9e3228d77834aed8ab53885f20 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Mon, 13 Nov 2023 15:40:13 +0100 Subject: [PATCH 020/121] MDEV-32790: Output result in show create table for mysql_json type should be longtext - We don't test `json` MySQL tables from `std_data` since the error `ER_TABLE_NEEDS_REBUILD ` is invoked. However MDEV-32235 will override this test after merge, but leave it to show behavior and historical changes. - Closes PR #2833 Reviewer: --- .../main/mysql_json_table_recreate.result | 44 +++++++++++++++++++ .../main/mysql_json_table_recreate.test | 36 +++++++++++++++ plugin/type_mysql_json/type.cc | 2 +- 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/mysql_json_table_recreate.result b/mysql-test/main/mysql_json_table_recreate.result index 207dde9d8ad..b2ab19f4fbf 100644 --- a/mysql-test/main/mysql_json_table_recreate.result +++ b/mysql-test/main/mysql_json_table_recreate.result @@ -169,3 +169,47 @@ Total_Number_of_Tests Succesful_Tests String_is_valid_JSON drop table tempty; drop table mysql_json_test; drop table mysql_json_test_big; +# +# MDEV-32790: Output result in show create table +# for mysql_json type should be longtext +# +create table t1(j json); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `j` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`j`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t1; +create table t1(j mysql_json); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `j` mysql_json /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t1; +create table `testjson` ( +`t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL +) ENGINE=InnoDB DEFAULT CH...' at line 2 +create table `testjson` ( +`t` json /* JSON from MySQL 5.7*/ COLLATE utf8mb4_bin NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +show create table testjson; +Table Create Table +testjson CREATE TABLE `testjson` ( + `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`t`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table testjson; +create table `testjson` ( +`t` longtext /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +show create table testjson; +Table Create Table +testjson CREATE TABLE `testjson` ( + `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table testjson; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/mysql_json_table_recreate.test b/mysql-test/main/mysql_json_table_recreate.test index a399b546591..7e9895a1f10 100644 --- a/mysql-test/main/mysql_json_table_recreate.test +++ b/mysql-test/main/mysql_json_table_recreate.test @@ -88,3 +88,39 @@ from mysql_json_test_big; drop table tempty; drop table mysql_json_test; drop table mysql_json_test_big; + +--echo # +--echo # MDEV-32790: Output result in show create table +--echo # for mysql_json type should be longtext +--echo # + +create table t1(j json); +show create table t1; +drop table t1; +create table t1(j mysql_json); +show create table t1; +drop table t1; +# `json` type should not have character set and collation other than utf8mb4_bin +--error ER_PARSE_ERROR +create table `testjson` ( + `t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; + +# By removing character set from `json` field query should work and +# expand to `longtext` with characterset +create table `testjson` ( + `t` json /* JSON from MySQL 5.7*/ COLLATE utf8mb4_bin NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +show create table testjson; +drop table testjson; + +# `longtext` that is alias can have character set +create table `testjson` ( + `t` longtext /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; +show create table testjson; +drop table testjson; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/plugin/type_mysql_json/type.cc b/plugin/type_mysql_json/type.cc index c5168969b67..c915e0312bb 100644 --- a/plugin/type_mysql_json/type.cc +++ b/plugin/type_mysql_json/type.cc @@ -62,7 +62,7 @@ public: bool parse_mysql(String *dest, const char *data, size_t length) const; bool send(Protocol *protocol) { return Field::send(protocol); } void sql_type(String &s) const - { s.set_ascii(STRING_WITH_LEN("json /* MySQL 5.7 */")); } + { s.set_ascii(STRING_WITH_LEN("mysql_json /* JSON from MySQL 5.7 */")); } /* this will make ALTER TABLE to consider it different from built-in field */ Compression_method *compression_method() const { return (Compression_method*)1; } }; From 22f3ebe4bf11acb7b5e854bc4e6b3439af6982f1 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Thu, 11 Jan 2024 15:15:46 +0100 Subject: [PATCH 021/121] MDEV-32235: mysql_json cannot be used on newly created table Closes PR #2839 Reviewer: cvicentiu@mariadb.org --- .../main/mysql_json_table_recreate.result | 18 ++++++++++++------ mysql-test/main/mysql_json_table_recreate.test | 17 +++++++++++++++-- sql/sql_table.cc | 13 +++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/mysql_json_table_recreate.result b/mysql-test/main/mysql_json_table_recreate.result index b2ab19f4fbf..a0c2483d3d9 100644 --- a/mysql-test/main/mysql_json_table_recreate.result +++ b/mysql-test/main/mysql_json_table_recreate.result @@ -181,12 +181,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1(j mysql_json); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `j` mysql_json /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci -drop table t1; +ERROR HY000: Cannot create table `test`.`t1`: Run mariadb-upgrade, to upgrade table with mysql_json type. create table `testjson` ( `t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -211,5 +206,16 @@ testjson CREATE TABLE `testjson` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table testjson; # +# MDEV-32235: mysql_json cannot be used on newly created table +# +CREATE TABLE t(j mysql_json); +ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. +CREATE TABLE IF NOT EXISTS t(j mysql_json); +ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. +CREATE OR REPLACE TABLE t(j mysql_json); +ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. +CREATE TEMPORARY TABLE t(j mysql_json); +ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. +# # End of 10.5 tests # diff --git a/mysql-test/main/mysql_json_table_recreate.test b/mysql-test/main/mysql_json_table_recreate.test index 7e9895a1f10..bf4cac0f909 100644 --- a/mysql-test/main/mysql_json_table_recreate.test +++ b/mysql-test/main/mysql_json_table_recreate.test @@ -97,9 +97,8 @@ drop table mysql_json_test_big; create table t1(j json); show create table t1; drop table t1; +--error ER_CANT_CREATE_TABLE create table t1(j mysql_json); -show create table t1; -drop table t1; # `json` type should not have character set and collation other than utf8mb4_bin --error ER_PARSE_ERROR create table `testjson` ( @@ -121,6 +120,20 @@ create table `testjson` ( show create table testjson; drop table testjson; + +--echo # +--echo # MDEV-32235: mysql_json cannot be used on newly created table +--echo # + +--error ER_CANT_CREATE_TABLE +CREATE TABLE t(j mysql_json); +--error ER_CANT_CREATE_TABLE +CREATE TABLE IF NOT EXISTS t(j mysql_json); +--error ER_CANT_CREATE_TABLE +CREATE OR REPLACE TABLE t(j mysql_json); +--error ER_CANT_CREATE_TABLE +CREATE TEMPORARY TABLE t(j mysql_json); + --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d68bbd1ac4f..8088d3e0d70 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3657,6 +3657,19 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (sql_field->vcol_info) sql_field->flags&= ~NOT_NULL_FLAG; + if (sql_field->real_field_type() == MYSQL_TYPE_BLOB && + thd->lex->sql_command == SQLCOM_CREATE_TABLE) + { + if (!strcmp(sql_field->type_handler()->name().ptr(), "MYSQL_JSON")) + { + my_printf_error(ER_CANT_CREATE_TABLE, + "Cannot create table %`s.%`s: " + "Run mariadb-upgrade, " + "to upgrade table with mysql_json type.", MYF(0), + alter_info->db.str, alter_info->table_name.str); + DBUG_RETURN(TRUE); + } + } /* Initialize length from its original value (number of characters), which was set in the parser. This is necessary if we're From d0c80c211c1fe3370b68be540bb9113028c6746f Mon Sep 17 00:00:00 2001 From: Dave Gosselin Date: Mon, 8 Jan 2024 11:58:29 -0500 Subject: [PATCH 022/121] MDEV-32090 Test for null-safe equals in join This ticket is fixed by MDEV-32555 and this test captures a different use case. --- mysql-test/main/subselect_nulls_innodb.result | 27 ++++++++++++++++ mysql-test/main/subselect_nulls_innodb.test | 32 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 mysql-test/main/subselect_nulls_innodb.result create mode 100644 mysql-test/main/subselect_nulls_innodb.test diff --git a/mysql-test/main/subselect_nulls_innodb.result b/mysql-test/main/subselect_nulls_innodb.result new file mode 100644 index 00000000000..2cab41760b3 --- /dev/null +++ b/mysql-test/main/subselect_nulls_innodb.result @@ -0,0 +1,27 @@ +# +# MDEV-32090 Index does not handle null-safe equals operator correctly in join +# +CREATE TEMPORARY TABLE t1 ( +`id` int(10) unsigned NOT NULL, +`number` int(10) unsigned DEFAULT 0, +`name` varchar(47) DEFAULT NULL, +`street` mediumint(8) unsigned DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `streetNumber` (`street`,`number`,`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +INSERT INTO t1 (id, number, name, street) VALUES (100733476, 14, NULL, 1115569); +SELECT +b1.id +FROM +t1 b1 +INNER JOIN t1 b2 ON ( +b1.street = b2.street +AND b1.number <=> b2.number +AND b1.name <=> b2.name +); +id +100733476 +DROP TABLE t1; +# +# End of 10.11 tests +# diff --git a/mysql-test/main/subselect_nulls_innodb.test b/mysql-test/main/subselect_nulls_innodb.test new file mode 100644 index 00000000000..79d572a2e0e --- /dev/null +++ b/mysql-test/main/subselect_nulls_innodb.test @@ -0,0 +1,32 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-32090 Index does not handle null-safe equals operator correctly in join +--echo # + +CREATE TEMPORARY TABLE t1 ( + `id` int(10) unsigned NOT NULL, + `number` int(10) unsigned DEFAULT 0, + `name` varchar(47) DEFAULT NULL, + `street` mediumint(8) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `streetNumber` (`street`,`number`,`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +INSERT INTO t1 (id, number, name, street) VALUES (100733476, 14, NULL, 1115569); + +SELECT + b1.id +FROM + t1 b1 + INNER JOIN t1 b2 ON ( + b1.street = b2.street + AND b1.number <=> b2.number + AND b1.name <=> b2.name + ); + +DROP TABLE t1; + +--echo # +--echo # End of 10.11 tests +--echo # From 8b5c1d5afa33521d7a5024b58a7b8197e60bfd33 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Fri, 12 Jan 2024 15:20:25 +0100 Subject: [PATCH 023/121] Revert "MDEV-32235: mysql_json cannot be used on newly created table" This reverts commit 22f3ebe4bf11acb7b5e854bc4e6b3439af6982f1. --- .../main/mysql_json_table_recreate.result | 18 ++++++------------ mysql-test/main/mysql_json_table_recreate.test | 17 ++--------------- sql/sql_table.cc | 13 ------------- 3 files changed, 8 insertions(+), 40 deletions(-) diff --git a/mysql-test/main/mysql_json_table_recreate.result b/mysql-test/main/mysql_json_table_recreate.result index a0c2483d3d9..b2ab19f4fbf 100644 --- a/mysql-test/main/mysql_json_table_recreate.result +++ b/mysql-test/main/mysql_json_table_recreate.result @@ -181,7 +181,12 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1(j mysql_json); -ERROR HY000: Cannot create table `test`.`t1`: Run mariadb-upgrade, to upgrade table with mysql_json type. +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `j` mysql_json /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t1; create table `testjson` ( `t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -206,16 +211,5 @@ testjson CREATE TABLE `testjson` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table testjson; # -# MDEV-32235: mysql_json cannot be used on newly created table -# -CREATE TABLE t(j mysql_json); -ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. -CREATE TABLE IF NOT EXISTS t(j mysql_json); -ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. -CREATE OR REPLACE TABLE t(j mysql_json); -ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. -CREATE TEMPORARY TABLE t(j mysql_json); -ERROR HY000: Cannot create table `test`.`t`: Run mariadb-upgrade, to upgrade table with mysql_json type. -# # End of 10.5 tests # diff --git a/mysql-test/main/mysql_json_table_recreate.test b/mysql-test/main/mysql_json_table_recreate.test index bf4cac0f909..7e9895a1f10 100644 --- a/mysql-test/main/mysql_json_table_recreate.test +++ b/mysql-test/main/mysql_json_table_recreate.test @@ -97,8 +97,9 @@ drop table mysql_json_test_big; create table t1(j json); show create table t1; drop table t1; ---error ER_CANT_CREATE_TABLE create table t1(j mysql_json); +show create table t1; +drop table t1; # `json` type should not have character set and collation other than utf8mb4_bin --error ER_PARSE_ERROR create table `testjson` ( @@ -120,20 +121,6 @@ create table `testjson` ( show create table testjson; drop table testjson; - ---echo # ---echo # MDEV-32235: mysql_json cannot be used on newly created table ---echo # - ---error ER_CANT_CREATE_TABLE -CREATE TABLE t(j mysql_json); ---error ER_CANT_CREATE_TABLE -CREATE TABLE IF NOT EXISTS t(j mysql_json); ---error ER_CANT_CREATE_TABLE -CREATE OR REPLACE TABLE t(j mysql_json); ---error ER_CANT_CREATE_TABLE -CREATE TEMPORARY TABLE t(j mysql_json); - --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8088d3e0d70..d68bbd1ac4f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3657,19 +3657,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (sql_field->vcol_info) sql_field->flags&= ~NOT_NULL_FLAG; - if (sql_field->real_field_type() == MYSQL_TYPE_BLOB && - thd->lex->sql_command == SQLCOM_CREATE_TABLE) - { - if (!strcmp(sql_field->type_handler()->name().ptr(), "MYSQL_JSON")) - { - my_printf_error(ER_CANT_CREATE_TABLE, - "Cannot create table %`s.%`s: " - "Run mariadb-upgrade, " - "to upgrade table with mysql_json type.", MYF(0), - alter_info->db.str, alter_info->table_name.str); - DBUG_RETURN(TRUE); - } - } /* Initialize length from its original value (number of characters), which was set in the parser. This is necessary if we're From 8a763c014ede4adad9c84852269b5af61845c0d9 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Fri, 12 Jan 2024 15:39:38 +0100 Subject: [PATCH 024/121] MDEV-32235: mysql_json cannot be used on newly created table - Closes PR #2839 - Usage of `Column_definition_fix_attributes()` suggested by Alexandar Barkov - thanks bar, that is better than hook in server code (reverted 22f3ebe4bf11) - This method is called after parsing the data type: * in `CREATE/ALTER TABLE` * in SP: return data type, parameter data type, variable data type - We want to disallow all these use cases of MYSQL_JSON. - Reviewer: bar@mariadb.com cvicentiu@mariadb.org --- .../main/mysql_json_table_recreate.result | 38 ++++++++++++++--- .../main/mysql_json_table_recreate.test | 41 ++++++++++++++++++- plugin/type_mysql_json/type.cc | 5 +++ 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/mysql_json_table_recreate.result b/mysql-test/main/mysql_json_table_recreate.result index b2ab19f4fbf..a61377fe21d 100644 --- a/mysql-test/main/mysql_json_table_recreate.result +++ b/mysql-test/main/mysql_json_table_recreate.result @@ -30,6 +30,12 @@ show create table mysql_json_test; ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it! select * from mysql_json_test; ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it! +CREATE TABLE t2 AS SELECT * FROM mysql_json_test; +ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it! +CREATE TABLE t2 (a mysql_json /*new column*/) AS SELECT * FROM mysql_json_test; +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +CREATE TABLE t2 (actual mysql_json /*existing column*/) AS SELECT * FROM mysql_json_test; +ERROR HY000: 'MYSQL_JSON' is not allowed in this context LOCK TABLES mysql_json_test WRITE; ERROR HY000: Table rebuild required. Please do "ALTER TABLE `test.mysql_json_test` FORCE" or dump/reload to fix it! alter table mysql_json_test force; @@ -181,12 +187,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1(j mysql_json); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `j` mysql_json /* JSON from MySQL 5.7 */ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci -drop table t1; +ERROR HY000: 'MYSQL_JSON' is not allowed in this context create table `testjson` ( `t` json /* JSON from MySQL 5.7*/ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -211,5 +212,30 @@ testjson CREATE TABLE `testjson` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table testjson; # +# MDEV-32235: mysql_json cannot be used on newly created table +# +CREATE TABLE t(j mysql_json); +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +CREATE TABLE IF NOT EXISTS t(j mysql_json); +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +CREATE OR REPLACE TABLE t(j mysql_json); +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +CREATE TEMPORARY TABLE t(j mysql_json); +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +CREATE TABLE t1 (a TEXT); +ALTER TABLE t1 MODIFY a mysql_json; +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +DROP TABLE t1; +CREATE FUNCTION f1() RETURNS mysql_json RETURN NULL; +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +CREATE FUNCTION f1(a mysql_json) RETURNS INT RETURN 0; +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +CREATE PROCEDURE p1() +BEGIN +DECLARE a mysql_json; +END; +$$ +ERROR HY000: 'MYSQL_JSON' is not allowed in this context +# # End of 10.5 tests # diff --git a/mysql-test/main/mysql_json_table_recreate.test b/mysql-test/main/mysql_json_table_recreate.test index 7e9895a1f10..a6f1d3194ae 100644 --- a/mysql-test/main/mysql_json_table_recreate.test +++ b/mysql-test/main/mysql_json_table_recreate.test @@ -51,6 +51,13 @@ show create table mysql_json_test; --error ER_TABLE_NEEDS_REBUILD select * from mysql_json_test; +--error ER_TABLE_NEEDS_REBUILD +CREATE TABLE t2 AS SELECT * FROM mysql_json_test; +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE TABLE t2 (a mysql_json /*new column*/) AS SELECT * FROM mysql_json_test; +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE TABLE t2 (actual mysql_json /*existing column*/) AS SELECT * FROM mysql_json_test; + --error ER_TABLE_NEEDS_REBUILD LOCK TABLES mysql_json_test WRITE; @@ -97,9 +104,8 @@ drop table mysql_json_test_big; create table t1(j json); show create table t1; drop table t1; +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT create table t1(j mysql_json); -show create table t1; -drop table t1; # `json` type should not have character set and collation other than utf8mb4_bin --error ER_PARSE_ERROR create table `testjson` ( @@ -121,6 +127,37 @@ create table `testjson` ( show create table testjson; drop table testjson; +--echo # +--echo # MDEV-32235: mysql_json cannot be used on newly created table +--echo # + +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE TABLE t(j mysql_json); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE TABLE IF NOT EXISTS t(j mysql_json); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE OR REPLACE TABLE t(j mysql_json); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE TEMPORARY TABLE t(j mysql_json); + +CREATE TABLE t1 (a TEXT); +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +ALTER TABLE t1 MODIFY a mysql_json; +DROP TABLE t1; + +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE FUNCTION f1() RETURNS mysql_json RETURN NULL; +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE FUNCTION f1(a mysql_json) RETURNS INT RETURN 0; +DELIMITER $$; +--error ER_NOT_ALLOWED_IN_THIS_CONTEXT +CREATE PROCEDURE p1() +BEGIN + DECLARE a mysql_json; +END; +$$ +DELIMITER ;$$ + --echo # --echo # End of 10.5 tests --echo # diff --git a/plugin/type_mysql_json/type.cc b/plugin/type_mysql_json/type.cc index c915e0312bb..f84f76381a0 100644 --- a/plugin/type_mysql_json/type.cc +++ b/plugin/type_mysql_json/type.cc @@ -37,6 +37,11 @@ public: Field *make_table_field(MEM_ROOT *, const LEX_CSTRING *, const Record_addr &, const Type_all_attributes &, TABLE_SHARE *) const override; + bool Column_definition_fix_attributes(Column_definition *c) const override + { + my_error(ER_NOT_ALLOWED_IN_THIS_CONTEXT, MYF(0), "MYSQL_JSON"); + return true; + } void Column_definition_reuse_fix_attributes(THD *thd, Column_definition *def, const Field *field) const override; From 5b0a4159ef1717545ccd37c08db0cba0eef00e5a Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 5 Jan 2024 13:44:49 +0100 Subject: [PATCH 025/121] Fix test failures on s390x in test following main.column_compression_rpl The problem is the test is skipped after sourcing include/master-slave.inc. This leaves the slave threads running after the test is skipped, causing a following test to fail during rpl setup. Also rename have_normal_bzip.inc to the more appropriate _zlib. Signed-off-by: Kristian Nielsen --- .../include/{have_normal_bzip.inc => have_normal_zlib.inc} | 4 ++-- mysql-test/main/column_compression.test | 2 +- mysql-test/main/column_compression_rpl.test | 2 +- mysql-test/main/func_compress.test | 2 +- mysql-test/main/mysqlbinlog_row_compressed.test | 2 +- mysql-test/main/mysqlbinlog_stmt_compressed.test | 2 +- mysql-test/suite/compat/oracle/t/column_compression.test | 2 +- mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) rename mysql-test/include/{have_normal_bzip.inc => have_normal_zlib.inc} (67%) diff --git a/mysql-test/include/have_normal_bzip.inc b/mysql-test/include/have_normal_zlib.inc similarity index 67% rename from mysql-test/include/have_normal_bzip.inc rename to mysql-test/include/have_normal_zlib.inc index 36c06274398..a4531e687bc 100644 --- a/mysql-test/include/have_normal_bzip.inc +++ b/mysql-test/include/have_normal_zlib.inc @@ -1,9 +1,9 @@ --source include/have_compress.inc -# Test that the system is using the default/standard bzip library. +# Test that the system is using the default/standard zlib library. # If not, we have to skip the test as the compression lengths displayed # in the test will not match the results from used compression library. if (`select length(COMPRESS(space(5000))) != 33`) { - skip Test skipped as standard bzip is needed; + skip Test skipped as standard zlib is needed; } diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test index c628e8f9cca..de59cf5c7c8 100644 --- a/mysql-test/main/column_compression.test +++ b/mysql-test/main/column_compression.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc --source include/have_csv.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc let $MYSQLD_DATADIR= `select @@datadir`; diff --git a/mysql-test/main/column_compression_rpl.test b/mysql-test/main/column_compression_rpl.test index df8e889016b..18992f33f3c 100644 --- a/mysql-test/main/column_compression_rpl.test +++ b/mysql-test/main/column_compression_rpl.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc +--source include/have_normal_zlib.inc --source include/master-slave.inc ---source include/have_normal_bzip.inc --let $engine_type= myisam --let $engine_type2= innodb diff --git a/mysql-test/main/func_compress.test b/mysql-test/main/func_compress.test index 221dddd59f5..d18af140ed3 100644 --- a/mysql-test/main/func_compress.test +++ b/mysql-test/main/func_compress.test @@ -1,5 +1,5 @@ -- source include/have_compress.inc --- source include/have_normal_bzip.inc +-- source include/have_normal_zlib.inc # # Test for compress and uncompress functions: # diff --git a/mysql-test/main/mysqlbinlog_row_compressed.test b/mysql-test/main/mysqlbinlog_row_compressed.test index f2806861830..f493c4db2cd 100644 --- a/mysql-test/main/mysqlbinlog_row_compressed.test +++ b/mysql-test/main/mysqlbinlog_row_compressed.test @@ -4,7 +4,7 @@ --source include/have_log_bin.inc --source include/have_binlog_format_row.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc # # diff --git a/mysql-test/main/mysqlbinlog_stmt_compressed.test b/mysql-test/main/mysqlbinlog_stmt_compressed.test index 400f21f5ab9..1f1591e7a00 100644 --- a/mysql-test/main/mysqlbinlog_stmt_compressed.test +++ b/mysql-test/main/mysqlbinlog_stmt_compressed.test @@ -4,7 +4,7 @@ --source include/have_log_bin.inc --source include/have_binlog_format_statement.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc # # # mysqlbinlog: compressed query event diff --git a/mysql-test/suite/compat/oracle/t/column_compression.test b/mysql-test/suite/compat/oracle/t/column_compression.test index 01d4977ba96..e8d55000bc6 100644 --- a/mysql-test/suite/compat/oracle/t/column_compression.test +++ b/mysql-test/suite/compat/oracle/t/column_compression.test @@ -1,6 +1,6 @@ --source include/have_innodb.inc --source include/have_csv.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc SET sql_mode=ORACLE; diff --git a/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test b/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test index dab9bcfa864..24029a48aa4 100644 --- a/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test +++ b/mysql-test/suite/innodb/t/row_size_error_log_warnings_3.test @@ -1,7 +1,7 @@ --source include/have_innodb.inc --source include/have_sequence.inc --source include/innodb_page_size_small.inc ---source include/have_normal_bzip.inc +--source include/have_normal_zlib.inc call mtr.add_suppression("InnoDB: Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size (.*) for a record on index leaf page."); From 48e4962c44fa5cbdafb6d1ed9564f308a57eeedc Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Thu, 6 Jul 2023 11:55:40 +0700 Subject: [PATCH 026/121] MDEV-29298 INSERT ... SELECT Does not produce an optimizer trace Add INSERT ... SELECT to the list of commands that can be traced Approved by Sergei Petrunia (sergey@mariadb.com) --- mysql-test/main/opt_trace.result | 12 ++++++++++++ mysql-test/main/opt_trace.test | 14 ++++++++++++++ sql/opt_trace.cc | 3 ++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index 5766b8ead42..66f081c6590 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -9231,5 +9231,17 @@ json_detailed(json_extract(trace, '$**.in_to_subquery_conversion')) ] set in_predicate_conversion_threshold=@tmp; drop table t0; +# +# MDEV-29298: INSERT ... SELECT Does not produce an optimizer trace +# +create table t1 (a int, b int); +create table t2 (a int, b int); +insert into t1 values (1,1), (2,2), (3,3), (4,4), (5,5); +set optimizer_trace=1; +insert into t2 select * from t1 where a<= b and a>4; +select QUERY, LENGTH(trace)>1 from information_schema.optimizer_trace; +QUERY LENGTH(trace)>1 +insert into t2 select * from t1 where a<= b and a>4 1 +drop table t1, t2; # End of 10.5 tests set optimizer_trace='enabled=off'; diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index 43539fc764b..e7851fc62c5 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -861,5 +861,19 @@ set in_predicate_conversion_threshold=@tmp; drop table t0; --enable_view_protocol +--echo # +--echo # MDEV-29298: INSERT ... SELECT Does not produce an optimizer trace +--echo # +create table t1 (a int, b int); +create table t2 (a int, b int); +insert into t1 values (1,1), (2,2), (3,3), (4,4), (5,5); +set optimizer_trace=1; + +insert into t2 select * from t1 where a<= b and a>4; + +select QUERY, LENGTH(trace)>1 from information_schema.optimizer_trace; + +drop table t1, t2; + --echo # End of 10.5 tests set optimizer_trace='enabled=off'; diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc index ddec6d5ed2d..4bd54549532 100644 --- a/sql/opt_trace.cc +++ b/sql/opt_trace.cc @@ -103,7 +103,8 @@ inline bool sql_command_can_be_traced(enum enum_sql_command sql_command) sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_DELETE || sql_command == SQLCOM_DELETE_MULTI || - sql_command == SQLCOM_UPDATE_MULTI; + sql_command == SQLCOM_UPDATE_MULTI || + sql_command == SQLCOM_INSERT_SELECT; } void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex, From 82f27ea5a49798d5d89479db8715faa71f2a87ab Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Thu, 11 Jan 2024 12:54:16 +0100 Subject: [PATCH 027/121] MDEV-33187: Make mariadb-hotcopy compatible with DBI:MariaDB --- scripts/mysqlhotcopy.sh | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 44abcfec055..ebf82e46e03 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -189,21 +189,38 @@ $opt{quiet} = 0 if $opt{debug}; $opt{allowold} = 1 if $opt{keepold}; # --- connect to the database --- +## Socket takes precedence. my $dsn; -$dsn = ";host=" . (defined($opt{host}) ? $opt{host} : "localhost"); -$dsn .= ";port=$opt{port}" if $opt{port}; -$dsn .= ";mariadb_socket=$opt{socket}" if $opt{socket}; +my $prefix= 'mysql'; + +if (eval {DBI->install_driver("MariaDB")}) { + $dsn ="DBI:MariaDB:;"; + $prefix= 'mariadb'; +} +else { + $dsn = "DBI:mysql:;"; +} + +if ($opt{socket} and -S $opt{socket}) +{ + $dsn .= "${prefix}_socket=$opt{socket}"; +} +else +{ + $dsn .= "host=" . $opt{host}; + if ($opt{host} ne "localhost") + { + $dsn .= ";port=". $opt{port}; + } +} + +$dsn .= ";mariadb_read_default_group=mysqlhotcopy"; # use mariadb_read_default_group=mysqlhotcopy so that [client] and # [mysqlhotcopy] groups will be read from standard options files. - -my $dbh = DBI->connect("DBI:MariaDB:$dsn;mariadb_read_default_group=mysqlhotcopy", - $opt{user}, $opt{password}, -{ - RaiseError => 1, - PrintError => 0, - AutoCommit => 1, -}); +# make the connection to MariaDB +my $dbh= DBI->connect($dsn, $opt{user}, $opt{password}, { RaiseError => 1, PrintError => 0}) || + die("Can't make a connection to the MariaDB server.\n The error: $DBI::errstr"); # --- check that checkpoint table exists if specified --- if ( $opt{checkpoint} ) { From 7702e481df4a4ccce84558dbebccbc5a2fc64fd1 Mon Sep 17 00:00:00 2001 From: Paul Szabo Date: Fri, 12 Jan 2024 16:02:02 +0100 Subject: [PATCH 028/121] MDEV-30259: mariadb-hotcopy fails for performance_schema Signed-off-by: Paul Szabo psz@maths.usyd.edu.au www.maths.usyd.edu.au/u/psz School of Mathematics and Statistics University of Sydney Australia --- scripts/mysqlhotcopy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index ebf82e46e03..78399ac3599 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -288,6 +288,7 @@ if ( defined $opt{regexp} ) { $sth_dbs->execute; while ( my ($db_name) = $sth_dbs->fetchrow_array ) { next if $db_name =~ m/^information_schema$/i; + next if $db_name =~ m/^performance_schema$/i; push @db_desc, { 'src' => $db_name, 't_regex' => $t_regex } if ( $db_name =~ m/$opt{regexp}/o ); } } From 78ea9ee4f26d7927cfcadb482a0031e2e40c7684 Mon Sep 17 00:00:00 2001 From: Paul Szabo Date: Fri, 12 Jan 2024 16:03:41 +0100 Subject: [PATCH 029/121] MDEV-33187: mariadb-hotcopy fails for sys Signed-off-by: Paul Szabo psz@maths.usyd.edu.au www.maths.usyd.edu.au/u/psz School of Mathematics and Statistics University of Sydney Australia --- scripts/mysqlhotcopy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 78399ac3599..d0821e663c4 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -289,6 +289,7 @@ if ( defined $opt{regexp} ) { while ( my ($db_name) = $sth_dbs->fetchrow_array ) { next if $db_name =~ m/^information_schema$/i; next if $db_name =~ m/^performance_schema$/i; + next if $db_name =~ m/^sys$/i; push @db_desc, { 'src' => $db_name, 't_regex' => $t_regex } if ( $db_name =~ m/$opt{regexp}/o ); } } From ee30491e508e6c8c19c899f713662ec2e5042aaa Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Wed, 15 Nov 2023 11:09:26 +0200 Subject: [PATCH 030/121] MDEV-32111: Debian Sid/Trixie will not have libncurses 5 anymore Upstream Debian Sid which will become Debian Trixie (13) have dropped NCurses version 5 and changed dev package name just libncurses-dev --- debian/control | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 2bbd71d2ac9..eb6a5cba16c 100644 --- a/debian/control +++ b/debian/control @@ -26,8 +26,7 @@ Build-Depends: bison, libjudy-dev, libkrb5-dev, liblz4-dev, - libncurses5-dev (>= 5.0-6~), - libncurses5-dev:native (>= 5.0-6~), + libncurses-dev, libnuma-dev [linux-any], libpam0g-dev, libpcre2-dev, From 653cb195d30bca678b5b175157f0f34206c3761d Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 15 Jan 2024 13:01:22 +0530 Subject: [PATCH 031/121] MDEV-26740 Inplace alter rebuild increases file size PageBulk::init(): Unnecessary reserves the extent before allocating a page for bulk insert. btr_page_alloc() capable of handing the extending of tablespace. --- .../suite/innodb_zip/r/innochecksum_3.result | 2 -- storage/innobase/btr/btr0bulk.cc | 17 ++++------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/mysql-test/suite/innodb_zip/r/innochecksum_3.result b/mysql-test/suite/innodb_zip/r/innochecksum_3.result index 7de90721d64..89830fbbf62 100644 --- a/mysql-test/suite/innodb_zip/r/innochecksum_3.result +++ b/mysql-test/suite/innodb_zip/r/innochecksum_3.result @@ -173,7 +173,6 @@ Filename::tab#.ibd #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - -#::# | Freshly allocated page | - # Variables used by page type dump for ibdata1 Variables (--variable-name=value) @@ -208,7 +207,6 @@ Filename::tab#.ibd #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - #::# | Index page | index id=#, page level=#, No. of records=#, garbage=#, - -#::# | Freshly allocated page | - [6]: check the valid lower bound values for option # allow-mismatches,page,start-page,end-page [9]: check the both short and long options "page" and "start-page" when diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index f7afc575ed5..a39a96b4b04 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -70,24 +70,15 @@ PageBulk::init() alloc_mtr.start(); m_index->set_modified(alloc_mtr); - ulint n_reserved; - bool success; - success = fsp_reserve_free_extents(&n_reserved, - m_index->table->space, - 1, FSP_NORMAL, &alloc_mtr); - if (!success) { - alloc_mtr.commit(); - m_mtr.commit(); - return(DB_OUT_OF_FILE_SPACE); - } - /* Allocate a new page. */ new_block = btr_page_alloc(m_index, 0, FSP_UP, m_level, &alloc_mtr, &m_mtr); - m_index->table->space->release_free_extents(n_reserved); - alloc_mtr.commit(); + if (!new_block) { + m_mtr.commit(); + return DB_OUT_OF_FILE_SPACE; + } new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); From caad34df549b91b654c69bf3b5644277be783d31 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 15 Jan 2024 14:08:27 +0530 Subject: [PATCH 032/121] MDEV-32968 InnoDB fails to restore tablespace first page from doublewrite buffer when page is empty - InnoDB fails to find the space id from the page0 of the tablespace. In that case, InnoDB can use doublewrite buffer to recover the page0 and write into the file. - buf_dblwr_t::init_or_load_pages(): Loads only the pages which are valid.(page lsn >= checkpoint). To do that, InnoDB has to open the redo log before system tablespace, read the latest checkpoint information. recv_dblwr_t::find_first_page(): 1) Iterate the doublewrite buffer pages and find the 0th page 2) Read the tablespace flags, space id from the 0th page. 3) Read the 1st, 2nd and 3rd page from tablespace file and compare the space id with the space id which is stored in doublewrite buffer. 4) If it matches then we can write into the file. 5) Return space which matches the pages from the file. SysTablespace::read_lsn_and_check_flags(): Remove the retry logic for validating the first page. After restoring the first page from doublewrite buffer, assign tablespace flags by reading the first page. recv_recovery_read_max_checkpoint(): Reads the maximum checkpoint information from log file recv_recovery_from_checkpoint_start(): Avoid reading the checkpoint header information from log file Datafile::validate_first_page(): Throw error in case of first page validation fails. --- mysql-test/suite/innodb/r/doublewrite.result | 25 +++- .../suite/innodb/r/log_file_name.result | 7 +- mysql-test/suite/innodb/t/doublewrite.test | 38 ++++- .../suite/innodb/t/doublewrite_debug.test | 1 + mysql-test/suite/innodb/t/log_file_name.test | 9 +- storage/innobase/buf/buf0dblwr.cc | 11 +- storage/innobase/fsp/fsp0file.cc | 21 ++- storage/innobase/fsp/fsp0sysspace.cc | 17 +-- storage/innobase/include/buf0dblwr.h | 3 +- storage/innobase/include/log0recv.h | 18 ++- storage/innobase/log/log0recv.cc | 125 ++++++++++++---- storage/innobase/srv/srv0start.cc | 141 +++++++++--------- 12 files changed, 278 insertions(+), 138 deletions(-) diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result index 7763aa99322..ceb01ac4807 100644 --- a/mysql-test/suite/innodb/r/doublewrite.result +++ b/mysql-test/suite/innodb/r/doublewrite.result @@ -1,7 +1,7 @@ # # MDEV-32242 innodb.doublewrite test case always is skipped # -create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t1 (f1 int primary key, f2 blob) stats_persistent=0, engine=innodb; start transaction; insert into t1 values(1, repeat('#',12)); insert into t1 values(2, repeat('+',12)); @@ -19,6 +19,7 @@ XA PREPARE 'x'; disconnect dml; connection default; flush table t1 for export; +# Kill the server # restart FOUND 1 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err FOUND 1 /InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page number=3\]/ in mysqld.1.err @@ -33,5 +34,27 @@ f1 f2 3 //////////// 4 ------------ 5 ............ +connect dml,localhost,root,,; +XA START 'x'; +insert into t1 values (6, repeat('%', @@innodb_page_size/2)); +XA END 'x'; +XA PREPARE 'x'; +disconnect dml; +connection default; +flush table t1 for export; +# Kill the server +# restart +FOUND 2 /InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile/ in mysqld.1.err +XA ROLLBACK 'x'; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +select f1, f2 from t1; +f1 f2 +1 ############ +2 ++++++++++++ +3 //////////// +4 ------------ +5 ............ drop table t1; # End of 10.5 tests diff --git a/mysql-test/suite/innodb/r/log_file_name.result b/mysql-test/suite/innodb/r/log_file_name.result index 42b988ed3ca..3d48a24d217 100644 --- a/mysql-test/suite/innodb/r/log_file_name.result +++ b/mysql-test/suite/innodb/r/log_file_name.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); SET GLOBAL innodb_file_per_table=ON; FLUSH TABLES; CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; @@ -89,7 +90,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /\[ERROR\] InnoDB: Datafile .*u1.*\. Cannot determine the space ID from the first 64 pages/ in mysqld.1.err NOT FOUND /\[Note\] InnoDB: Cannot read first page of .*u2.ibd/ in mysqld.1.err # Fault 7: Missing or wrong data file and innodb_force_recovery @@ -98,11 +99,11 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace/ in mysqld.1.err FOUND 1 /\[ERROR\] InnoDB: Cannot replay rename of tablespace \d+ from '.*u4.ibd' to '.*u6.ibd' because the target file exists/ in mysqld.1.err # restart: --innodb-force-recovery=1 -FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace/ in mysqld.1.err FOUND 1 /\[Warning\] InnoDB: Tablespace \d+ was not found at .*u[1-5].ibd, and innodb_force_recovery was set. All redo log for this tablespace will be ignored!/ in mysqld.1.err # restart diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 89e6577b434..541e4d23a19 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -17,6 +17,7 @@ call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile"); call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: "); call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd"); call mtr.add_suppression("\\[Warning\\] Found 1 prepared XA transactions"); +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); --enable_query_log let INNODB_PAGE_SIZE=`select @@innodb_page_size`; @@ -24,7 +25,7 @@ let MYSQLD_DATADIR=`select @@datadir`; let ALGO=`select @@innodb_checksum_algorithm`; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; -create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t1 (f1 int primary key, f2 blob) stats_persistent=0, engine=innodb; start transaction; insert into t1 values(1, repeat('#',12)); @@ -38,7 +39,7 @@ commit work; SET GLOBAL innodb_fast_shutdown = 0; let $shutdown_timeout=; --source include/restart_mysqld.inc - +--source ../include/no_checkpoint_start.inc connect (dml,localhost,root,,); XA START 'x'; insert into t1 values (6, repeat('%', @@innodb_page_size/2)); @@ -50,8 +51,8 @@ connection default; flush table t1 for export; let $restart_parameters=; -let $shutdown_timeout=0; ---source include/shutdown_mysqld.inc +--let CLEANUP_IF_CHECKPOINT=drop table t1, unexpected_checkpoint; +--source ../include/no_checkpoint_end.inc perl; use IO::Handle; @@ -119,6 +120,35 @@ let SEARCH_PATTERN=InnoDB: Recovered page \[page id: space=[1-9][0-9]*, page num XA ROLLBACK 'x'; check table t1; select f1, f2 from t1; + +--source ../include/no_checkpoint_start.inc +connect (dml,localhost,root,,); +XA START 'x'; +insert into t1 values (6, repeat('%', @@innodb_page_size/2)); +XA END 'x'; +XA PREPARE 'x'; +disconnect dml; +connection default; + +flush table t1 for export; + +let $restart_parameters=; +--source ../include/no_checkpoint_end.inc + +# Zero out the first page in file and try to recover from dblwr +perl; +use IO::Handle; +open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/t1.ibd") or die; +syswrite(FILE, chr(0) x $ENV{INNODB_PAGE_SIZE}); +close FILE; +EOF + +--source include/start_mysqld.inc +let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=[1-9][0-9]*, page number=0\] of datafile; +--source include/search_pattern_in_file.inc +XA ROLLBACK 'x'; +check table t1; +select f1, f2 from t1; drop table t1; --echo # End of 10.5 tests diff --git a/mysql-test/suite/innodb/t/doublewrite_debug.test b/mysql-test/suite/innodb/t/doublewrite_debug.test index 1bff8b4e07f..3d96a74e698 100644 --- a/mysql-test/suite/innodb/t/doublewrite_debug.test +++ b/mysql-test/suite/innodb/t/doublewrite_debug.test @@ -17,6 +17,7 @@ call mtr.add_suppression("Plugin 'InnoDB' (init function returned error|registra call mtr.add_suppression("InnoDB: A bad Space ID was found in datafile"); call mtr.add_suppression("InnoDB: Checksum mismatch in datafile: "); call mtr.add_suppression("InnoDB: Inconsistent tablespace ID in .*t1\\.ibd"); +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); --enable_query_log let INNODB_PAGE_SIZE=`select @@innodb_page_size`; diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index 11eca0a7a12..494d256cd11 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -7,6 +7,8 @@ # Embedded server does not support crashing --source include/not_embedded.inc +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile:"); + SET GLOBAL innodb_file_per_table=ON; FLUSH TABLES; @@ -172,6 +174,7 @@ call mtr.add_suppression("InnoDB: Table test/u[123] in the InnoDB data dictionar call mtr.add_suppression("InnoDB: Cannot replay rename of tablespace.*"); call mtr.add_suppression("InnoDB: Attempted to open a previously opened tablespace"); call mtr.add_suppression("InnoDB: Recovery cannot access file"); +call mtr.add_suppression("InnoDB: Cannot read first page in datafile:"); FLUSH TABLES; --enable_query_log @@ -215,7 +218,7 @@ EOF --source include/start_mysqld.inc eval $check_no_innodb; -let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= \[ERROR\] InnoDB: Datafile .*u1.*\. Cannot determine the space ID from the first 64 pages; @@ -240,7 +243,7 @@ let SEARCH_PATTERN= \[Note\] InnoDB: Cannot read first page of .*u2.ibd; --source include/start_mysqld.inc eval $check_no_innodb; -let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; @@ -253,7 +256,7 @@ let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot replay rename of tablespace \d+ fro --source include/restart_mysqld.inc -let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 57ec3553b8d..d5c954dff89 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -324,11 +324,14 @@ func_exit: os_file_flush(file); } else - for (ulint i= 0; i < size * 2; i++, page += srv_page_size) - if (mach_read_from_8(my_assume_aligned<8>(page + FIL_PAGE_LSN))) - /* Each valid page header must contain a nonzero FIL_PAGE_LSN field. */ + { + alignas(8) char checkpoint[8]; + mach_write_to_8(checkpoint, log_sys.next_checkpoint_lsn); + for (auto i= size * 2; i--; page += srv_page_size) + if (memcmp_aligned<8>(page + FIL_PAGE_LSN, checkpoint, 8) >= 0) + /* Valid pages are not older than the log checkpoint. */ recv_sys.dblwr.add(page); - + } err= DB_SUCCESS; goto func_exit; } diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index f0ead3b80a3..653c848953a 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -475,9 +475,16 @@ Datafile::validate_for_recovery() err = find_space_id(); if (err != DB_SUCCESS || m_space_id == 0) { - ib::error() << "Datafile '" << m_filepath << "' is" - " corrupted. Cannot determine the space ID from" - " the first 64 pages."; + + m_space_id = recv_sys.dblwr.find_first_page( + m_filepath, m_handle); + + if (m_space_id) goto free_first_page; + + sql_print_error( + "InnoDB: Datafile '%s' is corrupted." + " Cannot determine the space ID from" + " the first 64 pages.", m_filepath); return(err); } @@ -485,7 +492,7 @@ Datafile::validate_for_recovery() m_space_id, m_filepath, m_handle)) { return(DB_CORRUPTION); } - +free_first_page: /* Free the previously read first page and then re-validate. */ free_first_page(); err = validate_first_page(0); @@ -531,9 +538,9 @@ Datafile::validate_first_page(lsn_t* flush_lsn) if (error_txt != NULL) { err_exit: - ib::info() << error_txt << " in datafile: " << m_filepath - << ", Space ID:" << m_space_id << ", Flags: " - << m_flags; + sql_print_error("InnoDB: %s in datafile: %s, Space ID: %zu, " + "Flags: %zu", error_txt, m_filepath, + m_space_id, m_flags); m_is_valid = false; free_first_page(); return(DB_CORRUPTION); diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index a7bb417c502..eb6e8d1166e 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -574,7 +574,7 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn) } err = it->read_first_page( - m_ignore_read_only ? false : srv_read_only_mode); + m_ignore_read_only && srv_read_only_mode); if (err != DB_SUCCESS) { return(err); @@ -588,20 +588,17 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn) /* Check the contents of the first page of the first datafile. */ - for (int retry = 0; retry < 2; ++retry) { + err = it->validate_first_page(flushed_lsn); - err = it->validate_first_page(flushed_lsn); - - if (err != DB_SUCCESS - && (retry == 1 - || recv_sys.dblwr.restore_first_page( + if (err != DB_SUCCESS) { + if (recv_sys.dblwr.restore_first_page( it->m_space_id, it->m_filepath, - it->handle()))) { - + it->handle())) { it->close(); - return(err); } + err = it->read_first_page( + m_ignore_read_only && srv_read_only_mode); } /* Make sure the tablespace space ID matches the diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h index f82baeec89a..99a41d069ef 100644 --- a/storage/innobase/include/buf0dblwr.h +++ b/storage/innobase/include/buf0dblwr.h @@ -103,7 +103,8 @@ public: If we are upgrading from a version before MySQL 4.1, then this function performs the necessary update operations to support innodb_file_per_table. If we are in a crash recovery, this function - loads the pages from double write buffer into memory. + loads the pages from double write buffer which are not older than + the checkpoint into memory. @param file File handle @param path Path name of file @return DB_SUCCESS or error code */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 34211392ba3..aca9f994acb 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -49,6 +49,11 @@ recv_find_max_checkpoint(ulint* max_field) ATTRIBUTE_COLD void recv_recover_page(fil_space_t* space, buf_page_t* bpage) MY_ATTRIBUTE((nonnull)); +/** Read the latest checkpoint information from log file +and store it in log_sys.next_checkpoint and recv_sys.mlog_checkpoint_lsn +@return error code or DB_SUCCESS */ +dberr_t recv_recovery_read_max_checkpoint(); + /** Start recovering from a redo log checkpoint. @param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN of first system tablespace page @@ -141,7 +146,18 @@ struct recv_dblwr_t @param file tablespace file handle @return whether the operation failed */ bool restore_first_page( - ulint space_id, const char *name, os_file_t file); + ulint space_id, const char *name, pfs_os_file_t file); + + /** Restore the first page of the given tablespace from + doublewrite buffer. + 1) Find the page which has page_no as 0 + 2) Read first 3 pages from tablespace file + 3) Compare the space_ids from the pages with page0 which + was retrieved from doublewrite buffer + @param name tablespace filepath + @param file tablespace file handle + @return space_id or 0 in case of error */ + uint32_t find_first_page(const char *name, pfs_os_file_t file); typedef std::deque > list; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 05120871b0a..52649419ec7 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3415,6 +3415,46 @@ recv_init_crash_recovery_spaces(bool rescan, bool& missing_tablespace) return DB_SUCCESS; } +dberr_t recv_recovery_read_max_checkpoint() +{ + ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED || + srv_operation == SRV_OPERATION_RESTORE || + srv_operation == SRV_OPERATION_RESTORE_EXPORT); + ut_d(mysql_mutex_lock(&buf_pool.mutex)); + ut_ad(UT_LIST_GET_LEN(buf_pool.LRU) == 0); + ut_ad(UT_LIST_GET_LEN(buf_pool.unzip_LRU) == 0); + ut_d(mysql_mutex_unlock(&buf_pool.mutex)); + + if (srv_force_recovery >= SRV_FORCE_NO_LOG_REDO) + { + sql_print_information("InnoDB: innodb_force_recovery=6 skips redo log apply"); + return DB_SUCCESS; + } + + mysql_mutex_lock(&log_sys.mutex); + ulint max_cp; + dberr_t err= recv_find_max_checkpoint(&max_cp); + + if (err != DB_SUCCESS) + recv_sys.recovered_lsn= log_sys.get_lsn(); + else + { + byte* buf= log_sys.checkpoint_buf; + err= log_sys.log.read(max_cp, {buf, OS_FILE_LOG_BLOCK_SIZE}); + if (err == DB_SUCCESS) + { + log_sys.next_checkpoint_no= + mach_read_from_8(buf + LOG_CHECKPOINT_NO); + log_sys.next_checkpoint_lsn= + mach_read_from_8(buf + LOG_CHECKPOINT_LSN); + recv_sys.mlog_checkpoint_lsn= + mach_read_from_8(buf + LOG_CHECKPOINT_END_LSN); + } + } + mysql_mutex_unlock(&log_sys.mutex); + return err; +} + /** Start recovering from a redo log checkpoint. @param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN of first system tablespace page @@ -3422,12 +3462,8 @@ of first system tablespace page dberr_t recv_recovery_from_checkpoint_start(lsn_t flush_lsn) { - ulint max_cp_field; - lsn_t checkpoint_lsn; bool rescan = false; - ib_uint64_t checkpoint_no; lsn_t contiguous_lsn; - byte* buf; dberr_t err = DB_SUCCESS; ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED @@ -3445,27 +3481,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) return(DB_SUCCESS); } - recv_sys.recovery_on = true; - mysql_mutex_lock(&log_sys.mutex); - - err = recv_find_max_checkpoint(&max_cp_field); - - if (err != DB_SUCCESS) { - - recv_sys.recovered_lsn = log_sys.get_lsn(); - mysql_mutex_unlock(&log_sys.mutex); - return(err); - } - - buf = log_sys.checkpoint_buf; - if ((err= log_sys.log.read(max_cp_field, {buf, OS_FILE_LOG_BLOCK_SIZE}))) { - mysql_mutex_unlock(&log_sys.mutex); - return(err); - } - - checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); - checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); + uint64_t checkpoint_no= log_sys.next_checkpoint_no; + lsn_t checkpoint_lsn= log_sys.next_checkpoint_lsn; + const lsn_t end_lsn= recv_sys.mlog_checkpoint_lsn; + recv_sys.recovery_on = true; /* Start reading the log from the checkpoint lsn. The variable contiguous_lsn contains an lsn up to which the log is known to @@ -3474,8 +3494,6 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size); - const lsn_t end_lsn = mach_read_from_8( - buf + LOG_CHECKPOINT_END_LSN); ut_ad(recv_sys.pages.empty()); contiguous_lsn = checkpoint_lsn; @@ -3845,8 +3863,52 @@ byte *recv_dblwr_t::find_page(const page_id_t page_id, return result; } +uint32_t recv_dblwr_t::find_first_page(const char *name, pfs_os_file_t file) +{ + os_offset_t file_size= os_file_get_size(file); + if (file_size != (os_offset_t) -1) + { + for (const page_t *page : pages) + { + uint32_t space_id= page_get_space_id(page); + if (page_get_page_no(page) > 0 || space_id == 0) +next_page: + continue; + uint32_t flags= mach_read_from_4( + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + page_id_t page_id(space_id, 0); + size_t page_size= fil_space_t::physical_size(flags); + if (file_size < 4 * page_size) + goto next_page; + byte *read_page= + static_cast(aligned_malloc(3 * page_size, page_size)); + /* Read 3 pages from the file and match the space id + with the space id which is stored in + doublewrite buffer page. */ + if (os_file_read(IORequestRead, file, read_page, page_size, + 3 * page_size) != DB_SUCCESS) + goto next_page; + for (ulint j= 0; j <= 2; j++) + { + byte *cur_page= read_page + j * page_size; + if (buf_is_zeroes(span(cur_page, page_size))) + return 0; + if (mach_read_from_4(cur_page + FIL_PAGE_OFFSET) != j + 1 || + memcmp(cur_page + FIL_PAGE_SPACE_ID, + page + FIL_PAGE_SPACE_ID, 4) || + buf_page_is_corrupted(false, cur_page, flags)) + goto next_page; + } + if (!restore_first_page(space_id, name, file)) + return space_id; + break; + } + } + return 0; +} + bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name, - os_file_t file) + pfs_os_file_t file) { const page_id_t page_id(space_id, 0); const byte* page= find_page(page_id); @@ -3854,10 +3916,11 @@ bool recv_dblwr_t::restore_first_page(ulint space_id, const char *name, { /* If the first page of the given user tablespace is not there in the doublewrite buffer, then the recovery is going to fail - now. Hence this is treated as error. */ - ib::error() - << "Corrupted page " << page_id << " of datafile '" - << name <<"' could not be found in the doublewrite buffer."; + now. Report error only when doublewrite buffer is not empty */ + if (pages.size()) + ib::error() << "Corrupted page " << page_id << " of datafile '" + << name <<"' could not be found in the " + <<"doublewrite buffer."; return true; } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 56e41616d1d..0760b8ca5fd 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -297,9 +297,6 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn, log_sys.log.create(); log_sys.log.open_file(logfile0); - if (!fil_system.sys_space->open(create_new_db)) { - return DB_ERROR; - } /* Create a log checkpoint. */ mysql_mutex_lock(&log_sys.mutex); @@ -1274,40 +1271,6 @@ dberr_t srv_start(bool create_new_db) /* Check if undo tablespaces and redo log files exist before creating a new system tablespace */ - if (create_new_db) { - err = srv_check_undo_redo_logs_exists(); - if (err != DB_SUCCESS) { - return(srv_init_abort(DB_ERROR)); - } - recv_sys.debug_free(); - } - - /* Open or create the data files. */ - ulint sum_of_new_sizes; - - err = srv_sys_space.open_or_create( - false, create_new_db, &sum_of_new_sizes, &flushed_lsn); - - switch (err) { - case DB_SUCCESS: - break; - case DB_CANNOT_OPEN_FILE: - ib::error() - << "Could not open or create the system tablespace. If" - " you tried to add new data files to the system" - " tablespace, and it failed here, you should now" - " edit innodb_data_file_path in my.cnf back to what" - " it was, and remove the new ibdata files InnoDB" - " created in this failed attempt. InnoDB only wrote" - " those files full of zeros, but did not yet use" - " them in any way. But be careful: do not remove" - " old data files which contain your precious data!"; - /* fall through */ - default: - /* Other errors might come from Datafile::validate_first_page() */ - return(srv_init_abort(err)); - } - srv_log_file_size_requested = srv_log_file_size; if (innodb_encrypt_temporary_tables && !log_crypt_init()) { @@ -1317,18 +1280,17 @@ dberr_t srv_start(bool create_new_db) std::string logfile0; bool create_new_log = create_new_db; if (create_new_db) { + err = srv_check_undo_redo_logs_exists(); + if (err != DB_SUCCESS) { + return(srv_init_abort(DB_ERROR)); + } + recv_sys.debug_free(); flushed_lsn = log_sys.get_lsn(); log_sys.set_flushed_lsn(flushed_lsn); err = create_log_file(true, flushed_lsn, logfile0); if (err != DB_SUCCESS) { - for (Tablespace::const_iterator - i = srv_sys_space.begin(); - i != srv_sys_space.end(); i++) { - os_file_delete(innodb_data_file_key, - i->filepath()); - } return(srv_init_abort(err)); } } else { @@ -1343,51 +1305,84 @@ dberr_t srv_start(bool create_new_db) } create_new_log = srv_log_file_size == 0; - if (create_new_log) { - if (flushed_lsn < lsn_t(1000)) { - ib::error() - << "Cannot create log file because" - " data files are corrupt or the" - " database was not shut down cleanly" - " after creating the data files."; - return srv_init_abort(DB_ERROR); + if (!create_new_log) { + srv_log_file_found = log_file_found; + + log_sys.log.open_file(get_log_file_path()); + + log_sys.log.create(); + + if (!log_set_capacity( + srv_log_file_size_requested)) { + return(srv_init_abort(DB_ERROR)); } - srv_log_file_size = srv_log_file_size_requested; + /* Enable checkpoints in the page cleaner. */ + recv_sys.recovery_on = false; - err = create_log_file(false, flushed_lsn, logfile0); - - if (err == DB_SUCCESS) { - err = create_log_file_rename(flushed_lsn, - logfile0); - } + err= recv_recovery_read_max_checkpoint(); if (err != DB_SUCCESS) { - return(srv_init_abort(err)); + return srv_init_abort(err); } + } + } - /* Suppress the message about - crash recovery. */ - flushed_lsn = log_sys.get_lsn(); - goto file_checked; + /* Open or create the data files. */ + ulint sum_of_new_sizes; + + err = srv_sys_space.open_or_create( + false, create_new_db, &sum_of_new_sizes, &flushed_lsn); + + switch (err) { + case DB_SUCCESS: + break; + case DB_CANNOT_OPEN_FILE: + sql_print_error("InnoDB: Could not open or create the system" + " tablespace. If you tried to add new data files" + " to the system tablespace, and it failed here," + " you should now edit innodb_data_file_path" + " in my.cnf back to what it was, and remove the" + " new ibdata files InnoDB created in this failed" + " attempt. InnoDB only wrote those files full of" + " zeros, but did not yet use them in any way. But" + " be careful: do not remove old data files which" + " contain your precious data!"); + /* fall through */ + default: + /* Other errors might come from Datafile::validate_first_page() */ + return(srv_init_abort(err)); + } + + if (!create_new_db && create_new_log) { + if (flushed_lsn < lsn_t(1000)) { + sql_print_error( + "InnoDB: Cannot create log file because" + " data files are corrupt or the" + " database was not shut down cleanly" + " after creating the data files."); + return srv_init_abort(DB_ERROR); } - srv_log_file_found = log_file_found; + srv_log_file_size = srv_log_file_size_requested; - log_sys.log.open_file(get_log_file_path()); - - log_sys.log.create(); - - if (!log_set_capacity(srv_log_file_size_requested)) { - return(srv_init_abort(DB_ERROR)); + err = create_log_file(false, flushed_lsn, logfile0); + if (err == DB_SUCCESS) { + err = create_log_file_rename(flushed_lsn, logfile0); } - /* Enable checkpoints in the page cleaner. */ - recv_sys.recovery_on = false; + if (err != DB_SUCCESS) { + return(srv_init_abort(err)); + } + + /* Suppress the message about + crash recovery. */ + flushed_lsn = log_sys.get_lsn(); + goto file_checked; } file_checked: - /* Open log file and data files in the systemtablespace: we keep + /* Open data files in the systemtablespace: we keep them open until database shutdown */ ut_d(fil_system.sys_space->recv_size = srv_sys_space_size_debug); From 931df937e9382248ab082e4b3abd8ed149d48cd4 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 16 Jan 2024 17:17:50 +1100 Subject: [PATCH 033/121] MDEV-32559 failing spider signal_ddl_recovery_done callback should result in spider deinit Since 0930eb86cb00edb2ae285c3250ca51bae126e5e5, system table creation needed for spider init is delayed to the signal_ddl_recovery_done callback. Since it is part of the init, failure should result in spider deinit. We also remove the call to spider_init_system_tables() from spider_db_init(), as it was removed in the commit mentioned above and accidentally restored in a merge. --- include/mysql/plugin.h | 16 ++++++++++++++-- sql/handler.cc | 3 ++- sql/handler.h | 2 +- sql/mysqld.cc | 8 ++++++++ storage/innobase/handler/ha_innodb.cc | 3 ++- .../spider/bugfix/r/signal_ddl_fail.result | 8 ++++++++ .../spider/bugfix/t/signal_ddl_fail.opt | 2 ++ .../spider/bugfix/t/signal_ddl_fail.test | 10 ++++++++++ storage/spider/spd_table.cc | 19 +++---------------- 9 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/signal_ddl_fail.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.test diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 89ecf2b34c1..8a7a5e14223 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -531,7 +531,13 @@ struct st_mysql_plugin const char *author; /* plugin author (for I_S.PLUGINS) */ const char *descr; /* general descriptive text (for I_S.PLUGINS) */ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ - int (*init)(void *); /* the function to invoke when plugin is loaded */ + /* + The function to invoke when plugin is loaded. Plugin + initialisation done here should defer any ALTER TABLE queries to + after the ddl recovery is done, in the signal_ddl_recovery_done() + callback called by ha_signal_ddl_recovery_done(). + */ + int (*init)(void *); int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ unsigned int version; /* plugin version (for I_S.PLUGINS) */ struct st_mysql_show_var *status_vars; @@ -555,7 +561,13 @@ struct st_maria_plugin const char *author; /* plugin author (for SHOW PLUGINS) */ const char *descr; /* general descriptive text (for SHOW PLUGINS ) */ int license; /* the plugin license (PLUGIN_LICENSE_XXX) */ - int (*init)(void *); /* the function to invoke when plugin is loaded */ + /* + The function to invoke when plugin is loaded. Plugin + initialisation done here should defer any ALTER TABLE queries to + after the ddl recovery is done, in the signal_ddl_recovery_done() + callback called by ha_signal_ddl_recovery_done(). + */ + int (*init)(void *); int (*deinit)(void *);/* the function to invoke when plugin is unloaded */ unsigned int version; /* plugin version (for SHOW PLUGINS) */ struct st_mysql_show_var *status_vars; diff --git a/sql/handler.cc b/sql/handler.cc index 58a2eb3e43a..86fc697ec0c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -968,7 +968,8 @@ static my_bool signal_ddl_recovery_done(THD *, plugin_ref plugin, void *) { handlerton *hton= plugin_hton(plugin); if (hton->signal_ddl_recovery_done) - (hton->signal_ddl_recovery_done)(hton); + if ((hton->signal_ddl_recovery_done)(hton)) + plugin_ref_to_int(plugin)->state= PLUGIN_IS_DELETED; return 0; } diff --git a/sql/handler.h b/sql/handler.h index 0296d30213f..2d01979ab48 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1565,7 +1565,7 @@ struct handlerton const LEX_CUSTRING *version, ulonglong create_id); /* Called for all storage handlers after ddl recovery is done */ - void (*signal_ddl_recovery_done)(handlerton *hton); + int (*signal_ddl_recovery_done)(handlerton *hton); /* Optional clauses in the CREATE/ALTER TABLE diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 952802541b9..8b7888dfb79 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5118,6 +5118,14 @@ static int init_server_components() tc_log= 0; // ha_initialize_handlerton() needs that + /* + Plugins may not be completed because system table DDLs are only + run after the ddl recovery done. Therefore between the + plugin_init() call and the ha_signal_ddl_recovery_done() call + below only things related to preparation for recovery should be + done and nothing else, and definitely not anything assuming that + all plugins have been initialised. + */ if (plugin_init(&remaining_argc, remaining_argv, (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | (opt_abort ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e3b18599c99..af556d65695 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2155,7 +2155,7 @@ all_fail: ut_d(purge_sys.resume_FTS()); } -static void innodb_ddl_recovery_done(handlerton*) +static int innodb_ddl_recovery_done(handlerton*) { ut_ad(!ddl_recovery_done); ut_d(ddl_recovery_done= true); @@ -2166,6 +2166,7 @@ static void innodb_ddl_recovery_done(handlerton*) drop_garbage_tables_after_restore(); srv_init_purge_tasks(); } + return 0; } /********************************************************************//** diff --git a/storage/spider/mysql-test/spider/bugfix/r/signal_ddl_fail.result b/storage/spider/mysql-test/spider/bugfix/r/signal_ddl_fail.result new file mode 100644 index 00000000000..c86e600b2c1 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/signal_ddl_fail.result @@ -0,0 +1,8 @@ +# +# MDEV-32559 Move alter table statements in spider init queries to be executed in the signal_ddl_recovery_done callback +# +select * from mysql.plugin; +name dl +# +# end of test signal_ddl_fail +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.opt b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.opt new file mode 100644 index 00000000000..d883df7bed2 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.opt @@ -0,0 +1,2 @@ +--plugin-load-add=ha_spider +--debug-dbug=d,fail_spider_ddl_recovery_done diff --git a/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.test b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.test new file mode 100644 index 00000000000..f13eae3a062 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/signal_ddl_fail.test @@ -0,0 +1,10 @@ +--source include/have_debug.inc +--echo # +--echo # MDEV-32559 Move alter table statements in spider init queries to be executed in the signal_ddl_recovery_done callback +--echo # +# This test tests that failure in ddl_recovery callback causes the +# plugin to be deinitialized. +select * from mysql.plugin; +--echo # +--echo # end of test signal_ddl_fail +--echo # diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 65a00f5da34..5dc489daca3 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -7127,9 +7127,10 @@ bool spider_init_system_tables() Spider is typically loaded before ddl_recovery, but DDL statements cannot be executed before ddl_recovery, so we delay system table creation. */ -static void spider_after_ddl_recovery(handlerton *) +static int spider_after_ddl_recovery(handlerton *) { - spider_init_system_tables(); + DBUG_EXECUTE_IF("fail_spider_ddl_recovery_done", return 1;); + return spider_init_system_tables(); } int spider_db_init( @@ -7151,16 +7152,6 @@ int spider_db_init( #ifdef HTON_CAN_READ_CONNECT_STRING_IN_PARTITION spider_hton->flags |= HTON_CAN_READ_CONNECT_STRING_IN_PARTITION; #endif - /* spider_hton->db_type = DB_TYPE_SPIDER; */ - /* - spider_hton->savepoint_offset; - spider_hton->savepoint_set = spider_savepoint_set; - spider_hton->savepoint_rollback = spider_savepoint_rollback; - spider_hton->savepoint_release = spider_savepoint_release; - spider_hton->create_cursor_read_view = spider_create_cursor_read_view; - spider_hton->set_cursor_read_view = spider_set_cursor_read_view; - spider_hton->close_cursor_read_view = spider_close_cursor_read_view; - */ spider_hton->panic = spider_panic; spider_hton->signal_ddl_recovery_done= spider_after_ddl_recovery; spider_hton->close_connection = spider_close_connection; @@ -7233,10 +7224,6 @@ int spider_db_init( #ifndef WITHOUT_SPIDER_BG_SEARCH if (pthread_attr_init(&spider_pt_attr)) goto error_pt_attr_init; -/* - if (pthread_attr_setdetachstate(&spider_pt_attr, PTHREAD_CREATE_DETACHED)) - goto error_pt_attr_setstate; -*/ #endif #if MYSQL_VERSION_ID < 50500 From fa3171df08dc9b274dfe7fa03205b66554b621ac Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 27 Dec 2023 18:57:49 +0400 Subject: [PATCH 034/121] MDEV-27666 User variable not parsed as geometry variable in geometry function Adding GEOMETRY type user variables. --- mysql-test/main/gis.result | 107 ++++++++++++++++++ mysql-test/main/gis.test | 63 +++++++++++ .../binlog/r/binlog_gis_user_var_stm.result | 12 ++ .../binlog/t/binlog_gis_user_var_stm.test | 15 +++ .../suite/rpl/r/rpl_gis_user_var.result | 21 ++++ mysql-test/suite/rpl/t/rpl_gis_user_var.test | 18 +++ plugin/user_variables/user_variables.cc | 6 +- sql/item_func.cc | 80 ++++++------- sql/item_func.h | 7 +- sql/log.cc | 10 +- sql/log_event.cc | 54 ++++++--- sql/log_event.h | 21 ++-- sql/log_event_client.cc | 7 +- sql/log_event_data_type.h | 74 ++++++++++++ sql/log_event_server.cc | 70 ++++++++---- sql/sql_binlog.cc | 5 +- sql/sql_class.h | 7 +- sql/sql_repl.cc | 2 +- sql/sql_type.cc | 28 +++++ sql/sql_type.h | 11 ++ sql/sql_type_geom.h | 7 ++ storage/spider/spd_conn.cc | 2 +- storage/spider/spd_table.cc | 2 +- 23 files changed, 510 insertions(+), 119 deletions(-) create mode 100644 mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result create mode 100644 mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test create mode 100644 mysql-test/suite/rpl/r/rpl_gis_user_var.result create mode 100644 mysql-test/suite/rpl/t/rpl_gis_user_var.test create mode 100644 sql/log_event_data_type.h diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index f8816090b04..258d0c2f050 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -5328,5 +5328,112 @@ SELECT BIT_XOR(a) FROM t1; ERROR HY000: Illegal parameter data type geometry for operation 'bit_xor(' DROP TABLE t1; # +# MDEV-27666 User variable not parsed as geometry variable in geometry function. +# +set @g= point(1, 1); +select ST_AsWKT(GeometryCollection(Point(44, 6), @g)); +ST_AsWKT(GeometryCollection(Point(44, 6), @g)) +GEOMETRYCOLLECTION(POINT(44 6),POINT(1 1)) +set @g= "just a string"; +select ST_AsWKT(GeometryCollection(Point(44, 6), @g)); +ERROR HY000: Illegal parameter data type longblob for operation 'geometrycollection' +SET @g= LineString(Point(0,0), Point(0,1)); +SELECT AsText(PointN(@g, 1)); +AsText(PointN(@g, 1)) +POINT(0 0) +SELECT AsText(PointN(@g, 2)); +AsText(PointN(@g, 2)) +POINT(0 1) +SET @g= Point(1, 1); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` point DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +POINT(1 1) +DROP TABLE t1; +SET @g= MultiPoint(Point(1, 1), Point(-1,-1)); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` multipoint DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +MULTIPOINT(1 1,-1 -1) +DROP TABLE t1; +SET @g= LineString(Point(1, 1), Point(2,2)); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` linestring DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +LINESTRING(1 1,2 2) +DROP TABLE t1; +SET @g= MultiLineString(LineString(Point(1, 1), Point(2,2)), +LineString(Point(-1, -1), Point(-2,-2))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` multilinestring DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +MULTILINESTRING((1 1,2 2),(-1 -1,-2 -2)) +DROP TABLE t1; +SET @g= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` polygon DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +POLYGON((0 0,30 0,30 30,0 0)) +DROP TABLE t1; +SET @g= MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), +Point(3, 0), Point(0, 3)))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` multipolygon DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +DROP TABLE t1; +SET @g= GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` geometrycollection DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +DROP TABLE t1; +SET @g= GeometryFromText('POINT(1 1)'); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `g` geometry DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT AsText(g) FROM t1; +AsText(g) +POINT(1 1) +DROP TABLE t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index 4d66fb2b07d..f160d8f1a10 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -3374,6 +3374,69 @@ SELECT BIT_OR(a) FROM t1; SELECT BIT_XOR(a) FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-27666 User variable not parsed as geometry variable in geometry function. +--echo # + +set @g= point(1, 1); +select ST_AsWKT(GeometryCollection(Point(44, 6), @g)); +set @g= "just a string"; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +select ST_AsWKT(GeometryCollection(Point(44, 6), @g)); + +SET @g= LineString(Point(0,0), Point(0,1)); +SELECT AsText(PointN(@g, 1)); +SELECT AsText(PointN(@g, 2)); + +SET @g= Point(1, 1); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; + +SET @g= MultiPoint(Point(1, 1), Point(-1,-1)); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; + +SET @g= LineString(Point(1, 1), Point(2,2)); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; + +SET @g= MultiLineString(LineString(Point(1, 1), Point(2,2)), + LineString(Point(-1, -1), Point(-2,-2))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; + +SET @g= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; + +SET @g= MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), + Point(3, 0), Point(0, 3)))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; + +SET @g= GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; + +SET @g= GeometryFromText('POINT(1 1)'); +CREATE TABLE t1 AS SELECT @g AS g; +SHOW CREATE TABLE t1; +SELECT AsText(g) FROM t1; +DROP TABLE t1; --echo # --echo # End of 10.5 tests diff --git a/mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result b/mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result new file mode 100644 index 00000000000..e467c9c89b4 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_gis_user_var_stm.result @@ -0,0 +1,12 @@ +SET @g0= POINT(1,1); +SET @g1= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))); +CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1; +DROP TABLE t1; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # User var # # @`g0`=/*point*/_binary X'000000000101000000000000000000F03F000000000000F03F' COLLATE binary +master-bin.000001 # User var # # @`g1`=/*polygon*/_binary X'0000000001030000000100000004000000000000000000000000000000000000000000000000003E4000000000000000000000000000003E400000000000003E4000000000000000000000000000000000' COLLATE binary +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1 +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ diff --git a/mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test b/mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test new file mode 100644 index 00000000000..7e789cd7ae4 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_gis_user_var_stm.test @@ -0,0 +1,15 @@ +--source include/not_embedded.inc +--source include/have_binlog_format_statement.inc +--source include/have_geometry.inc + +--disable_query_log +reset master; # get rid of previous tests binlog +--enable_query_log + +SET @g0= POINT(1,1); +SET @g1= Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))); +CREATE TABLE t1 AS SELECT @g0 AS g0, @g1 AS g1; +DROP TABLE t1; + +--let $binlog_file = LAST +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/rpl/r/rpl_gis_user_var.result b/mysql-test/suite/rpl/r/rpl_gis_user_var.result new file mode 100644 index 00000000000..c6aab9e03f0 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gis_user_var.result @@ -0,0 +1,21 @@ +include/master-slave.inc +[connection master] +# +# +# +connection master; +SET @p=POINT(1,1); +CREATE TABLE t1 AS SELECT @p AS p; +connection slave; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `p` point DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT ST_AsWKT(p) FROM t1; +ST_AsWKT(p) +POINT(1 1) +connection master; +DROP TABLE t1; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gis_user_var.test b/mysql-test/suite/rpl/t/rpl_gis_user_var.test new file mode 100644 index 00000000000..8edd8cb9309 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gis_user_var.test @@ -0,0 +1,18 @@ +--source include/have_geometry.inc +--source include/master-slave.inc + +--echo # +--echo # +--echo # + +connection master; +SET @p=POINT(1,1); +CREATE TABLE t1 AS SELECT @p AS p; +sync_slave_with_master; +SHOW CREATE TABLE t1; +SELECT ST_AsWKT(p) FROM t1; +connection master; +DROP TABLE t1; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/plugin/user_variables/user_variables.cc b/plugin/user_variables/user_variables.cc index f820e4ad890..c76337cb084 100644 --- a/plugin/user_variables/user_variables.cc +++ b/plugin/user_variables/user_variables.cc @@ -79,9 +79,9 @@ static int user_variables_fill(THD *thd, TABLE_LIST *tables, COND *cond) else return 1; - const LEX_CSTRING *tmp= var->unsigned_flag ? - &unsigned_result_types[var->type] : - &result_types[var->type]; + const LEX_CSTRING *tmp= var->type_handler()->is_unsigned() ? + &unsigned_result_types[var->type_handler()->result_type()] : + &result_types[var->type_handler()->result_type()]; field[2]->store(tmp->str, tmp->length, system_charset_info); if (var->charset()) diff --git a/sql/item_func.cc b/sql/item_func.cc index 5202d395580..b2f2d6550f1 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4658,7 +4658,6 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name, entry->length=0; entry->update_query_id=0; entry->set_charset(NULL); - entry->unsigned_flag= 0; /* If we are here, we were called from a SET or a query which sets a variable. Imagine it is this: @@ -4670,7 +4669,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name, by Item_func_get_user_var (because that's not necessary). */ entry->used_query_id=current_thd->query_id; - entry->type=STRING_RESULT; + entry->set_handler(&type_handler_long_blob); memcpy((char*) entry->name.str, name->str, name->length+1); if (my_hash_insert(hash,(uchar*) entry)) { @@ -4746,9 +4745,12 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) switch (args[0]->result_type()) { case STRING_RESULT: case TIME_RESULT: - set_handler(type_handler_long_blob. - type_handler_adjusted_to_max_octet_length(max_length, - collation.collation)); + if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY) + set_handler(args[0]->type_handler()); + else + set_handler(type_handler_long_blob. + type_handler_adjusted_to_max_octet_length(max_length, + collation.collation)); break; case REAL_RESULT: set_handler(&type_handler_double); @@ -4873,9 +4875,9 @@ bool Item_func_set_user_var::register_field_in_bitmap(void *arg) bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, - Item_result type, CHARSET_INFO *cs, - bool unsigned_arg) + const Type_handler *th, CHARSET_INFO *cs) { + entry->set_handler(th); if (set_null) { char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry)); @@ -4886,7 +4888,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, } else { - if (type == STRING_RESULT) + if (th->result_type() == STRING_RESULT) length++; // Store strings with end \0 if (length <= extra_size) { @@ -4915,20 +4917,18 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, return 1; } } - if (type == STRING_RESULT) + if (th->result_type() == STRING_RESULT) { length--; // Fix length change above entry->value[length]= 0; // Store end \0 } if (length) memmove(entry->value, ptr, length); - if (type == DECIMAL_RESULT) + if (th->result_type() == DECIMAL_RESULT) ((my_decimal*)entry->value)->fix_buffer_pointer(); entry->length= length; entry->set_charset(cs); - entry->unsigned_flag= unsigned_arg; } - entry->type=type; #ifdef USER_VAR_TRACKING #ifndef EMBEDDED_LIBRARY THD *thd= current_thd; @@ -4941,9 +4941,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, bool Item_func_set_user_var::update_hash(void *ptr, size_t length, - Item_result res_type, - CHARSET_INFO *cs, - bool unsigned_arg) + const Type_handler *th, + CHARSET_INFO *cs) { /* If we set a variable explicitly to NULL then keep the old @@ -4957,9 +4956,8 @@ Item_func_set_user_var::update_hash(void *ptr, size_t length, else null_value= args[0]->null_value; if (null_value && null_item) - res_type= m_var_entry->type; // Don't change type of item - if (::update_hash(m_var_entry, null_value, - ptr, length, res_type, cs, unsigned_arg)) + th= m_var_entry->type_handler(); // Don't change type of item + if (::update_hash(m_var_entry, null_value, ptr, length, th, cs)) { null_value= 1; return 1; @@ -4975,7 +4973,7 @@ double user_var_entry::val_real(bool *null_value) if ((*null_value= (value == 0))) return 0.0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: return *(double*) value; case INT_RESULT: @@ -5000,7 +4998,7 @@ longlong user_var_entry::val_int(bool *null_value) const if ((*null_value= (value == 0))) return 0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: return (longlong) *(double*) value; case INT_RESULT: @@ -5029,12 +5027,12 @@ String *user_var_entry::val_str(bool *null_value, String *str, if ((*null_value= (value == 0))) return (String*) 0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: str->set_real(*(double*) value, decimals, charset()); break; case INT_RESULT: - if (!unsigned_flag) + if (!type_handler()->is_unsigned()) str->set(*(longlong*) value, charset()); else str->set(*(ulonglong*) value, charset()); @@ -5061,7 +5059,7 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val) if ((*null_value= (value == 0))) return 0; - switch (type) { + switch (type_handler()->result_type()) { case REAL_RESULT: double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val); break; @@ -5200,33 +5198,37 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_numeric, 0); + &type_handler_double, &my_charset_numeric); break; } case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_numeric, unsigned_flag); + unsigned_flag ? (Type_handler *) &type_handler_ulonglong : + (Type_handler *) &type_handler_slonglong, + &my_charset_numeric); break; } case STRING_RESULT: { if (!save_result.vstr) // Null value - res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, 0); + res= update_hash((void*) 0, 0, &type_handler_long_blob, &my_charset_bin); else res= update_hash((void*) save_result.vstr->ptr(), - save_result.vstr->length(), STRING_RESULT, - save_result.vstr->charset(), 0); + save_result.vstr->length(), + field_type() == MYSQL_TYPE_GEOMETRY ? + type_handler() : &type_handler_long_blob, + save_result.vstr->charset()); break; } case DECIMAL_RESULT: { if (!save_result.vdec) // Null value - res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin, 0); + res= update_hash((void*) 0, 0, &type_handler_newdecimal, &my_charset_bin); else res= update_hash((void*) save_result.vdec, - sizeof(my_decimal), DECIMAL_RESULT, - &my_charset_numeric, 0); + sizeof(my_decimal), &type_handler_newdecimal, + &my_charset_numeric); break; } case ROW_RESULT: @@ -5618,9 +5620,8 @@ get_var_with_binlog(THD *thd, enum_sql_command sql_command, user_var_event->value= (char*) user_var_event + ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)); user_var_event->user_var_event= var_entry; - user_var_event->type= var_entry->type; + user_var_event->th= var_entry->type_handler(); user_var_event->charset_number= var_entry->charset()->number; - user_var_event->unsigned_flag= var_entry->unsigned_flag; if (!var_entry->value) { /* NULL value*/ @@ -5663,9 +5664,9 @@ bool Item_func_get_user_var::fix_length_and_dec() */ if (likely(!error && m_var_entry)) { - unsigned_flag= m_var_entry->unsigned_flag; + unsigned_flag= m_var_entry->type_handler()->is_unsigned(); max_length= (uint32)m_var_entry->length; - switch (m_var_entry->type) { + switch (m_var_entry->type_handler()->result_type()) { case REAL_RESULT: collation.set(&my_charset_numeric, DERIVATION_NUMERIC); fix_char_length(DBL_DIG + 8); @@ -5684,6 +5685,8 @@ bool Item_func_get_user_var::fix_length_and_dec() collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT); max_length= MAX_BLOB_WIDTH - 1; set_handler(&type_handler_long_blob); + if (m_var_entry->type_handler()->field_type() == MYSQL_TYPE_GEOMETRY) + set_handler(m_var_entry->type_handler()); break; case DECIMAL_RESULT: collation.set(&my_charset_numeric, DERIVATION_NUMERIC); @@ -5756,7 +5759,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) DBUG_ASSERT(thd->lex->exchange); if (!(entry= get_variable(&thd->user_vars, &org_name, 1))) return TRUE; - entry->type= STRING_RESULT; + entry->set_handler(&type_handler_long_blob); /* Let us set the same collation which is used for loading of fields in LOAD DATA INFILE. @@ -5772,15 +5775,14 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs) { - ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, 0 /* unsigned_arg */); + ::update_hash(entry, TRUE, 0, 0, &type_handler_long_blob, cs); } void Item_user_var_as_out_param::set_value(const char *str, uint length, CHARSET_INFO* cs) { - ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs, - 0 /* unsigned_arg */); + ::update_hash(entry, FALSE, (void*)str, length, &type_handler_long_blob, cs); } diff --git a/sql/item_func.h b/sql/item_func.h index 1b8aefe005c..b205d457f1d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -3066,8 +3066,8 @@ public: String *str_result(String *str); my_decimal *val_decimal_result(my_decimal *); bool is_null_result(); - bool update_hash(void *ptr, size_t length, enum Item_result type, - CHARSET_INFO *cs, bool unsigned_arg); + bool update_hash(void *ptr, size_t length, const Type_handler *th, + CHARSET_INFO *cs); bool send(Protocol *protocol, st_value *buffer); void make_send_field(THD *thd, Send_field *tmp_field); bool check(bool use_result_field); @@ -3825,7 +3825,6 @@ double my_double_round(double value, longlong dec, bool dec_unsigned, extern bool volatile mqh_used; bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, - Item_result type, CHARSET_INFO *cs, - bool unsigned_arg); + const Type_handler *th, CHARSET_INFO *cs); #endif /* ITEM_FUNC_INCLUDED */ diff --git a/sql/log.cc b/sql/log.cc index 3d3ac9b2b35..75199000b85 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6794,18 +6794,12 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) BINLOG_USER_VAR_EVENT *user_var_event; get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i); - /* setting flags for user var log event */ - uchar flags= User_var_log_event::UNDEF_F; - if (user_var_event->unsigned_flag) - flags|= User_var_log_event::UNSIGNED_F; - User_var_log_event e(thd, user_var_event->user_var_event->name.str, user_var_event->user_var_event->name.length, user_var_event->value, user_var_event->length, - user_var_event->type, - user_var_event->charset_number, - flags, + user_var_event->th->user_var_log_event_data_type( + user_var_event->charset_number), using_trans, direct); if (write_event(&e, cache_data, file)) diff --git a/sql/log_event.cc b/sql/log_event.cc index d367575f9e8..1a3161d49a4 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2880,6 +2880,41 @@ XA_prepare_log_event(const char* buf, User_var_log_event methods **************************************************************************/ +bool Log_event_data_type::unpack_optional_attributes(const char *pos, + const char *end) + +{ + for ( ; pos < end; ) + { + switch (*pos) { + case CHUNK_SIGNED: + m_is_unsigned= false; + pos++; + continue; + case CHUNK_UNSIGNED: + m_is_unsigned= true; + pos++; + continue; + case CHUNK_DATA_TYPE_NAME: + { + pos++; + if (pos >= end) + return true; + uint length= (uchar) *pos++; + if (pos + length > end) + return true; + m_data_type_name= {pos, length}; + pos+= length; + continue; + } + default: + break; // Unknown chunk + } + } + return false; +} + + User_var_log_event:: User_var_log_event(const char* buf, uint event_len, const Format_description_log_event* description_event) @@ -2917,11 +2952,8 @@ User_var_log_event(const char* buf, uint event_len, buf+= UV_NAME_LEN_SIZE + name_len; is_null= (bool) *buf; - flags= User_var_log_event::UNDEF_F; // defaults to UNDEF_F if (is_null) { - type= STRING_RESULT; - charset_number= my_charset_bin.number; val_len= 0; val= 0; } @@ -2936,8 +2968,8 @@ User_var_log_event(const char* buf, uint event_len, goto err; } - type= (Item_result) buf[UV_VAL_IS_NULL]; - charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); + m_type= (Item_result) buf[UV_VAL_IS_NULL]; + m_charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE); @@ -2950,20 +2982,14 @@ User_var_log_event(const char* buf, uint event_len, the flags value. Old events will not have this extra byte, thence, - we keep the flags set to UNDEF_F. + we keep m_is_unsigned==false. */ - size_t bytes_read= (val + val_len) - buf_start; - if (bytes_read > event_len) + const char *pos= val + val_len; + if (pos > buf_end || unpack_optional_attributes(pos, buf_end)) { error= true; goto err; } - if ((data_written - bytes_read) > 0) - { - flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + - UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE + - val_len); - } } err: diff --git a/sql/log_event.h b/sql/log_event.h index 28ac4cc78df..afe4862f152 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -57,6 +57,8 @@ #include "rpl_gtid.h" +#include "log_event_data_type.h" + /* Forward declarations */ #ifndef MYSQL_CLIENT class String; @@ -3269,32 +3271,27 @@ private: @section User_var_log_event_binary_format Binary Format */ -class User_var_log_event: public Log_event + +class User_var_log_event: public Log_event, public Log_event_data_type { public: - enum { - UNDEF_F= 0, - UNSIGNED_F= 1 - }; const char *name; size_t name_len; const char *val; size_t val_len; - Item_result type; - uint charset_number; bool is_null; - uchar flags; #ifdef MYSQL_SERVER bool deferred; query_id_t query_id; User_var_log_event(THD* thd_arg, const char *name_arg, size_t name_len_arg, - const char *val_arg, size_t val_len_arg, Item_result type_arg, - uint charset_number_arg, uchar flags_arg, + const char *val_arg, size_t val_len_arg, + const Log_event_data_type &data_type, bool using_trans, bool direct) :Log_event(thd_arg, 0, using_trans), + Log_event_data_type(data_type), name(name_arg), name_len(name_len_arg), val(val_arg), - val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg), - flags(flags_arg), deferred(false) + val_len(val_len_arg), + deferred(false) { is_null= !val; if (direct) diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index c1c5ddf377c..c20b41e9632 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -2435,7 +2435,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) } else { - switch (type) { + switch (m_type) { case REAL_RESULT: double real_val; char real_buf[FMT_G_BUFSIZE(14)]; @@ -2447,8 +2447,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) break; case INT_RESULT: char int_buf[22]; - longlong10_to_str(uint8korr(val), int_buf, - ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10)); + longlong10_to_str(uint8korr(val), int_buf, is_unsigned() ? 10 : -10); if (my_b_printf(&cache, ":=%s%s\n", int_buf, print_event_info->delimiter)) goto err; @@ -2503,7 +2502,7 @@ bool User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) people want to mysqlbinlog|mysql into another server not supporting the character set. But there's not much to do about this and it's unlikely. */ - if (!(cs= get_charset(charset_number, MYF(0)))) + if (!(cs= get_charset(m_charset_number, MYF(0)))) { /* Generate an unusable command (=> syntax error) is probably the best thing we can do here. diff --git a/sql/log_event_data_type.h b/sql/log_event_data_type.h new file mode 100644 index 00000000000..e3b2039a63c --- /dev/null +++ b/sql/log_event_data_type.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2024, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + 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 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-1335 USA */ + +#ifndef LOG_EVENT_DATA_TYPE_H +#define LOG_EVENT_DATA_TYPE_H + +class Log_event_data_type +{ +public: + + enum { + CHUNK_SIGNED= 0, + CHUNK_UNSIGNED= 1, + CHUNK_DATA_TYPE_NAME= 2 + }; + +protected: + LEX_CSTRING m_data_type_name; + Item_result m_type; + uint m_charset_number; + bool m_is_unsigned; + +public: + + Log_event_data_type() + :m_data_type_name({NULL,0}), + m_type(STRING_RESULT), + m_charset_number(my_charset_bin.number), + m_is_unsigned(false) + { } + + Log_event_data_type(const LEX_CSTRING &data_type_name_arg, + Item_result type_arg, + uint charset_number_arg, + bool is_unsigned_arg) + :m_data_type_name(data_type_name_arg), + m_type(type_arg), + m_charset_number(charset_number_arg), + m_is_unsigned(is_unsigned_arg) + { } + + const LEX_CSTRING & data_type_name() const + { + return m_data_type_name; + } + Item_result type() const + { + return m_type; + } + uint charset_number() const + { + return m_charset_number; + } + bool is_unsigned() const + { + return m_is_unsigned; + } + + bool unpack_optional_attributes(const char *str, const char *end); +}; + +#endif // LOG_EVENT_DATA_TYPE_H diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 13a981d4381..2a22021cc95 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -4170,11 +4170,16 @@ bool XA_prepare_log_event::write() #if defined(HAVE_REPLICATION) static bool user_var_append_name_part(THD *thd, String *buf, - const char *name, size_t name_len) + const char *name, size_t name_len, + const LEX_CSTRING &data_type_name) { return buf->append("@") || append_identifier(thd, buf, name, name_len) || - buf->append("="); + buf->append("=") || + (data_type_name.length && + (buf->append("/*") || + buf->append(data_type_name.str, data_type_name.length) || + buf->append("*/"))); } void User_var_log_event::pack_info(Protocol* protocol) @@ -4184,14 +4189,15 @@ void User_var_log_event::pack_info(Protocol* protocol) char buf_mem[FN_REFLEN+7]; String buf(buf_mem, sizeof(buf_mem), system_charset_info); buf.length(0); - if (user_var_append_name_part(protocol->thd, &buf, name, name_len) || + if (user_var_append_name_part(protocol->thd, &buf, name, name_len, + m_data_type_name) || buf.append("NULL")) return; protocol->store(buf.ptr(), buf.length(), &my_charset_bin); } else { - switch (type) { + switch (m_type) { case REAL_RESULT: { double real_val; @@ -4200,7 +4206,8 @@ void User_var_log_event::pack_info(Protocol* protocol) String buf(buf_mem, sizeof(buf_mem), system_charset_info); float8get(real_val, val); buf.length(0); - if (user_var_append_name_part(protocol->thd, &buf, name, name_len) || + if (user_var_append_name_part(protocol->thd, &buf, name, name_len, + m_data_type_name) || buf.append(buf2, my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH, buf2, NULL))) return; @@ -4213,10 +4220,11 @@ void User_var_log_event::pack_info(Protocol* protocol) char buf_mem[FN_REFLEN + 22]; String buf(buf_mem, sizeof(buf_mem), system_charset_info); buf.length(0); - if (user_var_append_name_part(protocol->thd, &buf, name, name_len) || + if (user_var_append_name_part(protocol->thd, &buf, name, name_len, + m_data_type_name) || buf.append(buf2, longlong10_to_str(uint8korr(val), buf2, - ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10))-buf2)) + (is_unsigned() ? 10 : -10))-buf2)) return; protocol->store(buf.ptr(), buf.length(), &my_charset_bin); break; @@ -4229,7 +4237,8 @@ void User_var_log_event::pack_info(Protocol* protocol) String str(buf2, sizeof(buf2), &my_charset_bin); buf.length(0); my_decimal((const uchar *) (val + 2), val[0], val[1]).to_string(&str); - if (user_var_append_name_part(protocol->thd, &buf, name, name_len) || + if (user_var_append_name_part(protocol->thd, &buf, name, name_len, + m_data_type_name) || buf.append(buf2)) return; protocol->store(buf.ptr(), buf.length(), &my_charset_bin); @@ -4242,7 +4251,7 @@ void User_var_log_event::pack_info(Protocol* protocol) String buf(buf_mem, sizeof(buf_mem), system_charset_info); CHARSET_INFO *cs; buf.length(0); - if (!(cs= get_charset(charset_number, MYF(0)))) + if (!(cs= get_charset(m_charset_number, MYF(0)))) { if (buf.append("???")) return; @@ -4251,7 +4260,8 @@ void User_var_log_event::pack_info(Protocol* protocol) { size_t old_len; char *beg, *end; - if (user_var_append_name_part(protocol->thd, &buf, name, name_len) || + if (user_var_append_name_part(protocol->thd, &buf, name, name_len, + m_data_type_name) || buf.append("_") || buf.append(cs->csname) || buf.append(" ")) @@ -4299,10 +4309,10 @@ bool User_var_log_event::write() } else { - buf1[1]= type; - int4store(buf1 + 2, charset_number); + buf1[1]= m_type; + int4store(buf1 + 2, m_charset_number); - switch (type) { + switch (m_type) { case REAL_RESULT: float8store(buf2, *(double*) val); break; @@ -4332,15 +4342,28 @@ bool User_var_log_event::write() buf1_length= 10; } - /* Length of the whole event */ - event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len; + uchar data_type_name_chunk_signature= (uchar) CHUNK_DATA_TYPE_NAME; + uint data_type_name_chunk_signature_length= m_data_type_name.length ? 1 : 0; + uchar data_type_name_length_length= m_data_type_name.length ? 1 : 0; + /* Length of the whole event */ + event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len + + data_type_name_chunk_signature_length + + data_type_name_length_length + + (uint) m_data_type_name.length; + + uchar unsig= m_is_unsigned ? CHUNK_UNSIGNED : CHUNK_SIGNED; + uchar data_type_name_length= (uchar) m_data_type_name.length; return write_header(event_length) || write_data(buf, sizeof(buf)) || write_data(name, name_len) || write_data(buf1, buf1_length) || write_data(pos, val_len) || - write_data(&flags, unsigned_len) || + write_data(&unsig, unsigned_len) || + write_data(&data_type_name_chunk_signature, + data_type_name_chunk_signature_length) || + write_data(&data_type_name_length, data_type_name_length_length) || + write_data(m_data_type_name.str, (uint) m_data_type_name.length) || write_footer(); } @@ -4364,7 +4387,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi) current_thd->query_id= query_id; /* recreating original time context */ } - if (!(charset= get_charset(charset_number, MYF(MY_WME)))) + if (!(charset= get_charset(m_charset_number, MYF(MY_WME)))) { rgi->rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER_THD(thd, ER_SLAVE_FATAL_ERROR), @@ -4383,7 +4406,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi) } else { - switch (type) { + switch (m_type) { case REAL_RESULT: if (val_len != 8) { @@ -4447,13 +4470,10 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi) if (e->fix_fields(thd, 0)) DBUG_RETURN(1); - /* - A variable can just be considered as a table with - a single record and with a single column. Thus, like - a column value, it could always have IMPLICIT derivation. - */ - e->update_hash((void*) val, val_len, type, charset, - (flags & User_var_log_event::UNSIGNED_F)); + const Type_handler *th= Type_handler::handler_by_log_event_data_type(thd, + *this); + e->update_hash((void*) val, val_len, th, charset); + if (!is_deferred()) free_root(thd->mem_root, 0); else diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 4dd5f16f351..05ae01b542f 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -134,7 +134,7 @@ int binlog_defragment(THD *thd) entry[k]= (user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name[k].str, name[k].length); - if (!entry[k] || entry[k]->type != STRING_RESULT) + if (!entry[k] || entry[k]->type_handler()->result_type() != STRING_RESULT) { my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), name[k].str); return -1; @@ -159,7 +159,8 @@ int binlog_defragment(THD *thd) gathered_length += entry[k]->length; } for (uint k=0; k < 2; k++) - update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0); + update_hash(entry[k], true, NULL, 0, + &type_handler_long_blob, &my_charset_bin); DBUG_ASSERT(gathered_length == thd->lex->comment.length); diff --git a/sql/sql_class.h b/sql/sql_class.h index 06abab99be7..a8ef8648210 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -275,9 +275,8 @@ typedef struct st_user_var_events user_var_entry *user_var_event; char *value; size_t length; - Item_result type; + const Type_handler *th; uint charset_number; - bool unsigned_flag; } BINLOG_USER_VAR_EVENT; /* @@ -6808,7 +6807,7 @@ public: // this is needed for user_vars hash -class user_var_entry +class user_var_entry: public Type_handler_hybrid_field_type { CHARSET_INFO *m_charset; public: @@ -6817,8 +6816,6 @@ class user_var_entry char *value; size_t length; query_id_t update_query_id, used_query_id; - Item_result type; - bool unsigned_flag; double val_real(bool *null_value); longlong val_int(bool *null_value) const; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 1a83b96b61b..270f051b9dd 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -510,7 +510,7 @@ static enum enum_binlog_checksum_alg get_binlog_checksum_value_at_connect(THD * } else { - DBUG_ASSERT(entry->type == STRING_RESULT); + DBUG_ASSERT(entry->type_handler()->result_type() == STRING_RESULT); String str; uint dummy_errors; str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin, diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 13e61a40be2..77931b6cf16 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2248,6 +2248,34 @@ Type_handler::get_handler_by_real_type(enum_field_types type) } +const Type_handler * +Type_handler::handler_by_log_event_data_type(THD *thd, + const Log_event_data_type &type) +{ + if (type.data_type_name().length) + { + const Type_handler *th= handler_by_name(thd, type.data_type_name()); + if (th) + return th; + } + switch (type.type()) { + case STRING_RESULT: + case ROW_RESULT: + case TIME_RESULT: + break; + case REAL_RESULT: + return &type_handler_double; + case INT_RESULT: + if (type.is_unsigned()) + return &type_handler_ulonglong; + return &type_handler_slonglong; + case DECIMAL_RESULT: + return &type_handler_newdecimal; + } + return &type_handler_long_blob; +} + + /** Create a DOUBLE field by default. */ diff --git a/sql/sql_type.h b/sql/sql_type.h index edce7f45abe..c8c92e56253 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -30,6 +30,8 @@ #include "sql_type_string.h" #include "sql_type_real.h" #include "compat56.h" +#include "log_event_data_type.h" + C_MODE_START #include C_MODE_END @@ -3652,6 +3654,9 @@ public: static const Type_handler *handler_by_name(THD *thd, const LEX_CSTRING &name); static const Type_handler *handler_by_name_or_error(THD *thd, const LEX_CSTRING &name); + static const Type_handler *handler_by_log_event_data_type( + THD *thd, + const Log_event_data_type &type); static const Type_handler *odbc_literal_type_handler(const LEX_CSTRING *str); static const Type_handler *blob_type_handler(uint max_octet_length); static const Type_handler *string_type_handler(uint max_octet_length); @@ -3936,6 +3941,12 @@ public: { return false; } + + virtual Log_event_data_type user_var_log_event_data_type(uint charset_nr) const + { + return Log_event_data_type({NULL,0}/*data type name*/, result_type(), + charset_nr, is_unsigned()); + } virtual uint Column_definition_gis_options_image(uchar *buff, const Column_definition &def) const diff --git a/sql/sql_type_geom.h b/sql/sql_type_geom.h index ff00beea598..858c2da2318 100644 --- a/sql/sql_type_geom.h +++ b/sql/sql_type_geom.h @@ -81,6 +81,13 @@ public: Field *make_conversion_table_field(MEM_ROOT *root, TABLE *table, uint metadata, const Field *target) const override; + Log_event_data_type user_var_log_event_data_type(uint charset_nr) + const override + { + return Log_event_data_type(name().lex_cstring(), result_type(), + charset_nr, false/*unsigned*/); + } + uint Column_definition_gis_options_image(uchar *buff, const Column_definition &def) const override; diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 9897e495c83..befd9bfd2db 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -1886,7 +1886,7 @@ int spider_conn_queue_loop_check( loop_check_buf[lex_str.length] = '\0'; DBUG_PRINT("info", ("spider param name=%s", lex_str.str)); loop_check = get_variable(&thd->user_vars, &lex_str, FALSE); - if (!loop_check || loop_check->type != STRING_RESULT) + if (!loop_check || loop_check->type_handler()->result_type() != STRING_RESULT) { DBUG_PRINT("info", ("spider client is not Spider")); lex_str.str = ""; diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 4ff54b591ba..717313df2af 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -4742,7 +4742,7 @@ SPIDER_SHARE *spider_get_share( ((char *) lex_str.str)[lex_str.length] = '\0'; DBUG_PRINT("info",("spider loop check param name=%s", lex_str.str)); loop_check = get_variable(&thd->user_vars, &lex_str, FALSE); - if (loop_check && loop_check->type == STRING_RESULT) + if (loop_check && loop_check->type_handler()->result_type() == STRING_RESULT) { lex_str.length = top_share->path.length + spider_unique_id.length + 1; lex_str.str = loop_check_buf + buf_sz - top_share->path.length - From 9c059a4f1cbff28634cced9f02da5a0279e6f242 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 17 Jan 2024 10:33:02 +1100 Subject: [PATCH 035/121] Spider: no need to check for ubsan when running ubsan tests It's ok to run these tests without ubsan too, and we get some tests for free. --- .../mysql-test/spider/bugfix/r/mdev_26541.result | 15 --------------- .../mysql-test/spider/bugfix/t/mdev_26541.test | 6 ++---- .../mysql-test/spider/bugfix/t/mdev_28998.test | 5 +---- .../mysql-test/spider/bugfix/t/mdev_30981.test | 11 ++++------- 4 files changed, 7 insertions(+), 30 deletions(-) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result index 72921d2e695..35a9d9167a6 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_26541.result @@ -2,18 +2,3 @@ # MDEV-26541 Undefined symbol: _ZTI12ha_partition when attempting to use ha_spider.so in UBSAN builds # INSTALL SONAME 'ha_spider.so'; -DROP FUNCTION spider_flush_table_mon_cache; -DROP FUNCTION spider_copy_tables; -DROP FUNCTION spider_ping_table; -DROP FUNCTION spider_bg_direct_sql; -DROP FUNCTION spider_direct_sql; -UNINSTALL SONAME IF EXISTS "ha_spider"; -DROP TABLE IF EXISTS mysql.spider_xa; -DROP TABLE IF EXISTS mysql.spider_xa_member; -DROP TABLE IF EXISTS mysql.spider_xa_failed_log; -DROP TABLE IF EXISTS mysql.spider_tables; -DROP TABLE IF EXISTS mysql.spider_link_mon_servers; -DROP TABLE IF EXISTS mysql.spider_link_failed_log; -DROP TABLE IF EXISTS mysql.spider_table_position_for_recovery; -DROP TABLE IF EXISTS mysql.spider_table_sts; -DROP TABLE IF EXISTS mysql.spider_table_crd; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test index bf6cb255d02..add5f621441 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_26541.test @@ -2,10 +2,7 @@ --echo # MDEV-26541 Undefined symbol: _ZTI12ha_partition when attempting to use ha_spider.so in UBSAN builds --echo # -if (`select not(count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "%UBSAN%"`) -{ ---skip test needs to be run with UBSAN -} +# this test should be checked with ubsan # init spider @@ -20,4 +17,5 @@ while (!$PLUGIN_EXIST) `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`; } +--disable_query_log --source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test index 66e3a15addb..51d4c5c9660 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28998.test @@ -2,10 +2,7 @@ --echo # MDEV-28998 ASAN errors in spider_fields::free_conn_holder or spider_create_group_by_handler --echo # -if (`select not(count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "%ASAN%"`) -{ ---skip test needs to be run with ASAN -} +# this test should be checked with ubsan --disable_query_log --disable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test index cc24ce82ce4..ca3f000c819 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_30981.test @@ -2,21 +2,18 @@ --echo # MDEV-30981 Spider UBSAN: null pointer passed as argument 2, which is declared to never be null in spider_create_trx_alter_table on ALTER --echo # -if (`select not(count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "%UBSAN%"`) -{ ---skip test needs to be run with UBSAN -} - +# this test should be checked with ubsan + --disable_query_log --disable_result_log --source ../../t/test_init.inc --enable_result_log --enable_query_log - + CREATE TABLE t (c INT) ENGINE=Spider PARTITION BY LIST (c) (PARTITION p VALUES IN (1,2)); ALTER TABLE t ENGINE=InnoDB; drop table t; - + --disable_query_log --disable_result_log --source ../t/test_deinit.inc From f8c88d905b44bffe161158309e9acc25ad3691aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 Jan 2024 11:14:24 +0200 Subject: [PATCH 036/121] MDEV-33213 History list is not shrunk unless there is a pause in the workload The parameter innodb_undo_log_truncate=ON enables a multi-phased logic: 1. Any "producers" (new starting transactions) are prohibited from using the rollback segments that reside in the undo tablespace. 2. Any transactions that use any of the rollback segments must be committed or aborted. 3. The purge of committed transaction history must process all the rollback segments. 4. The undo tablespace is truncated and rebuilt. 5. The rollback segments are re-enabled for new transactions. There was one flaw in this logic: The first step was not being invoked as often as it could be, and therefore innodb_undo_log_truncate=ON would have no chance to work during a heavy write workload. Independent of innodb_undo_log_truncate, even after commit 86767bcc0f121db3ad83a74647a642754a0ce57f we are missing some chances to free processed undo log pages. If we prohibited the creation of new transactions in one busy rollback segment at a time, we would be eventually guaranteed to be able to free such pages. purge_sys_t::skipped_rseg: The current candidate rollback segment for shrinking the history independent of innodb_undo_log_truncate. purge_sys_t::iterator::free_history_rseg(): Renamed from trx_purge_truncate_rseg_history(). Implement the logic around purge_sys.m_skipped_rseg. purge_sys_t::truncate_undo_space: Renamed from truncate. purge_sys.truncate_undo_space.last: Changed the type to integer to get rid of some pointer dereferencing and conditional branches. purge_sys_t::truncating_tablespace(), purge_sys_t::undo_truncate_try(): Refactored from trx_purge_truncate_history(). Set purge_sys.truncate_undo_space.current if applicable, or return an already set purge_sys.truncate_undo_space.current. purge_coordinator_state::do_purge(): Invoke purge_sys_t::truncating_tablespace() as part of the normal work loop, to implement innodb_undo_log_truncate=ON as often as possible. trx_purge_truncate_rseg_history(): Remove a redundant parameter. trx_undo_truncate_start(): Replace dead code with a debug assertion. Correctness tested by: Matthias Leich Performance tested by: Axel Schwenke Reviewed by: Debarun Banerjee --- storage/innobase/include/trx0purge.h | 51 +++++- storage/innobase/include/trx0rseg.h | 5 +- storage/innobase/include/trx0sys.h | 5 + storage/innobase/srv/srv0srv.cc | 3 +- storage/innobase/trx/trx0purge.cc | 233 ++++++++++++++++++--------- storage/innobase/trx/trx0undo.cc | 8 +- 6 files changed, 212 insertions(+), 93 deletions(-) diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 3ddd2e98fee..a836c134c02 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -140,6 +140,15 @@ private: bool m_initialized{false}; /** whether purge is enabled; protected by latch and std::atomic */ std::atomic m_enabled{false}; + /** The primary candidate for iterator::free_history() is + rseg=trx_sys.rseg_array[skipped_rseg]. This field may be changed + after invoking rseg.set_skip_allocation() and rseg.clear_skip_allocation() + and while holding the exclusive rseg.latch. + + This may only be 0 if innodb_undo_tablespaces=0, because rollback segment + 0 always resides in the system tablespace and would never be used when + dedicated undo tablespaces are in use. */ + Atomic_relaxed skipped_rseg; public: /** whether purge is active (may hold table handles) */ std::atomic m_active{false}; @@ -197,6 +206,11 @@ public: return undo_no <= other.undo_no; } + /** Remove unnecessary history data from a rollback segment. + @param rseg rollback segment + @return error code */ + inline dberr_t free_history_rseg(trx_rseg_t &rseg) const; + /** Free the undo pages up to this. */ dberr_t free_history() const; @@ -240,14 +254,15 @@ public: by the pq_mutex */ mysql_mutex_t pq_mutex; /*!< Mutex protecting purge_queue */ - /** Undo tablespace file truncation (only accessed by the - srv_purge_coordinator_thread) */ - struct { - /** The undo tablespace that is currently being truncated */ - fil_space_t* current; - /** The undo tablespace that was last truncated */ - fil_space_t* last; - } truncate; + /** innodb_undo_log_truncate=ON state; + only modified by purge_coordinator_callback() */ + struct { + /** The undo tablespace that is currently being truncated */ + Atomic_relaxed current; + /** The number of the undo tablespace that was last truncated, + relative from srv_undo_space_id_start */ + ulint last; + } truncate_undo_space; /** Create the instance */ void create(); @@ -357,6 +372,26 @@ public: typically via purge_sys_t::view_guard. */ return view.sees(id); } + +private: + /** Enable the use of a rollback segment and advance skipped_rseg, + after iterator::free_history_rseg() had invoked + rseg.set_skip_allocation(). */ + inline void rseg_enable(trx_rseg_t &rseg); + + /** Try to start truncating a tablespace. + @param id undo tablespace identifier + @param size the maximum desired undo tablespace size, in pages + @return undo tablespace whose truncation was started + @retval nullptr if truncation is not currently possible */ + inline fil_space_t *undo_truncate_try(ulint id, ulint size); +public: + /** Check if innodb_undo_log_truncate=ON needs to be handled. + This is only to be called by purge_coordinator_callback(). + @return undo tablespace chosen by innodb_undo_log_truncate=ON + @retval nullptr if truncation is not currently possible */ + fil_space_t *truncating_tablespace(); + /** A wrapper around trx_sys_t::clone_oldest_view(). */ template void clone_oldest_view() diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index 1d95b7d2e7a..f5d9a2199a1 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -73,14 +73,15 @@ private: /** Reference counter to track is_persistent() transactions, with SKIP flag. */ std::atomic ref; - +public: /** Whether undo tablespace truncation is pending */ static constexpr uint32_t SKIP= 1; /** Transaction reference count multiplier */ static constexpr uint32_t REF= 2; + /** @return the reference count and flags */ uint32_t ref_load() const { return ref.load(std::memory_order_relaxed); } - +private: /** Set the SKIP bit */ void ref_set_skip() { diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index c5f8ab012c4..cf1579a3e30 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -1189,6 +1189,11 @@ public: return count; } + /** Disable further allocation of transactions in a rollback segment + that are subject to innodb_undo_log_truncate=ON + @param space undo tablespace that will be truncated */ + inline void undo_truncate_start(fil_space_t &space); + private: static my_bool find_same_or_older_callback(rw_trx_hash_element_t *element, trx_id_t *id) diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 7923b14d69d..b29caf255fc 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1638,7 +1638,8 @@ inline void purge_coordinator_state::do_purge() ulint n_pages_handled= trx_purge(n_threads, history_size); if (!trx_sys.history_exists()) goto no_history; - if (purge_sys.truncate.current || srv_shutdown_state != SRV_SHUTDOWN_NONE) + if (purge_sys.truncating_tablespace() || + srv_shutdown_state != SRV_SHUTDOWN_NONE) { purge_truncation_task.wait(); trx_purge_truncate_history(); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 230036c8499..30cce66697f 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -169,10 +169,15 @@ void purge_sys_t::create() ut_ad(this == &purge_sys); ut_ad(!m_initialized); ut_ad(!enabled()); + ut_ad(!m_active); + /* If innodb_undo_tablespaces>0, the rollback segment 0 + (which always resides in the system tablespace) will + never be used; @see trx_assign_rseg_low() */ + skipped_rseg= srv_undo_tablespaces > 0; m_paused= 0; query= purge_graph_build(); next_stored= false; - rseg= NULL; + rseg= nullptr; page_no= 0; offset= 0; hdr_page_no= 0; @@ -180,8 +185,8 @@ void purge_sys_t::create() latch.SRW_LOCK_INIT(trx_purge_latch_key); end_latch.init(); mysql_mutex_init(purge_sys_pq_mutex_key, &pq_mutex, nullptr); - truncate.current= NULL; - truncate.last= NULL; + truncate_undo_space.current= nullptr; + truncate_undo_space.last= 0; m_initialized= true; } @@ -387,17 +392,50 @@ static void trx_purge_free_segment(buf_block_t *rseg_hdr, buf_block_t *block, block->page.frame, &mtr)); } +void purge_sys_t::rseg_enable(trx_rseg_t &rseg) +{ + ut_ad(this == &purge_sys); +#ifndef SUX_LOCK_GENERIC + ut_ad(rseg.latch.is_write_locked()); +#endif + uint8_t skipped= skipped_rseg; + ut_ad(skipped < TRX_SYS_N_RSEGS); + if (&rseg == &trx_sys.rseg_array[skipped]) + { + /* If this rollback segment is subject to innodb_undo_log_truncate=ON, + we must not clear the flag. But we will advance purge_sys.skipped_rseg + to be able to choose another candidate for this soft truncation, and + to prevent the following scenario: + + (1) purge_sys_t::iterator::free_history_rseg() had invoked + rseg.set_skip_allocation() + (2) undo log truncation had completed on this rollback segment + (3) SET GLOBAL innodb_undo_log_truncate=OFF + (4) purge_sys_t::iterator::free_history_rseg() would not be able to + invoke rseg.set_skip_allocation() on any other rollback segment + before this rseg has grown enough */ + if (truncate_undo_space.current != rseg.space) + rseg.clear_skip_allocation(); + skipped++; + /* If innodb_undo_tablespaces>0, the rollback segment 0 + (which always resides in the system tablespace) will + never be used; @see trx_assign_rseg_low() */ + if (!(skipped%= TRX_SYS_N_RSEGS) && srv_undo_tablespaces) + skipped++; + skipped_rseg= skipped; + } +} + /** Remove unnecessary history data from a rollback segment. @param rseg rollback segment @param limit truncate anything before this -@param all whether everything can be truncated @return error code */ -static dberr_t -trx_purge_truncate_rseg_history(trx_rseg_t &rseg, - const purge_sys_t::iterator &limit, bool all) +inline dberr_t purge_sys_t::iterator::free_history_rseg(trx_rseg_t &rseg) const { fil_addr_t hdr_addr; mtr_t mtr; + bool freed= false; + uint32_t rseg_ref= 0; mtr.start(); @@ -407,6 +445,8 @@ trx_purge_truncate_rseg_history(trx_rseg_t &rseg, { func_exit: mtr.commit(); + if (freed && (rseg.SKIP & rseg_ref)) + purge_sys.rseg_enable(rseg); return err; } @@ -428,16 +468,40 @@ loop: const trx_id_t undo_trx_no= mach_read_from_8(b->page.frame + hdr_addr.boffset + TRX_UNDO_TRX_NO); - if (undo_trx_no >= limit.trx_no) + if (undo_trx_no >= trx_no) { - if (undo_trx_no == limit.trx_no) - err = trx_undo_truncate_start(&rseg, hdr_addr.page, - hdr_addr.boffset, limit.undo_no); + if (undo_trx_no == trx_no) + err= trx_undo_truncate_start(&rseg, hdr_addr.page, + hdr_addr.boffset, undo_no); goto func_exit; } + else + { + rseg_ref= rseg.ref_load(); + if (rseg_ref >= rseg.REF || !purge_sys.sees(rseg.needs_purge)) + { + /* We cannot clear this entire rseg because trx_assign_rseg_low() + has already chosen it for a future trx_undo_assign(), or + because some recently started transaction needs purging. - if (!all) - goto func_exit; + If this invocation could not reduce rseg.history_size at all + (!freed), we will try to ensure progress and prevent our + starvation by disabling one rollback segment for future + trx_assign_rseg_low() invocations until a future invocation has + made progress and invoked purge_sys_t::rseg_enable(rseg) on that + rollback segment. */ + + if (!(rseg.SKIP & rseg_ref) && !freed && + ut_d(!trx_rseg_n_slots_debug &&) + &rseg == &trx_sys.rseg_array[purge_sys.skipped_rseg]) + /* If rseg.space == purge_sys.truncate_undo_space.current + the following will be a no-op. A possible conflict + with innodb_undo_log_truncate=ON will be handled in + purge_sys_t::rseg_enable(). */ + rseg.set_skip_allocation(); + goto func_exit; + } + } fil_addr_t prev_hdr_addr= flst_get_prev_addr(b->page.frame + hdr_addr.boffset + @@ -500,6 +564,7 @@ loop: mtr.commit(); ut_ad(rseg.history_size > 0); rseg.history_size--; + freed= true; mtr.start(); rseg_hdr->page.lock.x_lock(); ut_ad(rseg_hdr->page.id() == rseg.page_id()); @@ -554,9 +619,7 @@ dberr_t purge_sys_t::iterator::free_history() const ut_ad(rseg.is_persistent()); log_free_check(); rseg.latch.wr_lock(SRW_LOCK_CALL); - dberr_t err= - trx_purge_truncate_rseg_history(rseg, *this, !rseg.is_referenced() && - purge_sys.sees(rseg.needs_purge)); + dberr_t err= free_history_rseg(rseg); rseg.latch.wr_unlock(); if (err) return err; @@ -564,6 +627,62 @@ dberr_t purge_sys_t::iterator::free_history() const return DB_SUCCESS; } +inline void trx_sys_t::undo_truncate_start(fil_space_t &space) +{ + ut_ad(this == &trx_sys); + /* Undo tablespace always are a single file. */ + ut_a(UT_LIST_GET_LEN(space.chain) == 1); + fil_node_t *file= UT_LIST_GET_FIRST(space.chain); + /* The undo tablespace files are never closed. */ + ut_ad(file->is_open()); + sql_print_information("InnoDB: Starting to truncate %s", file->name); + + for (auto &rseg : rseg_array) + if (rseg.space == &space) + { + /* Prevent a race with purge_sys_t::iterator::free_history_rseg() */ + rseg.latch.rd_lock(SRW_LOCK_CALL); + /* Once set, this rseg will not be allocated to subsequent + transactions, but we will wait for existing active + transactions to finish. */ + rseg.set_skip_allocation(); + rseg.latch.rd_unlock(); + } +} + +inline fil_space_t *purge_sys_t::undo_truncate_try(ulint id, ulint size) +{ + ut_ad(srv_is_undo_tablespace(id)); + fil_space_t *space= fil_space_get(id); + if (space && space->get_size() > size) + { + truncate_undo_space.current= space; + trx_sys.undo_truncate_start(*space); + return space; + } + return nullptr; +} + +fil_space_t *purge_sys_t::truncating_tablespace() +{ + ut_ad(this == &purge_sys); + + fil_space_t *space= truncate_undo_space.current; + if (space || srv_undo_tablespaces_active < 2 || !srv_undo_log_truncate) + return space; + + const ulint size= ulint(srv_max_undo_log_size >> srv_page_size_shift); + for (ulint i= truncate_undo_space.last, j= i;; ) + { + if (fil_space_t *s= undo_truncate_try(srv_undo_space_id_start + i, size)) + return s; + ++i; + i%= srv_undo_tablespaces_active; + if (i == j) + return nullptr; + } +} + #if defined __GNUC__ && __GNUC__ == 4 && !defined __clang__ # if defined __arm__ || defined __aarch64__ /* Work around an internal compiler error in GCC 4.8.5 */ @@ -589,55 +708,14 @@ TRANSACTIONAL_TARGET void trx_purge_truncate_history() head.undo_no= 0; } - if (head.free_history() != DB_SUCCESS || srv_undo_tablespaces_active < 2) + if (head.free_history() != DB_SUCCESS) return; - while (srv_undo_log_truncate) + while (fil_space_t *space= purge_sys.truncating_tablespace()) { - if (!purge_sys.truncate.current) - { - const ulint threshold= - ulint(srv_max_undo_log_size >> srv_page_size_shift); - for (ulint i= purge_sys.truncate.last - ? purge_sys.truncate.last->id - srv_undo_space_id_start : 0, - j= i;; ) - { - const auto space_id= srv_undo_space_id_start + i; - ut_ad(srv_is_undo_tablespace(space_id)); - fil_space_t *space= fil_space_get(space_id); - ut_a(UT_LIST_GET_LEN(space->chain) == 1); - - if (space && space->get_size() > threshold) - { - purge_sys.truncate.current= space; - break; - } - - ++i; - i %= srv_undo_tablespaces_active; - if (i == j) - return; - } - } - - fil_space_t &space= *purge_sys.truncate.current; - /* Undo tablespace always are a single file. */ - fil_node_t *file= UT_LIST_GET_FIRST(space.chain); - /* The undo tablespace files are never closed. */ - ut_ad(file->is_open()); - - DBUG_LOG("undo", "marking for truncate: " << file->name); - - for (auto &rseg : trx_sys.rseg_array) - if (rseg.space == &space) - /* Once set, this rseg will not be allocated to subsequent - transactions, but we will wait for existing active - transactions to finish. */ - rseg.set_skip_allocation(); - for (auto &rseg : trx_sys.rseg_array) { - if (rseg.space != &space) + if (rseg.space != space) continue; rseg.latch.rd_lock(SRW_LOCK_CALL); @@ -670,8 +748,9 @@ not_free: rseg.latch.rd_unlock(); } - sql_print_information("InnoDB: Truncating %s", file->name); - trx_purge_cleanse_purge_queue(space); + const char *file_name= UT_LIST_GET_FIRST(space->chain)->name; + sql_print_information("InnoDB: Truncating %s", file_name); + trx_purge_cleanse_purge_queue(*space); /* Lock all modified pages of the tablespace. @@ -688,12 +767,12 @@ not_free: /* Adjust the tablespace metadata. */ mysql_mutex_lock(&fil_system.mutex); - if (space.crypt_data) + if (space->crypt_data) { - space.reacquire(); + space->reacquire(); mysql_mutex_unlock(&fil_system.mutex); - fil_space_crypt_close_tablespace(&space); - space.release(); + fil_space_crypt_close_tablespace(space); + space->release(); } else mysql_mutex_unlock(&fil_system.mutex); @@ -705,17 +784,17 @@ not_free: mtr_t mtr; mtr.start(); - mtr.x_lock_space(&space); + mtr.x_lock_space(space); /* Associate the undo tablespace with mtr. During mtr::commit_shrink(), InnoDB can use the undo tablespace object to clear all freed ranges */ - mtr.set_named_space(&space); - mtr.trim_pages(page_id_t(space.id, size)); - ut_a(fsp_header_init(&space, size, &mtr) == DB_SUCCESS); + mtr.set_named_space(space); + mtr.trim_pages(page_id_t(space->id, size)); + ut_a(fsp_header_init(space, size, &mtr) == DB_SUCCESS); for (auto &rseg : trx_sys.rseg_array) { - if (rseg.space != &space) + if (rseg.space != space) continue; ut_ad(!rseg.is_referenced()); @@ -724,7 +803,7 @@ not_free: possibly before this server had been started up. */ dberr_t err; - buf_block_t *rblock= trx_rseg_header_create(&space, + buf_block_t *rblock= trx_rseg_header_create(space, &rseg - trx_sys.rseg_array, trx_sys.get_max_trx_id(), &mtr, &err); @@ -737,7 +816,7 @@ not_free: rseg.reinit(rblock->page.id().page_no()); } - mtr.commit_shrink(space, size); + mtr.commit_shrink(*space, size); /* No mutex; this is only updated by the purge coordinator. */ export_vars.innodb_undo_truncations++; @@ -759,10 +838,10 @@ not_free: log_buffer_flush_to_disk(); DBUG_SUICIDE();); - sql_print_information("InnoDB: Truncated %s", file->name); - purge_sys.truncate.last= purge_sys.truncate.current; - ut_ad(&space == purge_sys.truncate.current); - purge_sys.truncate.current= nullptr; + sql_print_information("InnoDB: Truncated %s", file_name); + ut_ad(space == purge_sys.truncate_undo_space.current); + purge_sys.truncate_undo_space.current= nullptr; + purge_sys.truncate_undo_space.last= space->id - srv_undo_space_id_start; } } diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index def47686da2..ccc68dfeef7 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -907,15 +907,13 @@ trx_undo_truncate_start( trx_undo_rec_t* last_rec; mtr_t mtr; + ut_ad(rseg->is_persistent()); + if (!limit) { return DB_SUCCESS; } loop: - mtr_start(&mtr); - - if (!rseg->is_persistent()) { - mtr.set_log_mode(MTR_LOG_NO_REDO); - } + mtr.start(); dberr_t err; const buf_block_t* undo_page; From 8e337e016ff882862d4d2f32488b5142370ff8da Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 17 Jan 2024 10:45:05 +0100 Subject: [PATCH 037/121] new WolfSSL v5.6.6-stable --- extra/wolfssl/user_settings.h.in | 5 +++++ extra/wolfssl/wolfssl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/extra/wolfssl/user_settings.h.in b/extra/wolfssl/user_settings.h.in index 425f6f154b9..baa64fcdfbe 100644 --- a/extra/wolfssl/user_settings.h.in +++ b/extra/wolfssl/user_settings.h.in @@ -28,6 +28,11 @@ #define NO_OLD_TIMEVAL_NAME #define HAVE_SECURE_RENEGOTIATION #define HAVE_EXTENDED_MASTER +/* + Following is workaround about a WolfSSL 5.6.6 bug. + The bug is about undefined sessionCtxSz during compilation. +*/ +#define WOLFSSL_SESSION_ID_CTX /* TLSv1.3 definitions (all needed to build) */ #define WOLFSSL_TLS13 diff --git a/extra/wolfssl/wolfssl b/extra/wolfssl/wolfssl index 3b3c175af0e..66596ad9e1d 160000 --- a/extra/wolfssl/wolfssl +++ b/extra/wolfssl/wolfssl @@ -1 +1 @@ -Subproject commit 3b3c175af0e993ffaae251871421e206cc41963f +Subproject commit 66596ad9e1d7efa8479656872cf09c9c1870a02e From 6a514ef6727c1c1102f57554cdf28aaa775d210a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 Jan 2024 12:50:44 +0200 Subject: [PATCH 038/121] MDEV-30940: Try to fix the test --- mysql-test/suite/innodb/r/lock_move_wait_lock_race.result | 3 ++- mysql-test/suite/innodb/t/lock_move_wait_lock_race.test | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result b/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result index 572fbc9b1d1..c78102d9c3b 100644 --- a/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result +++ b/mysql-test/suite/innodb/r/lock_move_wait_lock_race.result @@ -1,4 +1,5 @@ -CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) ENGINE=InnoDB; +CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) +STATS_PERSISTENT=0 ENGINE=InnoDB; INSERT INTO t VALUES (10, "0123456789"); connection default; BEGIN; diff --git a/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test b/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test index 3a04c7127c8..0f88f8d9d0f 100644 --- a/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test +++ b/mysql-test/suite/innodb/t/lock_move_wait_lock_race.test @@ -3,7 +3,8 @@ --source include/have_debug.inc --source include/have_debug_sync.inc -CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) ENGINE=InnoDB; +CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) +STATS_PERSISTENT=0 ENGINE=InnoDB; INSERT INTO t VALUES (10, "0123456789"); --connection default From 615f4a8c9e6679322c4b788d8bbc573e53267f05 Mon Sep 17 00:00:00 2001 From: Robin Newhouse Date: Thu, 7 Dec 2023 00:16:28 +0000 Subject: [PATCH 039/121] MDEV-32587 Allow json exponential notation starting with zero Modify the NS_ZERO state in the JSON number parser to allow exponential notation with a zero coefficient (e.g. 0E-4). The NS_ZERO state transition on 'E' was updated to move to the NS_EX state rather than returning a syntax error. Similar change was made for the NS_ZE1 (negative zero) starter state. This allows accepted number grammar to include cases like: - 0E4 - -0E-10 which were previously disallowed. Numeric parsing remains the same for all other states. Test cases are added to func_json.test to validate parsing for various exponential numbers starting with zero coefficients. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services. --- mysql-test/main/func_json.result | 33 ++++++++++++++++++++++++++++++++ mysql-test/main/func_json.test | 16 ++++++++++++++++ strings/json_lib.c | 6 +++--- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 4b42c1def16..5d80ad2a7fc 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -1300,5 +1300,38 @@ f foo SET @@COLLATION_CONNECTION= @old_collation_connection; # +# MDEV-32587 JSON_VALID fail to validate integer zero in scientific notation +# +select JSON_VALID(' {"number": 1E-4}'); +JSON_VALID(' {"number": 1E-4}') +1 +select JSON_VALID(' {"number": 0E-4}'); +JSON_VALID(' {"number": 0E-4}') +1 +select JSON_VALID(' {"number": 0.0}'); +JSON_VALID(' {"number": 0.0}') +1 +select JSON_VALID(' {"number": 0.1E-4}'); +JSON_VALID(' {"number": 0.1E-4}') +1 +select JSON_VALID(' {"number": 0e-4}'); +JSON_VALID(' {"number": 0e-4}') +1 +select JSON_VALID(' {"number": -0E-4}'); +JSON_VALID(' {"number": -0E-4}') +1 +select JSON_VALUE(' {"number": 0E-4}', '$.number'); +JSON_VALUE(' {"number": 0E-4}', '$.number') +0E-4 +select JSON_VALID(' {"number": 00E-4}'); +JSON_VALID(' {"number": 00E-4}') +0 +select JSON_VALID(' {"number": 01E-4}'); +JSON_VALID(' {"number": 01E-4}') +0 +select JSON_VALID(' {"number": 0E-4.0}'); +JSON_VALID(' {"number": 0E-4.0}') +0 +# # End of 10.4 tests # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index eed433aa118..a271dac3dca 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -840,6 +840,22 @@ SELECT JSON_VALUE('["foo"]', '$**[0]') AS f; SET @@COLLATION_CONNECTION= @old_collation_connection; +--echo # +--echo # MDEV-32587 JSON_VALID fail to validate integer zero in scientific notation +--echo # +# Passing +select JSON_VALID(' {"number": 1E-4}'); +select JSON_VALID(' {"number": 0E-4}'); +select JSON_VALID(' {"number": 0.0}'); +select JSON_VALID(' {"number": 0.1E-4}'); +select JSON_VALID(' {"number": 0e-4}'); +select JSON_VALID(' {"number": -0E-4}'); +select JSON_VALUE(' {"number": 0E-4}', '$.number'); +# Failing +select JSON_VALID(' {"number": 00E-4}'); +select JSON_VALID(' {"number": 01E-4}'); +select JSON_VALID(' {"number": 0E-4.0}'); + --echo # --echo # End of 10.4 tests --echo # diff --git a/strings/json_lib.c b/strings/json_lib.c index 781172f0340..3b9b169e2d1 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -467,12 +467,12 @@ enum json_num_states { static int json_num_states[NS_NUM_STATES][N_NUM_CLASSES]= { -/* - + 0 1..9 POINT E END_OK ERROR */ +/* - + 0 1..9 POINT E END_OK ERROR */ /*OK*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*GO*/ { NS_GO1, JE_SYN, NS_Z, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*GO1*/ { JE_SYN, JE_SYN, NS_Z1, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, -/*ZERO*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, -/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, +/*ZERO*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, +/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, /*INT*/ { JE_SYN, JE_SYN, NS_INT, NS_INT, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, /*FRAC*/ { JE_SYN, JE_SYN, NS_FRAC, NS_FRAC,JE_SYN, NS_EX, NS_OK, JE_BAD_CHR }, /*EX*/ { NS_EX, NS_EX, NS_EX1, NS_EX1, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, From 03854a84abf71c734f7a1c49897e3ef010a3fe4e Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 17 Jan 2024 22:26:12 +0100 Subject: [PATCH 040/121] MDEV-32374 Improve lsn_lock. Also use futex-like on Windows Upon further benchmarking, it turns out srw_mutex performs overall slightly better with WaitOnAddress than CRITICAL_SECTION. --- storage/innobase/include/log0log.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 58213856c79..54851ca0a65 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -180,9 +180,6 @@ private: /* On ARM, we do more spinning */ typedef srw_spin_lock log_rwlock; typedef pthread_mutex_wrapper log_lsn_lock; -#elif defined _WIN32 - typedef srw_lock log_rwlock; - typedef pthread_mutex_wrapper log_lsn_lock; #else typedef srw_lock log_rwlock; typedef srw_mutex log_lsn_lock; From c95ba183d2528ea33a04210d9f46dabde36e46e3 Mon Sep 17 00:00:00 2001 From: Sophist <3001893+Sophist-UK@users.noreply.github.com> Date: Thu, 21 Dec 2023 20:08:32 +0000 Subject: [PATCH 041/121] Replace incorrect message `mariadb-safe` with correct `mariadbd-safe` --- scripts/mysql_install_db.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index bfca263478b..3bc4d63b7df 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -657,7 +657,7 @@ then then echo echo "You can start the MariaDB daemon with:" - echo "cd '$basedir' ; $bindir/mariadb-safe --datadir='$ldata'" + echo "cd '$basedir' ; $bindir/mariadbd-safe --datadir='$ldata'" echo echo "You can test the MariaDB daemon with mysql-test-run.pl" echo "cd '$basedir/@INSTALL_MYSQLTESTDIR@' ; perl mariadb-test-run.pl" From f63045b11950c0659b7e3dcf66996be0422d76dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 18 Jan 2024 10:14:21 +0200 Subject: [PATCH 042/121] MDEV-33213 fixup: GCC 5 -Wconversion --- storage/innobase/trx/trx0purge.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 30cce66697f..7eaedabdd90 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -420,7 +420,7 @@ void purge_sys_t::rseg_enable(trx_rseg_t &rseg) /* If innodb_undo_tablespaces>0, the rollback segment 0 (which always resides in the system tablespace) will never be used; @see trx_assign_rseg_low() */ - if (!(skipped%= TRX_SYS_N_RSEGS) && srv_undo_tablespaces) + if (!(skipped&= (TRX_SYS_N_RSEGS - 1)) && srv_undo_tablespaces) skipped++; skipped_rseg= skipped; } From ee1407f74dc063a851e1fe41b980ccc1ce4c01bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 18 Jan 2024 11:00:27 +0200 Subject: [PATCH 043/121] MDEV-32268: GNU libc posix_fallocate() may be extremely slow os_file_set_size(): Let us invoke the Linux system call fallocate(2) directly, because the GNU libc posix_fallocate() implements a fallback that writes to the file 1 byte every 4096 or fewer bytes. In one environment, invoking fallocate() directly would lead to 4 times the file growth rate during ALTER TABLE. Presumably, what happened was that the NFS server used a smaller allocation block size than 4096 bytes and therefore created a heavily fragmented sparse file when posix_fallocate() was used. For example, extending a file by 4 MiB would create 1,024 file fragments. When the file is actually being written to with data, it would be "unsparsed". The built-in EOPNOTSUPP fallback in os_file_set_size() writes a buffer of 1 MiB of NUL bytes. This was always used on musl libc and other Linux implementations of posix_fallocate(). --- storage/innobase/os/os0file.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 71e48da0dec..075f838ebb1 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -4934,8 +4934,18 @@ fallback: return true; } current_size &= ~4095ULL; +# ifdef __linux__ + if (!fallocate(file, 0, current_size, + size - current_size)) { + err = 0; + break; + } + + err = errno; +# else err = posix_fallocate(file, current_size, size - current_size); +# endif } } while (err == EINTR && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED); From a2eb664f08422b59ee7ea16e4739561c8c2c17bb Mon Sep 17 00:00:00 2001 From: Sophist <3001893+Sophist-UK@users.noreply.github.com> Date: Thu, 21 Dec 2023 20:08:32 +0000 Subject: [PATCH 044/121] Replace incorrect message `mariadb-safe` with correct `mariadbd-safe` --- scripts/mysql_install_db.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 9b4d8e6be96..a860feeb80e 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -701,7 +701,7 @@ then then echo echo "You can start the MariaDB daemon with:" - echo "cd '$basedir' ; $bindir/mariadb-safe --datadir='$ldata'" + echo "cd '$basedir' ; $bindir/mariadbd-safe --datadir='$ldata'" echo echo "You can test the MariaDB daemon with mariadb-test-run.pl" echo "cd '$basedir/@INSTALL_MYSQLTESTDIR@' ; perl mariadb-test-run.pl" From ac774a2656fe03f1a3ebcd5859865e9cbd3ca817 Mon Sep 17 00:00:00 2001 From: Sophist <3001893+Sophist-UK@users.noreply.github.com> Date: Thu, 21 Dec 2023 20:09:29 +0000 Subject: [PATCH 045/121] Replace incorrect message `mariadb-safe` with correct `mariadbd-safe` --- scripts/mysqld_safe.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 0802cf0614a..44dfe5e4935 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -42,7 +42,7 @@ trap '' 1 2 3 15 # we shouldn't let anyone kill us case "$0" in *mysqld_safe) - echo "$0: Deprecated program name. It will be removed in a future release, use 'mariadb-safe' instead" 1>&2 + echo "$0: Deprecated program name. It will be removed in a future release, use 'mariadbd-safe' instead" 1>&2 ;; esac From a6290a5bc5f3cba096854595c354d19d9267743d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 15 Jan 2024 09:04:19 +0200 Subject: [PATCH 046/121] MDEV-33095 innodb_flush_method=O_DIRECT creates excessive errors on Solaris The directio(3C) function on Solaris is supported on NFS and UFS while the majority of users should be on ZFS, which is a copy-on-write file system that implements transparent compression and therefore cannot support unbuffered I/O. Let us remove the call to directio() and simply treat innodb_flush_method=O_DIRECT in the same way as the previous default value innodb_flush_method=fsync on Solaris. Also, let us remove some dead code around calls to os_file_set_nocache() on platforms where fcntl(2) is not usable with O_DIRECT. On IBM AIX, O_DIRECT is not documented for fcntl(2), only for open(2). --- cmake/os/AIX.cmake | 3 ++ cmake/os/SunOS.cmake | 4 +++ cmake/os/WindowsCache.cmake | 1 + config.h.cmake | 1 + configure.cmake | 1 + extra/mariabackup/fil_cur.cc | 2 ++ mysql-test/mariadb-test-run.pl | 2 +- storage/innobase/fil/fil0fil.cc | 12 ++++++-- storage/innobase/fil/fil0pagecompress.cc | 5 ---- storage/innobase/handler/ha_innodb.cc | 8 ++--- storage/innobase/include/os0file.h | 10 ++++--- storage/innobase/os/os0file.cc | 37 ++++++++++-------------- storage/innobase/row/row0merge.cc | 3 +- 13 files changed, 50 insertions(+), 39 deletions(-) diff --git a/cmake/os/AIX.cmake b/cmake/os/AIX.cmake index 299b79198c6..7513c4f42c2 100644 --- a/cmake/os/AIX.cmake +++ b/cmake/os/AIX.cmake @@ -34,5 +34,8 @@ ELSE() SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -maix64 -pthread -mcmodel=large") ENDIF() +# fcntl(fd, F_SETFL, O_DIRECT) is not supported; O_DIRECT is an open(2) flag +SET(HAVE_FCNTL_DIRECT 0 CACHE INTERNAL "") + # make it WARN by default, not AUTO (that implies -Werror) SET(MYSQL_MAINTAINER_MODE "WARN" CACHE STRING "Enable MariaDB maintainer-specific warnings. One of: NO (warnings are disabled) WARN (warnings are enabled) ERR (warnings are errors) AUTO (warnings are errors in Debug only)") diff --git a/cmake/os/SunOS.cmake b/cmake/os/SunOS.cmake index 3a9d2dccb87..3d99d34789a 100644 --- a/cmake/os/SunOS.cmake +++ b/cmake/os/SunOS.cmake @@ -17,6 +17,10 @@ INCLUDE(CheckSymbolExists) INCLUDE(CheckCSourceRuns) INCLUDE(CheckCSourceCompiles) +# fcntl(fd, F_SETFL, O_DIRECT) is not supported, +# and directio(3C) would only work on UFS or NFS, not ZFS. +SET(HAVE_FCNTL_DIRECT 0 CACHE INTERNAL "") + # Enable 64 bit file offsets SET(_FILE_OFFSET_BITS 64) diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index c1048661aaa..ceb4262730f 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -44,6 +44,7 @@ SET(HAVE_EXECINFO_H CACHE INTERNAL "") SET(HAVE_FCHMOD CACHE INTERNAL "") SET(HAVE_FCNTL CACHE INTERNAL "") SET(HAVE_FCNTL_H 1 CACHE INTERNAL "") +SET(HAVE_FCNTL_DIRECT 0 CACHE INTERNAL "") SET(HAVE_FCNTL_NONBLOCK CACHE INTERNAL "") SET(HAVE_FDATASYNC CACHE INTERNAL "") SET(HAVE_DECL_FDATASYNC CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index 5075561d6e0..9b89d647543 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -30,6 +30,7 @@ #cmakedefine HAVE_DLFCN_H 1 #cmakedefine HAVE_EXECINFO_H 1 #cmakedefine HAVE_FCNTL_H 1 +#cmakedefine HAVE_FCNTL_DIRECT 1 #cmakedefine HAVE_FENV_H 1 #cmakedefine HAVE_FLOAT_H 1 #cmakedefine HAVE_FNMATCH_H 1 diff --git a/configure.cmake b/configure.cmake index cce8c4f611b..2d6f6183914 100644 --- a/configure.cmake +++ b/configure.cmake @@ -705,6 +705,7 @@ CHECK_SYMBOL_EXISTS(O_NONBLOCK "unistd.h;fcntl.h" HAVE_FCNTL_NONBLOCK) IF(NOT HAVE_FCNTL_NONBLOCK) SET(NO_FCNTL_NONBLOCK 1) ENDIF() +CHECK_SYMBOL_EXISTS(O_DIRECT "fcntl.h" HAVE_FCNTL_DIRECT) # # Test for how the C compiler does inline, if at all diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 8820ce40c2b..ce36240fb70 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -199,11 +199,13 @@ xb_fil_cur_open( return(XB_FIL_CUR_SKIP); } +#ifdef HAVE_FCNTL_DIRECT if (srv_file_flush_method == SRV_O_DIRECT || srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC) { os_file_set_nocache(cursor->file, node->name, "OPEN"); } +#endif posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL); diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 96fcd96c1fa..2750e10ecf5 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -4506,7 +4506,7 @@ sub extract_warning_lines ($$) { qr|InnoDB: io_setup\(\) failed with EAGAIN|, qr|io_uring_queue_init\(\) failed with|, qr|InnoDB: liburing disabled|, - qr/InnoDB: Failed to set (O_DIRECT|DIRECTIO_ON) on file/, + qr/InnoDB: Failed to set O_DIRECT on file/, qr|setrlimit could not change the size of core files to 'infinity';|, qr|feedback plugin: failed to retrieve the MAC address|, qr|Plugin 'FEEDBACK' init function returned error|, diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 34748199c0d..58598ec5581 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -357,8 +357,9 @@ static bool fil_node_open_file_low(fil_node_t *node) ut_ad(!node->is_open()); ut_ad(node->space->is_closing()); mysql_mutex_assert_owner(&fil_system.mutex); - ulint type; static_assert(((UNIV_ZIP_SIZE_MIN >> 1) << 3) == 4096, "compatibility"); +#if defined _WIN32 || defined HAVE_FCNTL_DIRECT + ulint type; switch (FSP_FLAGS_GET_ZIP_SSIZE(node->space->flags)) { case 1: case 2: @@ -367,6 +368,9 @@ static bool fil_node_open_file_low(fil_node_t *node) default: type= OS_DATA_FILE; } +#else + constexpr auto type= OS_DATA_FILE; +#endif for (;;) { @@ -1937,9 +1941,10 @@ fil_ibd_create( mtr.commit(); log_write_up_to(mtr.commit_lsn(), true); - ulint type; static_assert(((UNIV_ZIP_SIZE_MIN >> 1) << 3) == 4096, "compatibility"); +#if defined _WIN32 || defined HAVE_FCNTL_DIRECT + ulint type; switch (FSP_FLAGS_GET_ZIP_SSIZE(flags)) { case 1: case 2: @@ -1948,6 +1953,9 @@ fil_ibd_create( default: type = OS_DATA_FILE; } +#else + constexpr auto type = OS_DATA_FILE; +#endif file = os_file_create( innodb_data_file_key, path, diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 3d7c65eb01f..825df9cfe00 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -49,11 +49,6 @@ Updated 14/02/2015 #include "buf0lru.h" #include "ibuf0ibuf.h" #include "zlib.h" -#ifdef __linux__ -#include -#include -#include -#endif #include "row0mysql.h" #ifdef HAVE_LZ4 #include "lz4.h" diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index af556d65695..5436956479a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4102,7 +4102,7 @@ static int innodb_init_params() data_mysql_default_charset_coll = (ulint) default_charset_info->number; -#ifndef _WIN32 +#ifdef HAVE_FCNTL_DIRECT if (srv_use_atomic_writes && my_may_have_atomic_write) { /* Force O_DIRECT on Unixes (on Windows writes are always @@ -4134,9 +4134,7 @@ static int innodb_init_params() } #endif -#ifndef _WIN32 - ut_ad(srv_file_flush_method <= SRV_O_DIRECT_NO_FSYNC); -#else +#ifdef _WIN32 switch (srv_file_flush_method) { case SRV_ALL_O_DIRECT_FSYNC + 1 /* "async_unbuffered"="unbuffered" */: srv_file_flush_method = SRV_ALL_O_DIRECT_FSYNC; @@ -4147,6 +4145,8 @@ static int innodb_init_params() default: ut_ad(srv_file_flush_method <= SRV_ALL_O_DIRECT_FSYNC); } +#else + ut_ad(srv_file_flush_method <= SRV_O_DIRECT_NO_FSYNC); #endif innodb_buffer_pool_size_init(); diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index c0db3b0d752..e0f398301e3 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -151,9 +151,11 @@ static const ulint OS_FILE_NORMAL = 62; /* @} */ /** Types for file create @{ */ -static const ulint OS_DATA_FILE = 100; -static const ulint OS_LOG_FILE = 101; -static const ulint OS_DATA_FILE_NO_O_DIRECT = 103; +static constexpr ulint OS_DATA_FILE = 100; +static constexpr ulint OS_LOG_FILE = 101; +#if defined _WIN32 || defined HAVE_FCNTL_DIRECT +static constexpr ulint OS_DATA_FILE_NO_O_DIRECT = 103; +#endif /* @} */ /** Error codes from os_file_get_last_error @{ */ @@ -382,7 +384,7 @@ os_file_create_simple_no_error_handling_func( bool* success) MY_ATTRIBUTE((warn_unused_result)); -#ifdef _WIN32 +#ifndef HAVE_FCNTL_DIRECT #define os_file_set_nocache(fd, file_name, operation_name) do{}while(0) #else /** Tries to disable OS caching on an opened file descriptor. diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 7628939f2dd..014a9eb632f 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -970,7 +970,7 @@ os_file_create_simple_func( *success = false; int create_flag; - const char* mode_str = NULL; + const char* mode_str __attribute__((unused)); ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); ut_a(!(create_mode & OS_FILE_ON_ERROR_NO_EXIT)); @@ -1046,12 +1046,14 @@ os_file_create_simple_func( } while (retry); +#ifdef HAVE_FCNTL_DIRECT /* This function is always called for data files, we should disable OS caching (O_DIRECT) here as we do in os_file_create_func(), so we open the same file in the same mode, see man page of open(2). */ if (!srv_read_only_mode && *success) { os_file_set_nocache(file, name, mode_str); } +#endif #ifndef _WIN32 if (!read_only @@ -1137,7 +1139,7 @@ os_file_create_func( ); int create_flag; - const char* mode_str = NULL; + const char* mode_str __attribute__((unused)); on_error_no_exit = create_mode & OS_FILE_ON_ERROR_NO_EXIT ? true : false; @@ -1179,9 +1181,13 @@ os_file_create_func( return(OS_FILE_CLOSED); } +#if defined _WIN32 || defined HAVE_FCNTL_DIRECT ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE || type == OS_DATA_FILE_NO_O_DIRECT); +#else + ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE); +#endif ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL); @@ -1224,6 +1230,7 @@ os_file_create_func( } while (retry); +#ifdef HAVE_FCNTL_DIRECT /* We disable OS caching (O_DIRECT) only on data files */ if (!read_only && *success @@ -1231,6 +1238,7 @@ os_file_create_func( && type != OS_DATA_FILE_NO_O_DIRECT) { os_file_set_nocache(file, name, mode_str); } +#endif #ifndef _WIN32 if (!read_only @@ -2147,12 +2155,14 @@ os_file_create_func( } break; +#if defined _WIN32 || defined HAVE_FCNTL_DIRECT case SRV_O_DIRECT_NO_FSYNC: case SRV_O_DIRECT: if (type != OS_DATA_FILE) { break; } /* fall through */ +#endif case SRV_ALL_O_DIRECT_FSYNC: /*Traditional Windows behavior, no buffering for any files.*/ if (type != OS_DATA_FILE_NO_O_DIRECT) { @@ -3037,17 +3047,14 @@ os_file_handle_error_cond_exit( return(false); } -#ifndef _WIN32 +#ifdef HAVE_FCNTL_DIRECT /** Tries to disable OS caching on an opened file descriptor. @param[in] fd file descriptor to alter @param[in] file_name file name, used in the diagnostic message @param[in] name "open" or "create"; used in the diagnostic message */ void -os_file_set_nocache( - int fd MY_ATTRIBUTE((unused)), - const char* file_name MY_ATTRIBUTE((unused)), - const char* operation_name MY_ATTRIBUTE((unused))) +os_file_set_nocache(int fd, const char *file_name, const char *operation_name) { const auto innodb_flush_method = srv_file_flush_method; switch (innodb_flush_method) { @@ -3058,18 +3065,6 @@ os_file_set_nocache( return; } - /* some versions of Solaris may not have DIRECTIO_ON */ -#if defined(__sun__) && defined(DIRECTIO_ON) - if (directio(fd, DIRECTIO_ON) == -1) { - int errno_save = errno; - - ib::error() - << "Failed to set DIRECTIO_ON on file " - << file_name << "; " << operation_name << ": " - << strerror(errno_save) << "," - " continuing anyway."; - } -#elif defined(O_DIRECT) if (fcntl(fd, F_SETFL, O_DIRECT) == -1) { int errno_save = errno; static bool warning_message_printed = false; @@ -3088,10 +3083,8 @@ os_file_set_nocache( << ", continuing anyway."; } } -#endif /* defined(__sun__) && defined(DIRECTIO_ON) */ } - -#endif /* _WIN32 */ +#endif /* HAVE_FCNTL_DIRECT */ /** Check if the file system supports sparse files. @param fh file handle diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 178c2836c7c..c5ac548c768 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -4193,13 +4193,14 @@ row_merge_file_create( merge_file->fd = row_merge_file_create_low(path); merge_file->offset = 0; merge_file->n_rec = 0; - +#ifdef HAVE_FCNTL_DIRECT if (merge_file->fd != OS_FILE_CLOSED) { if (srv_disable_sort_file_cache) { os_file_set_nocache(merge_file->fd, "row0merge.cc", "sort"); } } +#endif return(merge_file->fd); } From 2ef01d003483edd01ff1c524b6e5f52238c7abec Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Sat, 30 Dec 2023 19:42:10 -0500 Subject: [PATCH 047/121] wsrep scripts fixes for working on OpenBSD --- scripts/wsrep_sst_common.sh | 6 +++--- scripts/wsrep_sst_rsync.sh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 4e177073872..63d2d4ef6d1 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -1166,9 +1166,9 @@ is_local_ip() # the domain name check: if [ "${2:-0}" -eq 0 ]; then # We consider all the names of a given host to be local addresses: - [ "$1" = "$(hostname -s)" -o \ - "$1" = "$(hostname -f)" -o \ - "$1" = "$(hostname -d)" ] && return 0 + [ "$1" = "$(hostname -s 2>/dev/null)" -o \ + "$1" = "$(hostname -f 2>/dev/null)" -o \ + "$1" = "$(hostname -d 2>/dev/null)" ] && return 0 fi # If the address contains anything other than digits # and separators, it is not a local address: diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index ade9bb491e5..3dc5da7a48e 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -475,9 +475,9 @@ EOF # Preparing binlog files for transfer: wsrep_log_info "Preparing binlog files for transfer:" tar_type=0 - if tar --help | grep -qw -F -- '--transform'; then + if tar --help 2>/dev/null | grep -qw -F -- '--transform'; then tar_type=1 - elif tar --version | grep -qw -E '^bsdtar'; then + elif tar --version 2>/dev/null | grep -qw -E '^bsdtar'; then tar_type=2 fi if [ $tar_type -eq 2 ]; then @@ -980,7 +980,7 @@ EOF fi # Extracting binlog files: wsrep_log_info "Extracting binlog files:" - if tar --version | grep -qw -E '^bsdtar'; then + if tar --version 2>/dev/null | grep -qw -E '^bsdtar'; then tar -tf "$BINLOG_TAR_FILE" > "$tmpfile" && \ tar -xvf "$BINLOG_TAR_FILE" > /dev/null || RC=$? else From 82e8633420bbb0104a3242db4408ecef71932cac Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 19 Jan 2024 15:24:19 +1100 Subject: [PATCH 048/121] innodb: IO Error message missing space Noted by Susmeet Khaire - thanks. --- storage/innobase/os/os0file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 014a9eb632f..3aede37909d 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -3454,7 +3454,7 @@ static void write_io_callback(void *c) if (UNIV_UNLIKELY(cb->m_err != 0)) ib::info () << "IO Error: " << cb->m_err - << "during write of " + << " during write of " << cb->m_len << " bytes, for file " << request.node->name << "(" << cb->m_fh << "), returned " << cb->m_ret_len; From 16f2f8e5a7aa28c4bd4720f3281f8d1f1d06ba5b Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 17 Jan 2024 20:32:51 +0100 Subject: [PATCH 049/121] new CC 3.3 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 458a4396b44..26cef16b25f 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 458a4396b443dcefedcf464067560078aa09d8b4 +Subproject commit 26cef16b25f01c1b159b0c73e3f6d9bcfcac90d5 From d34479dc664d4cbd4e9dad6b0f92d7c8e55595d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 19 Jan 2024 12:40:16 +0200 Subject: [PATCH 050/121] MDEV-33053 InnoDB LRU flushing does not run before running out of buffer pool buf_flush_LRU(): Display a warning if no pages could be evicted and no writes initiated. buf_pool_t::need_LRU_eviction(): Renamed from buf_pool_t::ran_out(). Check if the amount of free pages is smaller than innodb_lru_scan_depth instead of checking if it is 0. buf_flush_page_cleaner(): For the final LRU flush after a checkpoint flush, use a "budget" of innodb_io_capacity_max, like we do in the case when we are not in "furious" checkpoint flushing. Co-developed by: Debarun Banerjee Reviewed by: Debarun Banerjee Tested by: Matthias Leich --- storage/innobase/buf/buf0flu.cc | 71 +++++++++++++++++++++++------- storage/innobase/buf/buf0lru.cc | 31 +++++++++---- storage/innobase/include/buf0buf.h | 9 ++-- 3 files changed, 82 insertions(+), 29 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index f07ecedf535..ca9c71938c1 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1797,6 +1797,28 @@ ulint buf_flush_LRU(ulint max_n, bool evict) buf_pool.try_LRU_scan= true; pthread_cond_broadcast(&buf_pool.done_free); } + else if (!pages && !buf_pool.try_LRU_scan && + buf_pool.LRU_warned.test_and_set(std::memory_order_acquire)) + { + /* For example, with the minimum innodb_buffer_pool_size=5M and + the default innodb_page_size=16k there are only a little over 316 + pages in the buffer pool. The buffer pool can easily be exhausted + by a workload of some dozen concurrent connections. The system could + reach a deadlock like the following: + + (1) Many threads are waiting in buf_LRU_get_free_block() + for buf_pool.done_free. + (2) Some threads are waiting for a page latch which is held by + another thread that is waiting in buf_LRU_get_free_block(). + (3) This thread is the only one that could make progress, but + we fail to do so because all the pages that we scanned are + buffer-fixed or latched by some thread. */ + sql_print_warning("InnoDB: Could not free any blocks in the buffer pool!" + " %zu blocks are in use and %zu free." + " Consider increasing innodb_buffer_pool_size.", + UT_LIST_GET_LEN(buf_pool.LRU), + UT_LIST_GET_LEN(buf_pool.free)); + } return pages; } @@ -2287,6 +2309,16 @@ func_exit: goto func_exit; } +TPOOL_SUPPRESS_TSAN +bool buf_pool_t::need_LRU_eviction() const +{ + /* try_LRU_scan==false means that buf_LRU_get_free_block() is waiting + for buf_flush_page_cleaner() to evict some blocks */ + return UNIV_UNLIKELY(!try_LRU_scan || + (UT_LIST_GET_LEN(LRU) > BUF_LRU_MIN_LEN && + UT_LIST_GET_LEN(free) < srv_LRU_scan_depth / 2)); +} + /** page_cleaner thread tasked with flushing dirty pages from the buffer pools. As of now we'll have only one coordinator. */ static void buf_flush_page_cleaner() @@ -2319,21 +2351,24 @@ static void buf_flush_page_cleaner() } mysql_mutex_lock(&buf_pool.flush_list_mutex); - if (buf_pool.ran_out()) - goto no_wait; - else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) - break; + if (!buf_pool.need_LRU_eviction()) + { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) + break; - if (buf_pool.page_cleaner_idle() && - (!UT_LIST_GET_LEN(buf_pool.flush_list) || - srv_max_dirty_pages_pct_lwm == 0.0)) - /* We are idle; wait for buf_pool.page_cleaner_wakeup() */ - my_cond_wait(&buf_pool.do_flush_list, - &buf_pool.flush_list_mutex.m_mutex); - else - my_cond_timedwait(&buf_pool.do_flush_list, - &buf_pool.flush_list_mutex.m_mutex, &abstime); - no_wait: + if (buf_pool.page_cleaner_idle() && + (!UT_LIST_GET_LEN(buf_pool.flush_list) || + srv_max_dirty_pages_pct_lwm == 0.0)) + { + buf_pool.LRU_warned.clear(std::memory_order_release); + /* We are idle; wait for buf_pool.page_cleaner_wakeup() */ + my_cond_wait(&buf_pool.do_flush_list, + &buf_pool.flush_list_mutex.m_mutex); + } + else + my_cond_timedwait(&buf_pool.do_flush_list, + &buf_pool.flush_list_mutex.m_mutex, &abstime); + } set_timespec(abstime, 1); lsn_limit= buf_flush_sync_lsn; @@ -2365,7 +2400,7 @@ static void buf_flush_page_cleaner() } while (false); - if (!buf_pool.ran_out()) + if (!buf_pool.need_LRU_eviction()) continue; mysql_mutex_lock(&buf_pool.flush_list_mutex); oldest_lsn= buf_pool.get_oldest_modification(0); @@ -2394,7 +2429,7 @@ static void buf_flush_page_cleaner() if (oldest_lsn >= soft_lsn_limit) buf_flush_async_lsn= soft_lsn_limit= 0; } - else if (buf_pool.ran_out()) + else if (buf_pool.need_LRU_eviction()) { buf_pool.page_cleaner_set_idle(false); buf_pool.n_flush_inc(); @@ -2509,9 +2544,11 @@ static void buf_flush_page_cleaner() MONITOR_FLUSH_ADAPTIVE_PAGES, n_flushed); } - else if (buf_flush_async_lsn <= oldest_lsn) + else if (buf_flush_async_lsn <= oldest_lsn && + !buf_pool.need_LRU_eviction()) goto check_oldest_and_set_idle; + n= srv_max_io_capacity; n= n >= n_flushed ? n - n_flushed : 0; goto LRU_flush; } diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index b80b99a9b12..ce37209f154 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -60,10 +60,6 @@ static constexpr ulint BUF_LRU_OLD_TOLERANCE = 20; frames in the buffer pool, we set this to TRUE */ static bool buf_lru_switched_on_innodb_mon = false; -/** True if diagnostic message about difficult to find free blocks -in the buffer bool has already printed. */ -static bool buf_lru_free_blocks_error_printed; - /******************************************************************//** These statistics are not 'of' LRU but 'for' LRU. We keep count of I/O and page_zip_decompress() operations. Based on the statistics, @@ -408,6 +404,7 @@ got_mutex: buf_LRU_check_size_of_non_data_objects(); buf_block_t* block; + IF_DBUG(static bool buf_lru_free_blocks_error_printed,); DBUG_EXECUTE_IF("ib_lru_force_no_free_page", if (!buf_lru_free_blocks_error_printed) { n_iterations = 21; @@ -417,9 +414,25 @@ retry: /* If there is a block in the free list, take it */ if ((block = buf_LRU_get_free_only()) != nullptr) { got_block: + const ulint LRU_size = UT_LIST_GET_LEN(buf_pool.LRU); + const ulint available = UT_LIST_GET_LEN(buf_pool.free); + const ulint scan_depth = srv_LRU_scan_depth / 2; + ut_ad(LRU_size <= BUF_LRU_MIN_LEN || available >= scan_depth + || buf_pool.need_LRU_eviction()); + if (!have_mutex) { mysql_mutex_unlock(&buf_pool.mutex); } + + if (UNIV_UNLIKELY(available < scan_depth) + && LRU_size > BUF_LRU_MIN_LEN) { + mysql_mutex_lock(&buf_pool.flush_list_mutex); + if (!buf_pool.page_cleaner_active()) { + buf_pool.page_cleaner_wakeup(true); + } + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + } + block->page.zip.clear(); return block; } @@ -445,10 +458,11 @@ got_block: if ((block = buf_LRU_get_free_only()) != nullptr) { goto got_block; } + const bool wake = buf_pool.need_LRU_eviction(); mysql_mutex_unlock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex); const auto n_flush = buf_pool.n_flush(); - if (!buf_pool.try_LRU_scan) { + if (wake && !buf_pool.page_cleaner_active()) { buf_pool.page_cleaner_wakeup(true); } mysql_mutex_unlock(&buf_pool.flush_list_mutex); @@ -467,9 +481,10 @@ not_found: MONITOR_INC( MONITOR_LRU_GET_FREE_WAITS ); } - if (n_iterations == 21 && !buf_lru_free_blocks_error_printed - && srv_buf_pool_old_size == srv_buf_pool_size) { - buf_lru_free_blocks_error_printed = true; + if (n_iterations == 21 + && srv_buf_pool_old_size == srv_buf_pool_size + && buf_pool.LRU_warned.test_and_set(std::memory_order_acquire)) { + IF_DBUG(buf_lru_free_blocks_error_printed = true,); mysql_mutex_unlock(&buf_pool.mutex); ib::warn() << "Difficult to find free blocks in the buffer pool" " (" << n_iterations << " search iterations)! " diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 5626af17bb7..4986e83cfb9 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1488,10 +1488,8 @@ public: n_chunks_new / 4 * chunks->size; } - /** @return whether the buffer pool has run out */ - TPOOL_SUPPRESS_TSAN - bool ran_out() const - { return UNIV_UNLIKELY(!try_LRU_scan || !UT_LIST_GET_LEN(free)); } + /** @return whether the buffer pool is running low */ + bool need_LRU_eviction() const; /** @return whether the buffer pool is shrinking */ inline bool is_shrinking() const @@ -1811,6 +1809,9 @@ public: Set whenever the free list grows, along with a broadcast of done_free. Protected by buf_pool.mutex. */ Atomic_relaxed try_LRU_scan; + /** Whether we have warned to be running out of buffer pool */ + std::atomic_flag LRU_warned; + /* @} */ /** @name LRU replacement algorithm fields */ From 7e65e3027e7b55d64067ff0bef0dcbc9801fe967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 19 Jan 2024 12:40:32 +0200 Subject: [PATCH 051/121] MDEV-33275 buf_flush_LRU(): mysql_mutex_assert_owner(&buf_pool.mutex) failed In commit a55b951e6082a4ce9a1f2ed5ee176ea7dbbaf1f2 (MDEV-26827) an error was introduced in a rarely executed code path of the buf_flush_page_cleaner() thread. As a result, the function buf_flush_LRU() could be invoked while not holding buf_pool.mutex. Reviewed by: Debarun Banerjee --- storage/innobase/buf/buf0flu.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index ca9c71938c1..21ca288ec23 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -2547,6 +2547,8 @@ static void buf_flush_page_cleaner() else if (buf_flush_async_lsn <= oldest_lsn && !buf_pool.need_LRU_eviction()) goto check_oldest_and_set_idle; + else + mysql_mutex_lock(&buf_pool.mutex); n= srv_max_io_capacity; n= n >= n_flushed ? n - n_flushed : 0; From 21560bee9d6351b6f934a889bed123b548a49bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 19 Jan 2024 12:46:11 +0200 Subject: [PATCH 052/121] Revert "MDEV-32899 InnoDB is holding shared dict_sys.latch while waiting for FOREIGN KEY child table lock on DDL" This reverts commit 569da6a7bab034fc9768af88d8dbc2a8e2944764, commit 768a736174d6caf09df43e84b0c1b9ec52f1a301, and commit ba6bf7ad9e52c1dc31a22a619c17e1bb55b46d5d because of a regression that was filed as MDEV-33104. --- .../perfschema/r/sxlock_func,debug.rdiff | 22 ------- .../suite/perfschema/t/sxlock_func.test | 1 - storage/innobase/dict/dict0dict.cc | 37 ++++-------- storage/innobase/handler/ha_innodb.cc | 37 ++++++++---- storage/innobase/handler/handler0alter.cc | 11 +++- storage/innobase/include/dict0dict.h | 60 +++++++++---------- storage/innobase/include/lock0lock.h | 7 --- storage/innobase/lock/lock0lock.cc | 32 ---------- 8 files changed, 79 insertions(+), 128 deletions(-) delete mode 100644 mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff diff --git a/mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff b/mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff deleted file mode 100644 index 0596810e553..00000000000 --- a/mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff +++ /dev/null @@ -1,22 +0,0 @@ -@@ -7,7 +7,6 @@ - WHERE name LIKE 'wait/synch/rwlock/innodb/%' - AND name!='wait/synch/rwlock/innodb/btr_search_latch' ORDER BY name; - name --wait/synch/rwlock/innodb/dict_operation_lock - wait/synch/rwlock/innodb/fil_space_latch - wait/synch/rwlock/innodb/lock_latch - wait/synch/rwlock/innodb/trx_i_s_cache_lock -@@ -19,11 +18,13 @@ - select name from performance_schema.setup_instruments - where name like "wait/synch/sxlock/%" order by name; - name -+wait/synch/sxlock/innodb/dict_operation_lock - wait/synch/sxlock/innodb/index_tree_rw_lock - SELECT DISTINCT name FROM performance_schema.rwlock_instances - WHERE name LIKE 'wait/synch/sxlock/innodb/%' - ORDER BY name; - name -+wait/synch/sxlock/innodb/dict_operation_lock - wait/synch/sxlock/innodb/index_tree_rw_lock - create table t1(a int) engine=innodb; - begin; diff --git a/mysql-test/suite/perfschema/t/sxlock_func.test b/mysql-test/suite/perfschema/t/sxlock_func.test index 24d0e07ca41..c43adc849d2 100644 --- a/mysql-test/suite/perfschema/t/sxlock_func.test +++ b/mysql-test/suite/perfschema/t/sxlock_func.test @@ -5,7 +5,6 @@ --source include/not_embedded.inc --source include/have_perfschema.inc --source include/have_innodb.inc ---source include/maybe_debug.inc UPDATE performance_schema.setup_instruments SET enabled = 'NO', timed = 'YES'; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index d51ced003e8..a66bd0df510 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -958,12 +958,11 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) if (latch_ex_wait_start.compare_exchange_strong (old, now, std::memory_order_relaxed, std::memory_order_relaxed)) { -#ifdef UNIV_DEBUG - latch.x_lock(SRW_LOCK_ARGS(file, line)); -#else latch.wr_lock(SRW_LOCK_ARGS(file, line)); -#endif latch_ex_wait_start.store(0, std::memory_order_relaxed); + ut_ad(!latch_readers); + ut_ad(!latch_ex); + ut_d(latch_ex= pthread_self()); return; } @@ -978,39 +977,33 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) if (waited > threshold / 4) ib::warn() << "A long wait (" << waited << " seconds) was observed for dict_sys.latch"; -#ifdef UNIV_DEBUG - latch.x_lock(SRW_LOCK_ARGS(file, line)); -#else latch.wr_lock(SRW_LOCK_ARGS(file, line)); -#endif + ut_ad(!latch_readers); + ut_ad(!latch_ex); + ut_d(latch_ex= pthread_self()); } #ifdef UNIV_PFS_RWLOCK ATTRIBUTE_NOINLINE void dict_sys_t::unlock() { -# ifdef UNIV_DEBUG - latch.x_unlock(); -# else + ut_ad(latch_ex == pthread_self()); + ut_ad(!latch_readers); + ut_d(latch_ex= 0); latch.wr_unlock(); -# endif } ATTRIBUTE_NOINLINE void dict_sys_t::freeze(const char *file, unsigned line) { -# ifdef UNIV_DEBUG - latch.s_lock(file, line); -# else latch.rd_lock(file, line); -# endif + ut_ad(!latch_ex); + ut_d(latch_readers++); } ATTRIBUTE_NOINLINE void dict_sys_t::unfreeze() { -# ifdef UNIV_DEBUG - latch.s_unlock(); -# else + ut_ad(!latch_ex); + ut_ad(latch_readers--); latch.rd_unlock(); -# endif } #endif /* UNIV_PFS_RWLOCK */ @@ -4544,11 +4537,7 @@ void dict_sys_t::close() temp_id_hash.free(); unlock(); -#ifdef UNIV_DEBUG - latch.free(); -#else latch.destroy(); -#endif mysql_mutex_destroy(&dict_foreign_err_mutex); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5436956479a..98f3fa0344d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -598,13 +598,7 @@ static PSI_rwlock_info all_innodb_rwlocks[] = # ifdef BTR_CUR_HASH_ADAPT { &btr_search_latch_key, "btr_search_latch", 0 }, # endif - { &dict_operation_lock_key, "dict_operation_lock", -# ifdef UNIV_DEBUG - PSI_RWLOCK_FLAG_SX -# else - 0 -# endif - }, + { &dict_operation_lock_key, "dict_operation_lock", 0 }, { &fil_space_latch_key, "fil_space_latch", 0 }, { &trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0 }, { &trx_purge_latch_key, "trx_purge_latch", 0 }, @@ -13546,7 +13540,14 @@ int ha_innobase::delete_table(const char *name) /* FOREIGN KEY constraints cannot exist on partitioned tables. */; #endif else - err= lock_table_children(table, trx); + { + dict_sys.freeze(SRW_LOCK_CALL); + for (const dict_foreign_t* f : table->referenced_set) + if (dict_table_t* child= f->foreign_table) + if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) + break; + dict_sys.unfreeze(); + } } dict_table_t *table_stats= nullptr, *index_stats= nullptr; @@ -13944,7 +13945,14 @@ int ha_innobase::truncate() dict_table_t *table_stats = nullptr, *index_stats = nullptr; MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; - dberr_t error= lock_table_children(ib_table, trx); + dberr_t error= DB_SUCCESS; + + dict_sys.freeze(SRW_LOCK_CALL); + for (const dict_foreign_t *f : ib_table->referenced_set) + if (dict_table_t *child= f->foreign_table) + if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) + break; + dict_sys.unfreeze(); if (error == DB_SUCCESS) error= lock_table_for_trx(ib_table, trx, LOCK_X); @@ -14135,7 +14143,16 @@ ha_innobase::rename_table( /* There is no need to lock any FOREIGN KEY child tables. */ } else if (dict_table_t *table = dict_table_open_on_name( norm_from, false, DICT_ERR_IGNORE_FK_NOKEY)) { - error = lock_table_children(table, trx); + dict_sys.freeze(SRW_LOCK_CALL); + for (const dict_foreign_t* f : table->referenced_set) { + if (dict_table_t* child = f->foreign_table) { + error = lock_table_for_trx(child, trx, LOCK_X); + if (error != DB_SUCCESS) { + break; + } + } + } + dict_sys.unfreeze(); if (error == DB_SUCCESS) { error = lock_table_for_trx(table, trx, LOCK_X); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index dc5c1f71925..3b892434a67 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -11203,7 +11203,16 @@ ha_innobase::commit_inplace_alter_table( fts_optimize_remove_table(ctx->old_table); } - error = lock_table_children(ctx->old_table, trx); + dict_sys.freeze(SRW_LOCK_CALL); + for (auto f : ctx->old_table->referenced_set) { + if (dict_table_t* child = f->foreign_table) { + error = lock_table_for_trx(child, trx, LOCK_X); + if (error != DB_SUCCESS) { + break; + } + } + } + dict_sys.unfreeze(); if (ctx->new_table->fts) { ut_ad(!ctx->new_table->fts->add_wq); diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index e4fc58007cf..895743be84b 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1316,14 +1316,14 @@ class dict_sys_t /** The my_hrtime_coarse().val of the oldest lock_wait() start, or 0 */ std::atomic latch_ex_wait_start; -#ifdef UNIV_DEBUG - typedef index_lock dict_lock; -#else - typedef srw_lock dict_lock; -#endif - /** the rw-latch protecting the data dictionary cache */ - alignas(CPU_LEVEL1_DCACHE_LINESIZE) dict_lock latch; + alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch; +#ifdef UNIV_DEBUG + /** whether latch is being held in exclusive mode (by any thread) */ + Atomic_relaxed latch_ex; + /** number of S-latch holders */ + Atomic_counter latch_readers; +#endif public: /** Indexes of SYS_TABLE[] */ enum @@ -1491,12 +1491,15 @@ public: } #ifdef UNIV_DEBUG - /** @return whether the current thread is holding the latch */ - bool frozen() const { return latch.have_any(); } - /** @return whether the current thread is holding a shared latch */ - bool frozen_not_locked() const { return latch.have_s(); } + /** @return whether any thread (not necessarily the current thread) + is holding the latch; that is, this check may return false + positives */ + bool frozen() const { return latch_readers || latch_ex; } + /** @return whether any thread (not necessarily the current thread) + is holding a shared latch */ + bool frozen_not_locked() const { return latch_readers; } /** @return whether the current thread holds the exclusive latch */ - bool locked() const { return latch.have_x(); } + bool locked() const { return latch_ex == pthread_self(); } #endif private: /** Acquire the exclusive latch */ @@ -1511,12 +1514,13 @@ public: /** Exclusively lock the dictionary cache. */ void lock(SRW_LOCK_ARGS(const char *file, unsigned line)) { -#ifdef UNIV_DEBUG - ut_ad(!latch.have_any()); - if (!latch.x_lock_try()) -#else - if (!latch.wr_lock_try()) -#endif + if (latch.wr_lock_try()) + { + ut_ad(!latch_readers); + ut_ad(!latch_ex); + ut_d(latch_ex= pthread_self()); + } + else lock_wait(SRW_LOCK_ARGS(file, line)); } @@ -1531,30 +1535,24 @@ public: /** Unlock the data dictionary cache. */ void unlock() { -# ifdef UNIV_DEBUG - latch.x_unlock(); -# else + ut_ad(latch_ex == pthread_self()); + ut_ad(!latch_readers); + ut_d(latch_ex= 0); latch.wr_unlock(); -# endif } /** Acquire a shared lock on the dictionary cache. */ void freeze() { -# ifdef UNIV_DEBUG - ut_ad(!latch.have_any()); - latch.s_lock(); -# else latch.rd_lock(); -# endif + ut_ad(!latch_ex); + ut_d(latch_readers++); } /** Release a shared lock on the dictionary cache. */ void unfreeze() { -# ifdef UNIV_DEBUG - latch.s_unlock(); -# else + ut_ad(!latch_ex); + ut_ad(latch_readers--); latch.rd_unlock(); -# endif } #endif diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 65537859924..59ee7f551b4 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -438,13 +438,6 @@ dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode, bool no_wait= false) MY_ATTRIBUTE((nonnull, warn_unused_result)); -/** Lock the child tables of a table. -@param table parent table -@param trx transaction -@return error code */ -dberr_t lock_table_children(dict_table_t *table, trx_t *trx) - MY_ATTRIBUTE((nonnull, warn_unused_result)); - /** Exclusively lock the data dictionary tables. @param trx dictionary transaction @return error code diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index c9072998e66..df51ceb16d8 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -3940,8 +3940,6 @@ static void lock_table_dequeue(lock_t *in_lock, bool owns_wait_mutex) dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode, bool no_wait) { - ut_ad(!dict_sys.frozen()); - mem_heap_t *heap= mem_heap_create(512); sel_node_t *node= sel_node_create(heap); que_thr_t *thr= pars_complete_graph_for_exec(node, trx, heap, nullptr); @@ -3978,36 +3976,6 @@ run_again: return err; } -/** Lock the child tables of a table. -@param table parent table -@param trx transaction -@return error code */ -dberr_t lock_table_children(dict_table_t *table, trx_t *trx) -{ - dict_sys.freeze(SRW_LOCK_CALL); - std::vector children; - - for (auto f : table->referenced_set) - if (dict_table_t *child= f->foreign_table) - { - child->acquire(); - children.emplace_back(child); - } - dict_sys.unfreeze(); - - dberr_t err= DB_SUCCESS; - - for (auto child : children) - if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) - break; - - for (auto child : children) - child->release(); - - return err; -} - - /** Exclusively lock the data dictionary tables. @param trx dictionary transaction @return error code From 7573fe8b07c52fdd45eac3d4f0f764f1c61ca41e Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 19 Jan 2024 15:00:13 +0530 Subject: [PATCH 053/121] MDEV-32968 InnoDB fails to restore tablespace first page from doublewrite buffer when page is empty recv_dblwr_t::find_first_page(): Free the allocated memory to read the first 3 pages from tablespace. innodb.doublewrite: Added sleep to ensure page cleaner thread wake up from my_cond_wait --- mysql-test/suite/innodb/t/doublewrite.test | 3 +++ storage/innobase/log/log0recv.cc | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 541e4d23a19..7e38851facb 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -39,6 +39,9 @@ commit work; SET GLOBAL innodb_fast_shutdown = 0; let $shutdown_timeout=; --source include/restart_mysqld.inc +# Ensure that buf_flush_page_cleaner() has woken up from its +# first my_cond_timedwait() and gone idle. +sleep 1; --source ../include/no_checkpoint_start.inc connect (dml,localhost,root,,); XA START 'x'; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 52649419ec7..ffe35e9dbc7 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3871,16 +3871,20 @@ uint32_t recv_dblwr_t::find_first_page(const char *name, pfs_os_file_t file) for (const page_t *page : pages) { uint32_t space_id= page_get_space_id(page); + byte *read_page= nullptr; if (page_get_page_no(page) > 0 || space_id == 0) + { next_page: + aligned_free(read_page); continue; + } uint32_t flags= mach_read_from_4( FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); page_id_t page_id(space_id, 0); size_t page_size= fil_space_t::physical_size(flags); if (file_size < 4 * page_size) goto next_page; - byte *read_page= + read_page= static_cast(aligned_malloc(3 * page_size, page_size)); /* Read 3 pages from the file and match the space id with the space id which is stored in @@ -3892,7 +3896,10 @@ next_page: { byte *cur_page= read_page + j * page_size; if (buf_is_zeroes(span(cur_page, page_size))) - return 0; + { + space_id= 0; + goto early_exit; + } if (mach_read_from_4(cur_page + FIL_PAGE_OFFSET) != j + 1 || memcmp(cur_page + FIL_PAGE_SPACE_ID, page + FIL_PAGE_SPACE_ID, 4) || @@ -3900,7 +3907,11 @@ next_page: goto next_page; } if (!restore_first_page(space_id, name, file)) + { +early_exit: + aligned_free(read_page); return space_id; + } break; } } From e8041c70656d2ebfcee8cf7343f944148b17946b Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 18 Jan 2024 20:59:00 -0800 Subject: [PATCH 054/121] MDEV-33270 Failure to call SP invoking another SP with parameter requiring type conversion This patch corrects the fix for MDEV-32569. The latter has not taken into account the fact not each statement uses the SELECT_LEX structure. In particular CALL statements do not use such structure. However the parameter passed to the stored procedure used in such a statement may require an invocation of Type_std_attributes::agg_item_set_converter(). Approved by Oleksandr Byelkin --- mysql-test/main/sp.result | 15 +++++++++++++++ mysql-test/main/sp.test | 20 ++++++++++++++++++++ sql/item.cc | 5 ++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 567597383bb..2f733107e8a 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8960,5 +8960,20 @@ DROP FUNCTION f1; DROP FUNCTION f2; DROP FUNCTION f3; DROP VIEW v1; +# +# MDEV-33270: Call of SP invoking another SP with a parameter +# requiring type conversion +# +SET NAMES latin1; +CREATE PROCEDURE p1 (a text) BEGIN SELECT a; END | +CREATE PROCEDURE p2 () CALL p1(concat('x',_utf8'x')) | +CALL p2(); +a +xx +CALL p2(); +a +xx +DROP PROCEDURE p1; +DROP PROCEDURE p2; # End of 10.4 tests # diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index c11ea23080b..50d9a611db9 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10567,5 +10567,25 @@ DROP FUNCTION f2; DROP FUNCTION f3; DROP VIEW v1; +--echo # +--echo # MDEV-33270: Call of SP invoking another SP with a parameter +--echo # requiring type conversion +--echo # + +SET NAMES latin1; + +--delimiter | + +CREATE PROCEDURE p1 (a text) BEGIN SELECT a; END | +CREATE PROCEDURE p2 () CALL p1(concat('x',_utf8'x')) | + +--delimiter ; + +CALL p2(); +CALL p2(); + +DROP PROCEDURE p1; +DROP PROCEDURE p2; + --echo # End of 10.4 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 6d30d63bc11..04b689f51af 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2586,7 +2586,10 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, return TRUE; if (!thd->stmt_arena->is_conventional() && - thd->lex->current_select->first_cond_optimization) + ((!thd->lex->current_select && + (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute() || + thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute())) || + thd->lex->current_select->first_cond_optimization)) { Query_arena *arena, backup; arena= thd->activate_stmt_arena_if_needed(&backup); From 3a33ae86010051a1022c392f2936b5fc9f3ab19e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 12 Jan 2024 16:57:37 +0100 Subject: [PATCH 055/121] MDEV-33091 pcre2 headers aren't found on Solaris use pkg-config to find pcre2, if possible rename PCRE_INCLUDES to use PKG_CHECK_MODULES naming, PCRE_INCLUDE_DIRS --- client/CMakeLists.txt | 2 +- cmake/pcre.cmake | 34 +++++++++++++--------- cmake/plugin.cmake | 2 +- extra/mariabackup/CMakeLists.txt | 2 +- libmysqld/CMakeLists.txt | 2 +- libmysqld/examples/CMakeLists.txt | 2 +- plugin/feedback/CMakeLists.txt | 2 +- plugin/qc_info/CMakeLists.txt | 2 +- sql/CMakeLists.txt | 2 +- storage/perfschema/CMakeLists.txt | 2 +- storage/perfschema/unittest/CMakeLists.txt | 2 +- unittest/embedded/CMakeLists.txt | 2 +- 12 files changed, 32 insertions(+), 24 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 55fd02b23c3..4dfce2478cd 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -16,7 +16,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include - ${PCRE_INCLUDES} + ${PCRE_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/mysys_ssl ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} diff --git a/cmake/pcre.cmake b/cmake/pcre.cmake index 65dc2ae28f6..c2eb26074ac 100644 --- a/cmake/pcre.cmake +++ b/cmake/pcre.cmake @@ -1,4 +1,3 @@ -INCLUDE (CheckCSourceRuns) INCLUDE (ExternalProject) SET(WITH_PCRE "auto" CACHE STRING @@ -6,7 +5,8 @@ SET(WITH_PCRE "auto" CACHE STRING MACRO(BUNDLE_PCRE2) SET(dir "${CMAKE_BINARY_DIR}/extra/pcre2") - SET(PCRE_INCLUDES ${dir}/src/pcre2-build ${dir}/src/pcre2/src) + SET(PCRE_INCLUDE_DIRS ${dir}/src/pcre2-build ${dir}/src/pcre2/src) + MESSAGE(STATUS "Will download and bundle pcre2") SET(byproducts) FOREACH(lib pcre2-posix pcre2-8) ADD_LIBRARY(${lib} STATIC IMPORTED GLOBAL) @@ -76,18 +76,26 @@ SET_TARGET_PROPERTIES(pcre2 PROPERTIES EXCLUDE_FROM_ALL TRUE) ENDMACRO() MACRO (CHECK_PCRE) - IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto") - CHECK_LIBRARY_EXISTS(pcre2-8 pcre2_match_8 "" HAVE_PCRE2) - ENDIF() - IF(NOT HAVE_PCRE2 OR WITH_PCRE STREQUAL "bundled") - IF (WITH_PCRE STREQUAL "system") - MESSAGE(FATAL_ERROR "system pcre2-8 library is not found or unusable") + IF (NOT TARGET pcre2 AND NOT PCRE_FOUND) + IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto") + FIND_PACKAGE(PkgConfig QUIET) + PKG_CHECK_MODULES(PCRE libpcre2-8) + # in case pkg-config or libpcre2-8.pc is not installed: + IF(NOT PCRE_FOUND) + UNSET(PCRE_FOUND CACHE) + CHECK_LIBRARY_EXISTS(pcre2-8 pcre2_match_8 "" PCRE_FOUND) + ENDIF() ENDIF() - BUNDLE_PCRE2() - ELSE() - CHECK_LIBRARY_EXISTS(pcre2-posix PCRE2regcomp "" NEEDS_PCRE2_DEBIAN_HACK) - IF(NEEDS_PCRE2_DEBIAN_HACK) - SET(PCRE2_DEBIAN_HACK "-Dregcomp=PCRE2regcomp -Dregexec=PCRE2regexec -Dregerror=PCRE2regerror -Dregfree=PCRE2regfree") + IF(NOT PCRE_FOUND OR WITH_PCRE STREQUAL "bundled") + IF (WITH_PCRE STREQUAL "system") + MESSAGE(FATAL_ERROR "system pcre2-8 library is not found or unusable") + ENDIF() + BUNDLE_PCRE2() + ELSE() + CHECK_LIBRARY_EXISTS(pcre2-posix PCRE2regcomp "" NEEDS_PCRE2_DEBIAN_HACK) + IF(NEEDS_PCRE2_DEBIAN_HACK) + SET(PCRE2_DEBIAN_HACK "-Dregcomp=PCRE2regcomp -Dregexec=PCRE2regexec -Dregerror=PCRE2regerror -Dregfree=PCRE2regfree") + ENDIF() ENDIF() ENDIF() ENDMACRO() diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index 813d8ef6e42..6efd40fd1bd 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -44,7 +44,7 @@ MACRO(MYSQL_ADD_PLUGIN) # Add common include directories INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql - ${PCRE_INCLUDES} + ${PCRE_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR}) diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt index a7a35c58ac3..4dfef82d3d5 100644 --- a/extra/mariabackup/CMakeLists.txt +++ b/extra/mariabackup/CMakeLists.txt @@ -36,7 +36,7 @@ INCLUDE_DIRECTORIES( ) IF(NOT HAVE_SYSTEM_REGEX) - INCLUDE_DIRECTORIES(${PCRE_INCLUDES}) + INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIRS}) ADD_DEFINITIONS(${PCRE2_DEBIAN_HACK}) ENDIF() diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index b414903f705..ff6e2cbf36d 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -23,7 +23,7 @@ ${CMAKE_SOURCE_DIR}/libmysqld ${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/tpool ${CMAKE_BINARY_DIR}/sql -${PCRE_INCLUDES} +${PCRE_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${SSL_INTERNAL_INCLUDE_DIRS} diff --git a/libmysqld/examples/CMakeLists.txt b/libmysqld/examples/CMakeLists.txt index 2a10def8e2e..d6646a128ca 100644 --- a/libmysqld/examples/CMakeLists.txt +++ b/libmysqld/examples/CMakeLists.txt @@ -15,7 +15,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/libmysqld/include - ${PCRE_INCLUDES} + ${PCRE_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/sql ${MY_READLINE_INCLUDE_DIR} ) diff --git a/plugin/feedback/CMakeLists.txt b/plugin/feedback/CMakeLists.txt index 2103250e5a6..fc35cbadc31 100644 --- a/plugin/feedback/CMakeLists.txt +++ b/plugin/feedback/CMakeLists.txt @@ -1,5 +1,5 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql - ${PCRE_INCLUDES} + ${PCRE_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}) SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc diff --git a/plugin/qc_info/CMakeLists.txt b/plugin/qc_info/CMakeLists.txt index b8c5f926cff..329f49c1fc9 100644 --- a/plugin/qc_info/CMakeLists.txt +++ b/plugin/qc_info/CMakeLists.txt @@ -1,4 +1,4 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql - ${PCRE_INCLUDES}) + ${PCRE_INCLUDE_DIRS}) MYSQL_ADD_PLUGIN(QUERY_CACHE_INFO qc_info.cc RECOMPILE_FOR_EMBEDDED) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 557fd5eb506..f1c1c65310b 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -52,7 +52,7 @@ ENDIF() INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql -${PCRE_INCLUDES} +${PCRE_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/sql diff --git a/storage/perfschema/CMakeLists.txt b/storage/perfschema/CMakeLists.txt index b4f5e96b607..e703e43fe50 100644 --- a/storage/perfschema/CMakeLists.txt +++ b/storage/perfschema/CMakeLists.txt @@ -24,7 +24,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql ${CMAKE_BINARY_DIR}/sql ${CMAKE_CURRENT_BINARY_DIR} - ${PCRE_INCLUDES} + ${PCRE_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}) ADD_DEFINITIONS(-DMYSQL_SERVER) diff --git a/storage/perfschema/unittest/CMakeLists.txt b/storage/perfschema/unittest/CMakeLists.txt index 2a22990f807..600795c78fc 100644 --- a/storage/perfschema/unittest/CMakeLists.txt +++ b/storage/perfschema/unittest/CMakeLists.txt @@ -22,7 +22,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/mysql - ${PCRE_INCLUDES} + ${PCRE_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/sql ${SSL_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/unittest/mytap diff --git a/unittest/embedded/CMakeLists.txt b/unittest/embedded/CMakeLists.txt index cf48550c377..428bb811de6 100644 --- a/unittest/embedded/CMakeLists.txt +++ b/unittest/embedded/CMakeLists.txt @@ -1,7 +1,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/libmysqld/include - ${PCRE_INCLUDES} + ${PCRE_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/sql ${MY_READLINE_INCLUDE_DIR} ) From 7e8e51eb3ad1ffd1bf8ec9c5dc23038e0e2e4b9c Mon Sep 17 00:00:00 2001 From: Sisi Huang Date: Thu, 11 Jan 2024 23:02:34 -0800 Subject: [PATCH 056/121] MDEV-32990 federatedx time_zone round trips Modified `federatedx_io_mysql::actual_query` to set the time zone to '+00:00' only upon establishing a new connection instead of with each query execution. --- storage/federatedx/federatedx_io_mysql.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/storage/federatedx/federatedx_io_mysql.cc b/storage/federatedx/federatedx_io_mysql.cc index cf620d59986..5c96982cf59 100644 --- a/storage/federatedx/federatedx_io_mysql.cc +++ b/storage/federatedx/federatedx_io_mysql.cc @@ -451,11 +451,14 @@ int federatedx_io_mysql::actual_query(const char *buffer, size_t length) get_port(), get_socket(), 0)) DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE); + + if ((error= mysql_real_query(&mysql, STRING_WITH_LEN("set time_zone='+00:00'")))) + DBUG_RETURN(error); + mysql.reconnect= 1; } - if (!(error= mysql_real_query(&mysql, STRING_WITH_LEN("set time_zone='+00:00'")))) - error= mysql_real_query(&mysql, buffer, (ulong)length); + error= mysql_real_query(&mysql, buffer, (ulong)length); DBUG_RETURN(error); } From 0c23f84d8dcb61c25849c07149933245333a32d9 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 11 Dec 2023 10:15:55 +1100 Subject: [PATCH 057/121] MDEV-32983 cosmetic improvement on path separator near ib_buffer_pool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A mix of path separators looks odd. InnoDB: Loading buffer pool(s) from C:\xampp\mysql\data/ib_buffer_pool This was changed in cf552f5886968fc022122960d3a9274ce9f27819 Both forward slashes and backward slashes work on Windows. We do not use \\?\ names. So we improve the consistent look of it so it doesn't look like a bug. Normalize, in this case, the path separator to \ for making the filename. Reported thanks to Github user @celestinoxp. Closes: https://github.com/ApacheFriends/xampp-build/issues/33 Reviewed by: Marko Mäkelä and Vladislav Vaintroub --- storage/innobase/buf/buf0dump.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index f142263a0e4..e9d544f9616 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -180,7 +180,7 @@ static void buf_dump_generate_path(char *path, size_t path_size) char buf[FN_REFLEN]; mysql_mutex_lock(&LOCK_global_system_variables); - snprintf(buf, sizeof buf, "%s/%s", get_buf_dump_dir(), + snprintf(buf, sizeof buf, "%s" FN_ROOTDIR "%s", get_buf_dump_dir(), srv_buf_dump_filename); mysql_mutex_unlock(&LOCK_global_system_variables); @@ -214,7 +214,7 @@ static void buf_dump_generate_path(char *path, size_t path_size) format = "%s%s"; break; default: - format = "%s/%s"; + format = "%s" FN_ROOTDIR "%s"; } snprintf(path, path_size, format, From e237925963eeff72809a7b9aafb4bd838c457064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Jan 2024 08:19:00 +0200 Subject: [PATCH 058/121] MDEV-33031 test fixup for HAVE_PERFSCHEMA=NO --- storage/spider/mysql-test/spider/bugfix/t/perfschema.opt | 2 +- storage/spider/mysql-test/spider/bugfix/t/perfschema.test | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/spider/mysql-test/spider/bugfix/t/perfschema.opt b/storage/spider/mysql-test/spider/bugfix/t/perfschema.opt index 611d08f0c78..d2ed32ddf34 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/perfschema.opt +++ b/storage/spider/mysql-test/spider/bugfix/t/perfschema.opt @@ -1 +1 @@ ---performance-schema +--loose-performance-schema diff --git a/storage/spider/mysql-test/spider/bugfix/t/perfschema.test b/storage/spider/mysql-test/spider/bugfix/t/perfschema.test index 2f1a961a513..9346d2b5aa3 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/perfschema.test +++ b/storage/spider/mysql-test/spider/bugfix/t/perfschema.test @@ -1,3 +1,4 @@ +source include/have_perfschema.inc; disable_query_log; source ../../include/init_spider.inc; enable_query_log; From 495e7f1b3ddc53a9f588a5e0b1f9ca2f2d82e43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Jan 2024 08:24:08 +0200 Subject: [PATCH 059/121] MDEV-33053 fixup: Correct a condition before a message --- storage/innobase/buf/buf0flu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 21ca288ec23..4f7fb316b88 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1798,7 +1798,7 @@ ulint buf_flush_LRU(ulint max_n, bool evict) pthread_cond_broadcast(&buf_pool.done_free); } else if (!pages && !buf_pool.try_LRU_scan && - buf_pool.LRU_warned.test_and_set(std::memory_order_acquire)) + !buf_pool.LRU_warned.test_and_set(std::memory_order_acquire)) { /* For example, with the minimum innodb_buffer_pool_size=5M and the default innodb_page_size=16k there are only a little over 316 From 7f11fad85a885d148254ca05f508125e3b94339c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Jan 2024 10:04:11 +0200 Subject: [PATCH 060/121] MDEV-32968: After-merge fix This fixes up merge commit 9d20853c74935717a20bbcb08d3bad6bf1a56dda --- storage/innobase/fsp/fsp0file.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 5cbc18c1c97..1c20efcdca2 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -502,9 +502,9 @@ err_exit: return DB_SUCCESS; } - sql_print_error("InnoDB: %s in datafile: %s, Space ID: %zu, " - "Flags: %zu", error_txt, m_filepath, - m_space_id, m_flags); + sql_print_error("InnoDB: %s in datafile: %s, Space ID: " + UINT32PF ", " "Flags: " UINT32PF, + error_txt, m_filepath, m_space_id, m_flags); m_is_valid = false; return DB_CORRUPTION; } From 0335629eb33a73db9ed9176a63140d84dfaaa4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Jan 2024 11:31:22 +0200 Subject: [PATCH 061/121] MDEV-32242 fixup: innodb.doublewrite test may be skipped again It is not sufficient to sleep for only 1 second to ensure that the page cleaner has gone idle. The timings could have been changed compared to earlier releases by commit a635c40648519fd6c3729c9657872a16a0a20821 (MDEV-27774). Let us allow the non-debug test innodb.doublewrite to be skipped, and remove the insufficient 1-second sleep. --- mysql-test/suite/innodb/t/doublewrite.test | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 7e38851facb..d73009908db 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -39,9 +39,6 @@ commit work; SET GLOBAL innodb_fast_shutdown = 0; let $shutdown_timeout=; --source include/restart_mysqld.inc -# Ensure that buf_flush_page_cleaner() has woken up from its -# first my_cond_timedwait() and gone idle. -sleep 1; --source ../include/no_checkpoint_start.inc connect (dml,localhost,root,,); XA START 'x'; @@ -54,7 +51,7 @@ connection default; flush table t1 for export; let $restart_parameters=; ---let CLEANUP_IF_CHECKPOINT=drop table t1, unexpected_checkpoint; +--let CLEANUP_IF_CHECKPOINT=XA COMMIT 'x';drop table t1; --source ../include/no_checkpoint_end.inc perl; From 1acf6a0f84d4bda8418467eff57fb607dd615b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 22 Jan 2024 12:42:37 +0200 Subject: [PATCH 062/121] MDEV-14425 fixup: mariabackup.huge_lsn,strict_crc32 rdiff Some old versions of "patch" (such as patch 2.5.9 on Microsoft Windows) require that a file name header be present. To ensure that the diff will be applied, let us add the header. --- mysql-test/suite/mariabackup/huge_lsn,strict_crc32.rdiff | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/mariabackup/huge_lsn,strict_crc32.rdiff b/mysql-test/suite/mariabackup/huge_lsn,strict_crc32.rdiff index 29afd468751..9ed08fcd26a 100644 --- a/mysql-test/suite/mariabackup/huge_lsn,strict_crc32.rdiff +++ b/mysql-test/suite/mariabackup/huge_lsn,strict_crc32.rdiff @@ -1,3 +1,5 @@ +--- suite/mariabackup/huge_lsn.result ++++ suite/mariabackup/huge_lsn.reject @@ -1,8 +1,8 @@ # # MDEV-13416 mariabackup fails with EFAULT "Bad Address" From 3cd8875145b2c1dffe1f12510fbf92bf1a8f2fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 16 Jan 2024 08:02:32 +0200 Subject: [PATCH 063/121] MDEV-14448: Ctrl-C should not exit the client This patch introduces the following behaviour for Linux while maintaining old behaviour for Windows: Ctrl + C (sigint) clears the current buffer and redraws the prompt. Ctrl-C no longer exits the client if no query is running. Ctrl-C kills the current running query if there is one. If there is an error communicating with the server while trying to issue a KILL QUERY, the client exits. This is in line with the past behaviour of Ctrl-C. On Linux Ctrl-D can be used to close the client. On Windows Ctrl-C and Ctrl-BREAK still exits the client if no query is running. Windows can also exit the client via \q or exit. == Implementation details == The Linux implementation has two corner cases, based on which library is used: libreadline or libedit, both are handled in code to achieve the same user experience. Additional code is taken from MySQL, ensuring there is identical behaviour on Windows, to MySQL's mysql client implementation for other CTRL- related signals. * The CTRL_CLOSE, CTRL_LOGOFF, CTRL_SHUTDOWN will issue the equivalent of CTRL-C and "end" the program. This ensures that the query is killed when the client is closed by closing the terminal, logging off the user or shutting down the system. The latter two signals are not sent for interactive applications, but it handles the case when a user has defined a service to use mysql client to issue a command. See https://learn.microsoft.com/en-us/windows/console/handlerroutine This patch is built on top of the initial work done by Anel Husakovic . Closes #2815 --- client/mysql.cc | 173 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 139 insertions(+), 34 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 214b0d51a32..befa0e9b113 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -89,6 +89,7 @@ extern "C" { #undef bcmp // Fix problem with new readline #if defined(__WIN__) #include +#include #else # ifdef __APPLE__ # include @@ -170,6 +171,9 @@ static int connect_flag=CLIENT_INTERACTIVE; static my_bool opt_binary_mode= FALSE; static my_bool opt_connect_expired_password= FALSE; static int interrupted_query= 0; +#ifdef USE_LIBEDIT_INTERFACE +static int sigint_received= 0; +#endif static char *current_host,*current_db,*current_user=0,*opt_password=0, *current_prompt=0, *delimiter_str= 0, *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME, @@ -1072,7 +1076,32 @@ extern "C" sig_handler handle_sigint(int sig); static sig_handler window_resize(int sig); #endif +static void end_in_sig_handler(int sig); +static bool kill_query(const char *reason); +#ifdef _WIN32 +static BOOL WINAPI ctrl_handler_windows(DWORD fdwCtrlType) +{ + switch (fdwCtrlType) + { + // Handle the CTRL-C signal. + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + handle_sigint(SIGINT); + return TRUE; // this means that the signal is handled + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + kill_query("Terminate"); + end_in_sig_handler(SIGINT + 1); + aborted= 1; + } + // This means to pass the signal to the next handler. This allows + // my_cgets and the internal ReadConsole call to exit and gracefully + // abort the program. + return FALSE; +} +#endif const char DELIMITER_NAME[]= "delimiter"; const uint DELIMITER_NAME_LEN= sizeof(DELIMITER_NAME) - 1; inline bool is_delimiter_command(char *name, ulong len) @@ -1205,11 +1234,12 @@ int main(int argc,char *argv[]) if (!status.batch) ignore_errors=1; // Don't abort monitor - if (opt_sigint_ignore) - signal(SIGINT, SIG_IGN); - else - signal(SIGINT, handle_sigint); // Catch SIGINT to clean up - signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up +#ifndef _WIN32 + signal(SIGINT, handle_sigint); // Catch SIGINT to clean up + signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up +#else + SetConsoleCtrlHandler(ctrl_handler_windows, TRUE); +#endif #if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL) /* Readline will call this if it installs a handler */ @@ -1376,30 +1406,35 @@ static bool do_connect(MYSQL *mysql, const char *host, const char *user, } -/* - This function handles sigint calls - If query is in process, kill query - If 'source' is executed, abort source command - no query in process, terminate like previous behavior - */ +void end_in_sig_handler(int sig) +{ +#ifdef _WIN32 + /* + When SIGINT is raised on Windows, the OS creates a new thread to handle the + interrupt. Once that thread completes, the main thread continues running + only to find that it's resources have already been free'd when the sigint + handler called mysql_end(). + */ + mysql_thread_end(); +#else + mysql_end(sig); +#endif +} -sig_handler handle_sigint(int sig) + +/* + Kill a running query. Returns true if we were unable to connect to the server. +*/ +bool kill_query(const char *reason) { char kill_buffer[40]; MYSQL *kill_mysql= NULL; - /* terminate if no query being executed, or we already tried interrupting */ - if (!executing_query || (interrupted_query == 2)) - { - tee_fprintf(stdout, "Ctrl-C -- exit!\n"); - goto err; - } - kill_mysql= mysql_init(kill_mysql); if (!do_connect(kill_mysql,current_host, current_user, opt_password, "", 0)) { - tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); - goto err; + tee_fprintf(stdout, "%s -- sorry, cannot connect to server to kill query, giving up ...\n", reason); + return true; } /* First time try to kill the query, second time the connection */ @@ -1414,27 +1449,65 @@ sig_handler handle_sigint(int sig) (interrupted_query == 1) ? "QUERY " : "", mysql_thread_id(&mysql)); if (verbose) - tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", + tee_fprintf(stdout, "%s -- sending \"%s\" to server ...\n", reason, kill_buffer); mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer)); mysql_close(kill_mysql); - tee_fprintf(stdout, "Ctrl-C -- query killed. Continuing normally.\n"); + if (interrupted_query == 1) + tee_fprintf(stdout, "%s -- query killed.\n", reason); + else + tee_fprintf(stdout, "%s -- connection killed.\n", reason); + if (in_com_source) aborted= 1; // Abort source command - return; + return false; +} + +/* + This function handles sigint calls + If query is in process, kill query + If 'source' is executed, abort source command + no query in process, regenerate prompt. +*/ +sig_handler handle_sigint(int sig) +{ + if (opt_sigint_ignore) + return; -err: -#ifdef _WIN32 /* - When SIGINT is raised on Windows, the OS creates a new thread to handle the - interrupt. Once that thread completes, the main thread continues running - only to find that it's resources have already been free'd when the sigint - handler called mysql_end(). + On Unix only, if no query is being executed just clear the prompt, + don't exit. On Windows we exit. */ - mysql_thread_end(); + if (!executing_query) + { +#ifndef _WIN32 + tee_fprintf(stdout, "^C\n"); +#ifdef USE_LIBEDIT_INTERFACE + /* Libedit will regenerate it outside of the signal handler. */ + sigint_received= 1; #else - mysql_end(sig); -#endif + rl_on_new_line(); // Regenerate the prompt on a newline + rl_replace_line("", 0); // Clear the previous text + rl_redisplay(); +#endif +#else // WIN32 + tee_fprintf(stdout, "Ctrl-C -- exit!\n"); + end_in_sig_handler(sig); +#endif + return; + } + + /* + When executing a query, this newline makes the prompt look like so: + ^C + Ctrl-C -- query killed. + */ + tee_fprintf(stdout, "\n"); + if (kill_query("Ctrl-C")) + { + aborted= 1; + end_in_sig_handler(sig); + } } @@ -1973,6 +2046,12 @@ static int get_options(int argc, char **argv) return(0); } +static inline void reset_prompt(char *in_string, bool *ml_comment) { + glob_buffer.length(0); + *ml_comment = false; + *in_string = 0; +} + static int read_and_execute(bool interactive) { #if defined(__WIN__) @@ -2063,7 +2142,7 @@ static int read_and_execute(bool interactive) size_t clen; do { - line= my_cgets((char*)tmpbuf.ptr(), tmpbuf.alloced_length()-1, &clen); + line= my_cgets((char*)tmpbuf.ptr(), tmpbuf.alloced_length()-1, &clen); buffer.append(line, clen); /* if we got buffer fully filled than there is a chance that @@ -2085,8 +2164,34 @@ static int read_and_execute(bool interactive) the readline/libedit library. */ if (line) + { free(line); + glob_buffer.length(0); + } line= readline(prompt); +#ifdef USE_LIBEDIT_INTERFACE + /* + libedit handles interrupts different than libreadline. + libreadline has its own signal handlers, thus a sigint during readline + doesn't force readline to return null string. + + However libedit returns null if the interrupt signal is raised. + We can also get an empty string when ctrl+d is pressed (EoF). + + We need this sigint_received flag, to differentiate between the two + cases. This flag is only set during our handle_sigint function when + LIBEDIT_INTERFACE is used. + */ + if (!line && sigint_received) + { + // User asked to clear the input. + sigint_received= 0; + reset_prompt(&in_string, &ml_comment); + continue; + } + // For safety, we always mark this as cleared. + sigint_received= 0; +#endif #endif /* defined(__WIN__) */ /* From 207c85783b2c7831e1851fe9d0a4228b18d3d3fd Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Fri, 19 Jan 2024 10:31:45 -0700 Subject: [PATCH 064/121] MDEV-33283: Binlog Checksum is Zeroed by Zlib if Part of Event Data is Empty An existing binlog checksum can be overridden to 0 if writing a NULL payload when using Zlib for the computation. That is, calling into Zlib's crc32 with empty data initializes an incremental CRC computation to 0. This patch changes the Log_event_writer::write_data() to exit immediately if there is nothing to write, thereby bypassing the checksum computation. This follows the pattern of Log_event_writer::encrypt_and_write(), which also exits immediately if there is no data to write. Reviewed By: ============ Andrei Elkin --- sql/log_event_server.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 2a22021cc95..f51f5b7deec 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -916,6 +916,10 @@ int Log_event_writer::write_header(uchar *pos, size_t len) int Log_event_writer::write_data(const uchar *pos, size_t len) { DBUG_ENTER("Log_event_writer::write_data"); + + if (!len) + DBUG_RETURN(0); + if (checksum_len) crc= my_checksum(crc, pos, len); From 01ca57ec1615015e163123fa1882bcc278c81b9a Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 17 Jan 2024 07:14:11 -0700 Subject: [PATCH 065/121] MDEV-32168: Postpush fix for rpl_domain_id_filter_master_crash While a replica may be reading events from the primary, the primary is killed. Left to its own devices, the IO thread may or may not stop in error, depending on what it is doing when its connection to the primary is killed (e.g. a failed read results in an error, whereas if the IO thread is idly waiting for events when the connection dies, it will enter into a reconnect loop and reconnect). MDEV-32168 changed the test to always wait for the reconnect, thus breaking the error case, as the IO thread would be stopped at a time of expecting it to be running. The fix is to manually stop/start the IO thread to ensure it is in a consistent state. Note that rpl_domain_id_filter_master_crash.test will need additional changes after fixing MDEV-33268 Reviewed By: ============ Kristian Nielsen --- .../rpl_domain_id_filter_master_crash.result | 5 +++-- .../t/rpl_domain_id_filter_master_crash.test | 20 +++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result index 4169a2ddc26..a54ff99b591 100644 --- a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result +++ b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result @@ -38,8 +38,9 @@ connection master; include/rpl_start_server.inc [server_number=1] # Master has restarted successfully connection slave; -include/wait_for_slave_io_to_start.inc -include/wait_for_slave_sql_to_start.inc +include/stop_slave_sql.inc +include/stop_slave_io.inc +include/start_slave.inc select * from ti; a 1 diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test index b1fa9af33a4..cdfdc098f5a 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test @@ -67,10 +67,26 @@ connection master; save_master_pos; --connection slave + +# Left to its own devices, the IO thread may or may not stop in error, +# depending on what it is doing when its connection to the primary is killed +# (e.g. a failed read results in an error, whereas if the IO thread is idly +# waiting for events when the connection dies, it will enter into a reconnect +# loop and reconnect). So we manually stop/start the IO thread to ensure it is +# in a consistent state +# +# FIXME: We shouldn't need to stop/start the SQL thread here, but due to +# MDEV-33268, we have to. So after fixing 33268, this should only stop/start +# the IO thread. Note the SQL thread must be stopped first due to an invalid +# DBUG_ASSERT in the IO thread's stop logic that depends on the state of the +# SQL thread (also reported and to be fixed in the same ticket). +# +--source include/stop_slave_sql.inc --let rpl_allow_error=1 ---source include/wait_for_slave_io_to_start.inc +--source include/stop_slave_io.inc --let rpl_allow_error= ---source include/wait_for_slave_sql_to_start.inc +--source include/start_slave.inc + sync_with_master; select * from ti; select * from tm; From 19f3796ec372f2c096c853120d4e2a81df1e5bb1 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 22 Jan 2024 15:57:05 +0100 Subject: [PATCH 066/121] new CC 3.3 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 26cef16b25f..e714a674827 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 26cef16b25f01c1b159b0c73e3f6d9bcfcac90d5 +Subproject commit e714a674827fbb8373dd71da634dd04736d7b5a6 From a9172b8a436a9e403aee63a16f9a5655b9c98e9b Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 22 Jan 2024 15:27:58 +0100 Subject: [PATCH 067/121] Update minizip files for connect enginbe from last zlib 1.3. --- storage/connect/zip.c | 369 ++++++++++++++++++------------------------ storage/connect/zip.h | 292 ++++++++++++++++----------------- 2 files changed, 303 insertions(+), 358 deletions(-) diff --git a/storage/connect/zip.c b/storage/connect/zip.c index f6a10601968..3d3d4caddef 100644 --- a/storage/connect/zip.c +++ b/storage/connect/zip.c @@ -14,8 +14,8 @@ Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data - It is used when recreting zip archive with RAW when deleting items from a zip. - ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. + It is used when recreating zip archive with RAW when deleting items from a zip. + ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer @@ -25,15 +25,13 @@ #include #include #include +#include #include #include "zlib.h" #include "zip.h" -#include "my_attribute.h" #ifdef STDC # include -# include -# include #endif #ifdef NO_ERRNO_H extern int errno; @@ -48,7 +46,7 @@ /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ +# define VERSIONMADEBY (0x0) /* platform dependent */ #endif #ifndef Z_BUFSIZE @@ -62,9 +60,6 @@ #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif /* #define SIZECENTRALDIRITEM (0x2e) @@ -117,7 +112,7 @@ typedef struct linkedlist_datablock_internal_s struct linkedlist_datablock_internal_s* next_datablock; uLong avail_in_this_block; uLong filled_in_this_block; - uLong unused; /* for future use and alignement */ + uLong unused; /* for future use and alignment */ unsigned char data[SIZEDATA_INDATABLOCK]; } linkedlist_datablock_internal; @@ -139,40 +134,40 @@ typedef struct uInt pos_in_buffered_data; /* last written byte in buffered_data */ ZPOS64_T pos_local_header; /* offset of the local header of the file - currenty writing */ + currently writing */ char* central_header; /* central header data for the current file */ uLong size_centralExtra; uLong size_centralheader; /* size of the central header for cur file */ uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ uLong flag; /* flag of the file currently writing */ - int method; /* compression method of file currenty wr.*/ + int method; /* compression method of file currently wr.*/ int raw; /* 1 for directly writing raw data */ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ uLong dosDate; uLong crc32; int encrypt; - int zip64; /* Add ZIP64 extened information in the extra field */ + int zip64; /* Add ZIP64 extended information in the extra field */ ZPOS64_T pos_zip64extrainfo; ZPOS64_T totalCompressedData; ZPOS64_T totalUncompressedData; #ifndef NOCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const z_crc_t* pcrc_32_tab; - int crypt_header_size; + unsigned crypt_header_size; #endif } curfile64_info; typedef struct { zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ + voidpf filestream; /* io structure of the zipfile */ linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile64_info ci; /* info on the file curretly writing */ + curfile64_info ci; /* info on the file currently writing */ ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ - ZPOS64_T add_position_when_writting_offset; + ZPOS64_T add_position_when_writing_offset; ZPOS64_T number_entry; #ifndef NO_ADDFILEINEXISTINGZIP @@ -187,8 +182,7 @@ typedef struct #include "crypt.h" #endif -local linkedlist_datablock_internal* allocate_new_datablock() -{ +local linkedlist_datablock_internal* allocate_new_datablock(void) { linkedlist_datablock_internal* ldi; ldi = (linkedlist_datablock_internal*) ALLOC(sizeof(linkedlist_datablock_internal)); @@ -201,30 +195,26 @@ local linkedlist_datablock_internal* allocate_new_datablock() return ldi; } -local void free_datablock(linkedlist_datablock_internal* ldi) -{ +local void free_datablock(linkedlist_datablock_internal* ldi) { while (ldi!=NULL) { linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); + free(ldi); ldi = ldinext; } } -local void init_linkedlist(linkedlist_data* ll) -{ +local void init_linkedlist(linkedlist_data* ll) { ll->first_block = ll->last_block = NULL; } -local void free_linkedlist(linkedlist_data* ll) -{ +local void free_linkedlist(linkedlist_data* ll) { free_datablock(ll->first_block); ll->first_block = ll->last_block = NULL; } -local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) -{ +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) { linkedlist_datablock_internal* ldi; const unsigned char* from_copy; @@ -239,7 +229,7 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) } ldi = ll->last_block; - from_copy = (unsigned char*)buf; + from_copy = (const unsigned char*)buf; while (len>0) { @@ -284,9 +274,7 @@ local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) */ -local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); -local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) -{ +local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) { unsigned char buf[8]; int n; for (n = 0; n < nbByte; n++) @@ -302,15 +290,13 @@ local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, } } - if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte) return ZIP_ERRNO; else return ZIP_OK; } -local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); -local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) -{ +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) { unsigned char* buf=(unsigned char*)dest; int n; for (n = 0; n < nbByte; n++) { @@ -330,25 +316,21 @@ local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) /****************************************************************************/ -local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) -{ +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) { uLong year = (uLong)ptm->tm_year; if (year>=1980) year-=1980; else if (year>=80) year-=80; return - (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | - ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); + (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) | + (((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); } /****************************************************************************/ -local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); - -local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) -{ +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) { unsigned char c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1) @@ -369,10 +351,7 @@ local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,vo /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ -local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; @@ -391,10 +370,7 @@ local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, return err; } -local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ +local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; @@ -421,11 +397,8 @@ local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, return err; } -local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); - -local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) -{ +local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { ZPOS64_T x; int i = 0; int err; @@ -476,10 +449,7 @@ local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; @@ -519,18 +489,18 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; - for (i=(int)uReadSize-3; (i--)>0;) { + for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } - } + if (uPosFound!=0) break; } - TRYFREE(buf); + free(buf); return uPosFound; } @@ -538,10 +508,7 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before the global comment) */ -local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; @@ -587,7 +554,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib // Signature "0x07064b50" Zip64 end of central directory locater if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { - uPosFound = uReadPos+i; + uPosFound = uReadPos+(unsigned)i; break; } } @@ -596,7 +563,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib break; } - TRYFREE(buf); + free(buf); if (uPosFound == 0) return 0; @@ -638,8 +605,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib return relativeOffset; } -static int LoadCentralDirectoryRecord(zip64_internal* pziinit) -{ +local int LoadCentralDirectoryRecord(zip64_internal* pziinit) { int err=ZIP_OK; ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ @@ -649,9 +615,9 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) uLong uL; uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ + spanning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ + for spanning ZIP, unsupported, always 0*/ ZPOS64_T number_entry; ZPOS64_T number_entry_CD; /* total number of entries in the central dir @@ -808,7 +774,7 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) } byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); - pziinit->add_position_when_writting_offset = byte_before_the_zipfile; + pziinit->add_position_when_writing_offset = byte_before_the_zipfile; { ZPOS64_T size_central_dir_to_read = size_central_dir; @@ -831,7 +797,7 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) size_central_dir_to_read-=read_this; } - TRYFREE(buf_read); + free(buf_read); } pziinit->begin_pos = byte_before_the_zipfile; pziinit->number_entry = number_entry_CD; @@ -847,8 +813,7 @@ static int LoadCentralDirectoryRecord(zip64_internal* pziinit) /************************************************************/ -static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) -{ +extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) { zip64_internal ziinit; zip64_internal* zi; int err=ZIP_OK; @@ -876,7 +841,7 @@ static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomm ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; - ziinit.add_position_when_writting_offset = 0; + ziinit.add_position_when_writing_offset = 0; init_linkedlist(&(ziinit.central_dir)); @@ -906,9 +871,9 @@ static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomm if (err != ZIP_OK) { # ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); + free(ziinit.globalcomment); # endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); + free(zi); return NULL; } else @@ -918,8 +883,7 @@ static zipFile zipOpen3 (const void *pathname, int append, zipcharpc* globalcomm } } -extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) -{ +extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) { if (pzlib_filefunc32_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; @@ -930,8 +894,7 @@ extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* gl return zipOpen3(pathname, append, globalcomment, NULL); } -extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) -{ +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) { if (pzlib_filefunc_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; @@ -946,18 +909,15 @@ extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* -extern zipFile ZEXPORT zipOpen (const char* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen(const char* pathname, int append) { return zipOpen3((const void*)pathname,append,NULL,NULL); } -extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) -{ +extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) { return zipOpen3(pathname,append,NULL,NULL); } -static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) -{ +local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) { /* write the local header */ int err; uInt size_filename = (uInt)strlen(filename); @@ -1035,8 +995,8 @@ static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); @@ -1053,24 +1013,24 @@ static int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize unnecessary allocations. */ -extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting __attribute__((unused)), - uLong versionMadeBy, uLong flagBase, int zip64) -{ +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) { zip64_internal* zi; uInt size_filename; uInt size_comment; uInt i; int err = ZIP_OK; -#ifdef NOCRYPT +# ifdef NOCRYPT + (crcForCrypting); if (password != NULL) return ZIP_PARAMERROR; -#endif +# endif if (file == NULL) return ZIP_PARAMERROR; @@ -1164,7 +1124,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, if(zi->ci.pos_local_header >= 0xffffffff) zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); else - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); @@ -1262,35 +1222,33 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, return err; } -extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, versionMadeBy, flagBase, 0); +extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, versionMadeBy, flagBase, 0); } -extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, 0); +extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, @@ -1298,70 +1256,64 @@ extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, c const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, zip64); + const char* password, uLong crcForCrypting, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); } extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); + const char* comment, int method, int level, int raw) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); } -extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); +extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); } -extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); +extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); } -local int zip64FlushWriteBuffer(zip64_internal* zi) -{ +local int zip64FlushWriteBuffer(zip64_internal* zi) { int err=ZIP_OK; if (zi->ci.encrypt != 0) @@ -1399,8 +1351,7 @@ local int zip64FlushWriteBuffer(zip64_internal* zi) return err; } -extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) -{ +extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) { zip64_internal* zi; int err=ZIP_OK; @@ -1450,7 +1401,7 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in else #endif { - zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf; zi->ci.stream.avail_in = len; while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) @@ -1501,17 +1452,15 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in return err; } -extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) { return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); } -extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) -{ +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) { zip64_internal* zi; ZPOS64_T compressed_size; uLong invalidValue = 0xffffffff; - short datasize = 0; + unsigned datasize = 0; int err=ZIP_OK; if (file == NULL) @@ -1742,15 +1691,13 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s return err; } -extern int ZEXPORT zipCloseFileInZip (zipFile file) -{ +extern int ZEXPORT zipCloseFileInZip(zipFile file) { return zipCloseFileInZipRaw (file,0,0); } -static int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { int err = ZIP_OK; - ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); @@ -1769,8 +1716,7 @@ static int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T return err; } -static int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ +local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; uLong Zip64DataSize = 44; @@ -1803,13 +1749,13 @@ static int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); } return err; } -static int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ + +local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; /*signature*/ @@ -1844,20 +1790,19 @@ static int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_cent if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff) { err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); } else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); } return err; } -static int Write_GlobalComment(zip64_internal* zi, const char* global_comment) -{ +local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) { int err = ZIP_OK; uInt size_global_comment = 0; @@ -1874,8 +1819,7 @@ static int Write_GlobalComment(zip64_internal* zi, const char* global_comment) return err; } -extern int ZEXPORT zipClose (zipFile file, const char* global_comment) -{ +extern int ZEXPORT zipClose(zipFile file, const char* global_comment) { zip64_internal* zi; int err = 0; uLong size_centraldir = 0; @@ -1916,7 +1860,7 @@ extern int ZEXPORT zipClose (zipFile file, const char* global_comment) } free_linkedlist(&(zi->central_dir)); - pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) { ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); @@ -1936,15 +1880,14 @@ extern int ZEXPORT zipClose (zipFile file, const char* global_comment) err = ZIP_ERRNO; #ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); + free(zi->globalcomment); #endif - TRYFREE(zi); + free(zi); return err; } -extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) -{ +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) { char* p = pData; int size = 0; char* pNewHeader; @@ -1954,10 +1897,10 @@ extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHe int retVal = ZIP_OK; - if(pData == NULL || *dataLen < 4) + if(pData == NULL || dataLen == NULL || *dataLen < 4) return ZIP_PARAMERROR; - pNewHeader = (char*)ALLOC(*dataLen); + pNewHeader = (char*)ALLOC((unsigned)*dataLen); pTmp = pNewHeader; while(p < (pData + *dataLen)) @@ -1996,7 +1939,7 @@ extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHe else retVal = ZIP_ERRNO; - TRYFREE(pNewHeader); + free(pNewHeader); return retVal; } diff --git a/storage/connect/zip.h b/storage/connect/zip.h index 8aaebb62343..5fc08413241 100644 --- a/storage/connect/zip.h +++ b/storage/connect/zip.h @@ -88,12 +88,12 @@ typedef voidp zipFile; /* tm_zip contain date/time info */ typedef struct tm_zip_s { - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years - [1980..2044] */ } tm_zip; typedef struct @@ -113,8 +113,8 @@ typedef const char* zipcharpc; #define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_ADDINZIP (2) -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +extern zipFile ZEXPORT zipOpen(const char *pathname, int append); +extern zipFile ZEXPORT zipOpen64(const void *pathname, int append); /* Create a zipfile. pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on @@ -131,41 +131,46 @@ extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another - Of couse, you can use RAW reading and writing to copy the file you did not want delte + Of course, you can use RAW reading and writing to copy the file you did not want delete */ -extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, +extern zipFile ZEXPORT zipOpen2(const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def); + +extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, - zlib_filefunc_def* pzlib_filefunc_def)); + zlib_filefunc64_def* pzlib_filefunc_def); -extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc64_def* pzlib_filefunc_def)); +extern zipFile ZEXPORT zipOpen3(const void *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def); -extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level)); +extern int ZEXPORT zipOpenNewFileInZip(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level); -extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int zip64)); +extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int zip64); /* Open a file in the ZIP for writing. @@ -184,70 +189,69 @@ extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, */ -extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw)); +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw); -extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int zip64)); +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int zip64); /* Same than zipOpenNewFileInZip, except if raw=1, we write raw file */ -extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting)); +extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting); -extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - int zip64 - )); +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + int zip64); /* Same than zipOpenNewFileInZip2, except @@ -256,47 +260,45 @@ extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, crcForCrypting : crc of file to compress (needed for crypting) */ -extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase - )); +extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase); -extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase, - int zip64 - )); +extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase, + int zip64); /* Same than zipOpenNewFileInZip4, except versionMadeBy : value for Version made by field @@ -304,25 +306,25 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, */ -extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, - const void* buf, - unsigned len)); +extern int ZEXPORT zipWriteInFileInZip(zipFile file, + const void* buf, + unsigned len); /* Write data in the zipfile */ -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +extern int ZEXPORT zipCloseFileInZip(zipFile file); /* Close the current file in the zipfile */ -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, + uLong uncompressed_size, + uLong crc32); -extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, - ZPOS64_T uncompressed_size, - uLong crc32)); +extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32); /* Close the current file in the zipfile, for file opened with @@ -330,14 +332,14 @@ extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, uncompressed_size and crc32 are value for the uncompressed size */ -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); +extern int ZEXPORT zipClose(zipFile file, + const char* global_comment); /* Close the zipfile */ -extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader); /* zipRemoveExtraInfoBlock - Added by Mathias Svensson From 15bd7e0b89eef3c85fbca61b4d738decbbc27dd3 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 22 Jan 2024 15:39:09 +0100 Subject: [PATCH 068/121] "New" version of CC (in fact no changes) --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index ae565eea90d..f1a72768d42 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit ae565eea90dd3053a5a7857e7cdad93342dbc645 +Subproject commit f1a72768d4256416e5c0bf01b254c303f6135bd0 From 117388225c1361c0a5b67d6115db1a6b54b43c2c Mon Sep 17 00:00:00 2001 From: Rex Date: Fri, 12 Jan 2024 09:32:34 +1200 Subject: [PATCH 069/121] MDEV-33165 Incorrect result interceptor passed to mysql_explain_union() Statements affect by this bug are all SQL statements that 1) prefixed with "EXPLAIN" 2) have a lower level join structure created for a union subquery. A bug in select_describe() passed an incorrect "result" object to mysql_explain_union(), resulting in unpredictable behaviour and out of context calls. Reviewed by: Oleksandr Byelkin, sanja@mariadb.com --- mysql-test/main/explain.result | 40 ++++++++++++++++++++++++++++++++++ mysql-test/main/explain.test | 23 +++++++++++++++++++ sql/sql_select.cc | 3 +-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/explain.result b/mysql-test/main/explain.result index 8a9fd3c5390..85d889a8c5f 100644 --- a/mysql-test/main/explain.result +++ b/mysql-test/main/explain.result @@ -459,3 +459,43 @@ id select_type table type possible_keys key key_len ref rows Extra NULL UNION RESULT ALL NULL NULL NULL NULL NULL Warnings: Note 1249 Select 4 was reduced during optimization +# +# End of 10.4 tests +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); +EXPLAIN SELECT * FROM t1, t2 WHERE t2.b IN (SELECT 5 UNION SELECT 6); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +EXPLAIN DELETE t2 FROM t1, t2 WHERE t2.b IN (SELECT 5 UNION SELECT 6); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +prepare stmt from "EXPLAIN DELETE t2 FROM t1, t2 WHERE t2.b IN (SELECT 5 UNION SELECT 6)"; +execute stmt; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +execute stmt; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +DROP TABLE t1, t2; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/explain.test b/mysql-test/main/explain.test index fc789601788..a546242d6aa 100644 --- a/mysql-test/main/explain.test +++ b/mysql-test/main/explain.test @@ -370,3 +370,26 @@ drop table t1; explain VALUES ( (VALUES (2))) UNION VALUES ( (SELECT 3)); + +--echo # +--echo # End of 10.4 tests +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (3),(4); + +EXPLAIN SELECT * FROM t1, t2 WHERE t2.b IN (SELECT 5 UNION SELECT 6); +EXPLAIN DELETE t2 FROM t1, t2 WHERE t2.b IN (SELECT 5 UNION SELECT 6); +prepare stmt from "EXPLAIN DELETE t2 FROM t1, t2 WHERE t2.b IN (SELECT 5 UNION SELECT 6)"; +execute stmt; +execute stmt; + +# Cleanup + +DROP TABLE t1, t2; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 21132651b07..2794c8d51e9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -27953,7 +27953,6 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, bool distinct,const char *message) { THD *thd=join->thd; - select_result *result=join->result; DBUG_ENTER("select_describe"); if (join->select_lex->pushdown_select) @@ -27988,7 +27987,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (unit->explainable()) { - if (mysql_explain_union(thd, unit, result)) + if (mysql_explain_union(thd, unit, unit->result)) DBUG_VOID_RETURN; } } From bc2f155019cfd416d173d7312280350e4e08a367 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 22 Jan 2024 11:38:26 +1100 Subject: [PATCH 070/121] Deb autobake: ready with noble (Ubuntu 24.04) Still not ready to support mariadb-plugin-rocks by distro. pmem (despite its EOL on Intel) and liburing are available on Noble (24.04). Its unclear why they where disabled in lunar/jammy. Too unstable to change now so introduce to 24.04 and see how it goes during testing. --- debian/autobake-deb.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index 8fb03093977..c958c38065f 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -150,13 +150,6 @@ in add_lsb_base_depends ;& "lunar"|"mantic") - # mariadb-plugin-rocksdb s390x not supported by us (yet) - # ubuntu doesn't support mips64el yet, so keep this just - # in case something changes. - if [[ ! "$architecture" =~ amd64|arm64|ppc64el|s390x ]] - then - remove_rocksdb_tools - fi if [[ ! "$architecture" =~ amd64|arm64|ppc64el ]] then disable_pmem @@ -165,6 +158,15 @@ in then replace_uring_with_aio fi + ;& + "noble") + # mariadb-plugin-rocksdb s390x not supported by us (yet) + # ubuntu doesn't support mips64el yet, so keep this just + # in case something changes. + if [[ ! "$architecture" =~ amd64|arm64|ppc64el|s390x ]] + then + remove_rocksdb_tools + fi ;; *) echo "Error: Unknown release '$LSBNAME'" >&2 From 13e49b783f4572d89badadb05f793d4333c881ac Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Fri, 19 Jan 2024 18:40:53 +0700 Subject: [PATCH 071/121] sql_test.cc compile fix --- sql/sql_test.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 1474099c030..47acdaf8d7c 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -29,14 +29,17 @@ #include #include "sql_connect.h" #include "thread_cache.h" -#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2) + #if defined(HAVE_MALLOC_H) #include -#elif defined(HAVE_SYS_MALLOC_H) -#include -#elif defined(HAVE_MALLOC_ZONE) -#include #endif + +#if defined(HAVE_SYS_MALLOC_H) +#include +#endif + +#if defined(HAVE_MALLOC_ZONE) +#include #endif #ifdef HAVE_EVENT_SCHEDULER From 5ce6a352b6e7b84b96dadebb943132c8b2f97391 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 22 Jan 2024 14:23:44 +1100 Subject: [PATCH 072/121] MDEV-33290: Disable ColumnStore based on boost version MCOL-5611 supporting with Boost-1.80, the version "next_prime" disappears from https://github.com/boostorg/unordered/blob/boost-1.79.0/include/boost/unordered/detail/implementation.hpp makes it the currenly highest supported versions. Lets check this version. While CMake-3.19+ supports version ranges in package determinations this isn't supported for Boost in Cmake-3.28. So we check for the 1.80 and don't compile ColumnStore. --- storage/columnstore/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/columnstore/CMakeLists.txt b/storage/columnstore/CMakeLists.txt index 81690f14b15..644f0ca8984 100644 --- a/storage/columnstore/CMakeLists.txt +++ b/storage/columnstore/CMakeLists.txt @@ -15,6 +15,13 @@ IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") add_subdirectory(columnstore) + # https://jira.mariadb.org/browse/MCOL-5611 + FIND_PACKAGE(Boost 1.80.0 COMPONENTS system filesystem thread regex date_time chrono atomic) + IF (Boost_FOUND) + MESSAGE_ONCE(CS_NO_BOOST "Boost Libraries >= 1.80.0 not supported!") + return() + ENDIF() + IF(TARGET columnstore) # Needed to bump the component changes up to the main scope APPEND_FOR_CPACK(CPACK_COMPONENTS_ALL) From 90cd712b84d69d64a8e6fa162b560602be87903a Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Mon, 13 Nov 2023 23:21:49 +0530 Subject: [PATCH 073/121] MDEV-27087: Add thread ID and database / table, where the error occured to SQL error plugin New plugin variable "with_db_and_thread_info" is added which prints the thread id and databse name to the logfile. the value is stored in variable "with_db_and_thread_info" log_sql_errors() is responsible for printing in the log. If detailed is enabled, print thread id and database name both, otherwise skip it. --- mysql-test/include/read_head.inc | 30 +++++++++++++++++++ mysql-test/suite/plugins/r/mdev_27087.result | 12 ++++++++ .../suite/plugins/r/sql_error_log.result | 1 + mysql-test/suite/plugins/t/mdev_27087.opt | 1 + mysql-test/suite/plugins/t/mdev_27087.test | 18 +++++++++++ plugin/sql_errlog/sql_errlog.c | 24 +++++++++++++-- 6 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 mysql-test/include/read_head.inc create mode 100644 mysql-test/suite/plugins/r/mdev_27087.result create mode 100644 mysql-test/suite/plugins/t/mdev_27087.opt create mode 100644 mysql-test/suite/plugins/t/mdev_27087.test diff --git a/mysql-test/include/read_head.inc b/mysql-test/include/read_head.inc new file mode 100644 index 00000000000..98818d76703 --- /dev/null +++ b/mysql-test/include/read_head.inc @@ -0,0 +1,30 @@ +# Purpose: +# Print first LINES_TO_READ from a file. +# The environment variables SEARCH_FILE and LINES_TO_READ must be set +# before sourcing this routine. +# Use: +# When the test is slow ( example because of ASAN build) then it +# may not flush the lines when 'cat' command is called and the +# test could fail with missing lines. Hence this can be used to +# to print first N lines. +# + +perl; + +use strict; + +my $search_file = $ENV{SEARCH_FILE} or die "SEARCH_FILE not set"; +my $lines_to_read = $ENV{LINES_TO_READ} or die "LINES_TO_READ not set"; + +open(FILE, '<', $search_file) or die "Can't open file $search_file: $!"; + +my $line_count = 0; +while ($line_count < $lines_to_read and my $line = ) +{ + print $line; + $line_count++; +} + +close(FILE); + +EOF diff --git a/mysql-test/suite/plugins/r/mdev_27087.result b/mysql-test/suite/plugins/r/mdev_27087.result new file mode 100644 index 00000000000..9cffceaa4db --- /dev/null +++ b/mysql-test/suite/plugins/r/mdev_27087.result @@ -0,0 +1,12 @@ +show variables like 'sql_error_log%'; +Variable_name Value +sql_error_log_filename sql_errors.log +sql_error_log_rate 1 +sql_error_log_rotate OFF +sql_error_log_rotations 9 +sql_error_log_size_limit 1000000 +sql_error_log_with_db_and_thread_info ON +set global sql_error_log_rate=1; +select * from t_doesnt_exist; +ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist +THREAD_ID DATABASE_NAME TIME HOSTNAME ERROR 1146: Table 'test.t_doesnt_exist' doesn't exist : select * from t_doesnt_exist diff --git a/mysql-test/suite/plugins/r/sql_error_log.result b/mysql-test/suite/plugins/r/sql_error_log.result index 98dfe0374fd..585457f5ee2 100644 --- a/mysql-test/suite/plugins/r/sql_error_log.result +++ b/mysql-test/suite/plugins/r/sql_error_log.result @@ -8,6 +8,7 @@ sql_error_log_rate 1 sql_error_log_rotate OFF sql_error_log_rotations 9 sql_error_log_size_limit 1000000 +sql_error_log_with_db_and_thread_info OFF set global sql_error_log_rate=1; select * from t_doesnt_exist; ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist diff --git a/mysql-test/suite/plugins/t/mdev_27087.opt b/mysql-test/suite/plugins/t/mdev_27087.opt new file mode 100644 index 00000000000..53c8ec8f812 --- /dev/null +++ b/mysql-test/suite/plugins/t/mdev_27087.opt @@ -0,0 +1 @@ +--plugin-load-add=$SQL_ERRLOG_SO --sql-error-log-with-db-and-thread-info=1 diff --git a/mysql-test/suite/plugins/t/mdev_27087.test b/mysql-test/suite/plugins/t/mdev_27087.test new file mode 100644 index 00000000000..ddd677b6681 --- /dev/null +++ b/mysql-test/suite/plugins/t/mdev_27087.test @@ -0,0 +1,18 @@ +--source include/not_embedded.inc + +if (!$SQL_ERRLOG_SO) { + skip No SQL_ERROR_LOG plugin; +} + +show variables like 'sql_error_log%'; +set global sql_error_log_rate=1; +--error ER_NO_SUCH_TABLE +select * from t_doesnt_exist; + +let $MYSQLD_DATADIR= `SELECT @@datadir`; +--let SEARCH_FILE= $MYSQLD_DATADIR/sql_errors.log +--let LINES_TO_READ=1 +--replace_regex /[1-9]* test [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID DATABASE_NAME TIME HOSTNAME / +--source include/read_head.inc + +remove_file $MYSQLD_DATADIR/sql_errors.log; diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c index e0ebd6b7737..619dc2e227e 100644 --- a/plugin/sql_errlog/sql_errlog.c +++ b/plugin/sql_errlog/sql_errlog.c @@ -39,6 +39,7 @@ static unsigned int rate; static unsigned long long size_limit; static unsigned int rotations; static char rotate; +static char with_db_and_thread_info; static unsigned int count; LOGGER_HANDLE *logfile; @@ -67,12 +68,19 @@ static MYSQL_SYSVAR_STR(filename, filename, "The file to log sql errors to", NULL, NULL, "sql_errors.log"); +static MYSQL_SYSVAR_BOOL(with_db_and_thread_info, with_db_and_thread_info, + PLUGIN_VAR_READONLY | PLUGIN_VAR_OPCMDARG, + "Show details about thread id and database name in the log", + NULL, NULL, + 0); + static struct st_mysql_sys_var* vars[] = { MYSQL_SYSVAR(rate), MYSQL_SYSVAR(size_limit), MYSQL_SYSVAR(rotations), MYSQL_SYSVAR(rotate), MYSQL_SYSVAR(filename), + MYSQL_SYSVAR(with_db_and_thread_info), NULL }; @@ -93,12 +101,24 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), count = 0; (void) localtime_r(&event_time, &t); - logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d " + if (with_db_and_thread_info) + { + logger_printf(logfile, "%llu %s %04d-%02d-%02d %2d:%02d:%02d " + "%s ERROR %d: %s : %s \n", + event->general_thread_id, event->database.str, t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, + event->general_user, event->general_error_code, + event->general_command, event->general_query); + } + else + { + logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d " "%s ERROR %d: %s : %s\n", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, event->general_user, event->general_error_code, event->general_command, event->general_query); + } } } } @@ -157,7 +177,7 @@ maria_declare_plugin(sql_errlog) 0x0100, NULL, vars, - "1.0", + "1.1", MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; From ee7cc0a466ac8a781f326d35cfa52d352a3ffc8c Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Tue, 9 Jan 2024 15:19:29 +0530 Subject: [PATCH 074/121] MDEV-32906: The SQL error plugin prints (null) as database if the mariadb client is not using any database to execute the SQL. Analysis: When there is no database, the database string is NULL so (null) gets printed. Fix: Print NULL instead of (null) because when there is no database SELECT DATABASE() return NULL. SO NULL is more appropriate choice. --- mysql-test/suite/plugins/r/mdev_27087.result | 12 ----- .../plugins/r/sql_error_log_withdbinfo.result | 37 ++++++++++++++ mysql-test/suite/plugins/t/mdev_27087.test | 18 ------- ...27087.opt => sql_error_log_withdbinfo.opt} | 2 +- .../plugins/t/sql_error_log_withdbinfo.test | 49 +++++++++++++++++++ plugin/sql_errlog/sql_errlog.c | 20 ++++++-- 6 files changed, 104 insertions(+), 34 deletions(-) delete mode 100644 mysql-test/suite/plugins/r/mdev_27087.result create mode 100644 mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result delete mode 100644 mysql-test/suite/plugins/t/mdev_27087.test rename mysql-test/suite/plugins/t/{mdev_27087.opt => sql_error_log_withdbinfo.opt} (62%) create mode 100644 mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test diff --git a/mysql-test/suite/plugins/r/mdev_27087.result b/mysql-test/suite/plugins/r/mdev_27087.result deleted file mode 100644 index 9cffceaa4db..00000000000 --- a/mysql-test/suite/plugins/r/mdev_27087.result +++ /dev/null @@ -1,12 +0,0 @@ -show variables like 'sql_error_log%'; -Variable_name Value -sql_error_log_filename sql_errors.log -sql_error_log_rate 1 -sql_error_log_rotate OFF -sql_error_log_rotations 9 -sql_error_log_size_limit 1000000 -sql_error_log_with_db_and_thread_info ON -set global sql_error_log_rate=1; -select * from t_doesnt_exist; -ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist -THREAD_ID DATABASE_NAME TIME HOSTNAME ERROR 1146: Table 'test.t_doesnt_exist' doesn't exist : select * from t_doesnt_exist diff --git a/mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result b/mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result new file mode 100644 index 00000000000..649d91269b6 --- /dev/null +++ b/mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result @@ -0,0 +1,37 @@ +show variables like 'sql_error_log%'; +Variable_name Value +sql_error_log_filename sql_errors.log +sql_error_log_rate 1 +sql_error_log_rotate OFF +sql_error_log_rotations 9 +sql_error_log_size_limit 1000000 +sql_error_log_with_db_and_thread_info ON +set global sql_error_log_rate=1; +# Trying to set the variable at runtime +SET sql_error_log_with_db_and_thread_info=OFF; +ERROR HY000: Variable 'sql_error_log_with_db_and_thread_info' is a read only variable +# +# Using test database from mtr +# +DROP DATABASE db; +ERROR HY000: Can't drop database 'db'; database doesn't exist +# +# Using no database at all +# +DROP DATABASE test; +DROP DATABASE db; +ERROR HY000: Can't drop database 'db'; database doesn't exist +# +# Using database with name `NULL` +# +CREATE DATABASE `NULL`; +USE `NULL`; +DROP DATABASE db; +ERROR HY000: Can't drop database 'db'; database doesn't exist +THREAD_ID `test` TIME HOSTNAME ERROR 1238: Variable 'sql_error_log_with_db_and_thread_info' is a read only variable : SET sql_error_log_with_db_and_thread_info=OFF +THREAD_ID `test` TIME HOSTNAME ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db +THREAD_ID NULL TIME HOSTNAME ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db +THREAD_ID `NULL` TIME HOSTNAME ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db +DROP DATABASE `NULL`; +# Reset +CREATE DATABASE test; diff --git a/mysql-test/suite/plugins/t/mdev_27087.test b/mysql-test/suite/plugins/t/mdev_27087.test deleted file mode 100644 index ddd677b6681..00000000000 --- a/mysql-test/suite/plugins/t/mdev_27087.test +++ /dev/null @@ -1,18 +0,0 @@ ---source include/not_embedded.inc - -if (!$SQL_ERRLOG_SO) { - skip No SQL_ERROR_LOG plugin; -} - -show variables like 'sql_error_log%'; -set global sql_error_log_rate=1; ---error ER_NO_SUCH_TABLE -select * from t_doesnt_exist; - -let $MYSQLD_DATADIR= `SELECT @@datadir`; ---let SEARCH_FILE= $MYSQLD_DATADIR/sql_errors.log ---let LINES_TO_READ=1 ---replace_regex /[1-9]* test [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID DATABASE_NAME TIME HOSTNAME / ---source include/read_head.inc - -remove_file $MYSQLD_DATADIR/sql_errors.log; diff --git a/mysql-test/suite/plugins/t/mdev_27087.opt b/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.opt similarity index 62% rename from mysql-test/suite/plugins/t/mdev_27087.opt rename to mysql-test/suite/plugins/t/sql_error_log_withdbinfo.opt index 53c8ec8f812..7d502896977 100644 --- a/mysql-test/suite/plugins/t/mdev_27087.opt +++ b/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.opt @@ -1 +1 @@ ---plugin-load-add=$SQL_ERRLOG_SO --sql-error-log-with-db-and-thread-info=1 +--plugin-load-add=$SQL_ERRLOG_SO --sql-error-log-with-db-and-thread-info=1 --lower_case_table_names=2 diff --git a/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test b/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test new file mode 100644 index 00000000000..bddcc14e275 --- /dev/null +++ b/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test @@ -0,0 +1,49 @@ +--source include/not_embedded.inc + +if (!$SQL_ERRLOG_SO) { + skip No SQL_ERROR_LOG plugin; +} + +show variables like 'sql_error_log%'; +set global sql_error_log_rate=1; + +let $MYSQLD_DATADIR= `SELECT @@datadir`; + +--echo # Trying to set the variable at runtime + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET sql_error_log_with_db_and_thread_info=OFF; + +--echo # +--echo # Using test database from mtr +--echo # + +--error ER_DB_DROP_EXISTS +DROP DATABASE db; + +--echo # +--echo # Using no database at all +--echo # + +DROP DATABASE test; +--error ER_DB_DROP_EXISTS +DROP DATABASE db; + +--echo # +--echo # Using database with name `NULL` +--echo # +CREATE DATABASE `NULL`; +USE `NULL`; +--error ER_DB_DROP_EXISTS +DROP DATABASE db; + + +--let SEARCH_FILE= $MYSQLD_DATADIR/sql_errors.log +--let LINES_TO_READ=4 +--replace_regex /[1-9]* `NULL` [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID `NULL` TIME HOSTNAME / /[1-9]* `test` [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID `test` TIME HOSTNAME / /[1-9]* NULL [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID NULL TIME HOSTNAME / +--source include/read_head.inc + +DROP DATABASE `NULL`; + +--echo # Reset +CREATE DATABASE test; diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c index 619dc2e227e..a3f36fc966e 100644 --- a/plugin/sql_errlog/sql_errlog.c +++ b/plugin/sql_errlog/sql_errlog.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -91,6 +92,7 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), { const struct mysql_event_general *event = (const struct mysql_event_general*)ev; + if (rate && event->event_subclass == MYSQL_AUDIT_GENERAL_ERROR) { @@ -103,12 +105,24 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), (void) localtime_r(&event_time, &t); if (with_db_and_thread_info) { - logger_printf(logfile, "%llu %s %04d-%02d-%02d %2d:%02d:%02d " + if (event->database.str) + { + logger_printf(logfile, "%llu %`s %04d-%02d-%02d %2d:%02d:%02d " "%s ERROR %d: %s : %s \n", event->general_thread_id, event->database.str, t.tm_year + 1900, - t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, - event->general_user, event->general_error_code, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, + t.tm_sec, event->general_user, event->general_error_code, event->general_command, event->general_query); + } + else + { + logger_printf(logfile, "%llu %s %04d-%02d-%02d %2d:%02d:%02d " + "%s ERROR %d: %s : %s \n", + event->general_thread_id, "NULL", t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, + t.tm_sec, event->general_user, event->general_error_code, + event->general_command, event->general_query); + } } else { From 81d01855fecbf60b87dbac5b44d3db7c0e6f37ef Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 23 Jan 2024 13:22:58 +0400 Subject: [PATCH 075/121] MDEV-28651 quote(NULL) returns incorrect result in view ('NU' instead of 'NULL') Item_func_quote did not calculate its max_length correctly for nullable arguments. Fix: In case if the argument is nullable, reserve at least 4 characters so the string "NULL" fits. --- mysql-test/main/func_str.result | 27 +++++++++++++++++++++++++++ mysql-test/main/func_str.test | 22 ++++++++++++++++++++++ sql/item_strfunc.h | 3 +++ 3 files changed, 52 insertions(+) diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index b4f25c34848..a47c149fb0d 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -5286,3 +5286,30 @@ ERROR 42000: Incorrect parameter count in the call to native function 'DECODE' # # End of 10.4 tests # +# +# Start of 10.5 tests +# +# +# MDEV-28651 quote(NULL) returns incorrect result in view ('NU' instead of 'NULL') +# +CREATE VIEW v1 AS SELECT quote(NULL); +SELECT * FROM v1; +quote(NULL) +NULL +DESCRIBE v1; +Field Type Null Key Default Extra +quote(NULL) varbinary(4) YES NULL +CREATE TABLE t1 AS SELECT * FROM v1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `quote(NULL)` varbinary(4) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +SELECT * FROM t1; +quote(NULL) +NULL +DROP TABLE t1; +DROP VIEW v1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test index b452ed1fe90..69161349720 100644 --- a/mysql-test/main/func_str.test +++ b/mysql-test/main/func_str.test @@ -2329,3 +2329,25 @@ SELECT DECODE(NULL, NULL, NULL); --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-28651 quote(NULL) returns incorrect result in view ('NU' instead of 'NULL') +--echo # + +CREATE VIEW v1 AS SELECT quote(NULL); +SELECT * FROM v1; +DESCRIBE v1; +CREATE TABLE t1 AS SELECT * FROM v1; +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +DROP VIEW v1; + + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index f9dba473e71..e770c3bff98 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1504,6 +1504,9 @@ public: collation.set(args[0]->collation); ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 + 2 * collation.collation->mbmaxlen; + // NULL argument is returned as a string "NULL" without quotes + if (args[0]->maybe_null) + set_if_bigger(max_result_length, 4 * collation.collation->mbmaxlen); max_length= (uint32) MY_MIN(max_result_length, MAX_BLOB_WIDTH); return FALSE; } From 7af50e4df456761c433838f0e65e88b9117f298c Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 8 Nov 2023 16:57:58 -0700 Subject: [PATCH 076/121] MDEV-32551: "Read semi-sync reply magic number error" warnings on master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rpl_semi_sync_slave_enabled_consistent.test and the first part of the commit message comes from Brandon Nesterenko. A test to show how to induce the "Read semi-sync reply magic number error" message on a primary. In short, if semi-sync is turned on during the hand-shake process between a primary and replica, but later a user negates the rpl_semi_sync_slave_enabled variable while the replica's IO thread is running; if the io thread exits, the replica can skip a necessary call to kill_connection() in repl_semisync_slave.slave_stop() due to its reliance on a global variable. Then, the replica will send a COM_QUIT packet to the primary on an active semi-sync connection, causing the magic number error. The test in this patch exits the IO thread by forcing an error; though note a call to STOP SLAVE could also do this, but it ends up needing more synchronization. That is, the STOP SLAVE command also tries to kill the VIO of the replica, which makes a race with the IO thread to try and send the COM_QUIT before this happens (which would need more debug_sync to get around). See THD::awake_no_mutex for details as to the killing of the replica’s vio. Notes: - The MariaDB documentation does not make it clear that when one enables semi-sync replication it does not matter if one enables it first in the master or slave. Any order works. Changes done: - The rpl_semi_sync_slave_enabled variable is now a default value for when semisync is started. The variable does not anymore affect semisync if it is already running. This fixes the original reported bug. Internally we now use repl_semisync_slave.get_slave_enabled() instead of rpl_semi_sync_slave_enabled. To check if semisync is active on should check the @@rpl_semi_sync_slave_status variable (as before). - The semisync protocol conflicts in the way that the original MySQL/MariaDB client-server protocol was designed (client-server send and reply packets are strictly ordered and includes a packet number to allow one to check if a packet is lost). When using semi-sync the master and slave can send packets at 'any time', so packet numbering does not work. The 'solution' has been that each communication starts with packet number 1, but in some cases there is still a chance that the packet number check can fail. Fixed by adding a flag (pkt_nr_can_be_reset) in the NET struct that one can use to signal that packet number checking should not be done. This is flag is set when semi-sync is used. - Added Master_info::semi_sync_reply_enabled to allow one to configure some slaves with semisync and other other slaves without semisync. Removed global variable semi_sync_need_reply that would not work with multi-master. - Repl_semi_sync_master::report_reply_packet() can now recognize the COM_QUIT packet from semisync slave and not give a "Read semi-sync reply magic number error" error for this case. The slave will be removed from the Ack listener. - On Windows, don't stop semisync Ack listener just because one slave connection is using socket_id > FD_SETSIZE. - Removed busy loop in Ack_receiver::run() by using "Self-pipe trick" to signal new slave and stop Ack_receiver. - Changed some Repl_semi_sync_slave functions that always returns 0 from int to void. - Added Repl_semi_sync_slave::slave_reconnect(). - Removed dummy_function Repl_semi_sync_slave::reset_slave(). - Removed some duplicate semisync notes from the error log. - Add test of "if (get_slave_enabled() && semi_sync_need_reply)" before calling Repl_semi_sync_slave::slave_reply(). (Speeds up the code as we can skip all initializations). - If epl_semisync_slave.slave_reply() fails, we disable semisync for that connection. - We do not call semisync.switch_off() if there are no active slaves. Instead we check in Repl_semi_sync_master::commit_trx() if there are no active threads. This simplices the code. - Changed assert() to DBUG_ASSERT() to ensure that the DBUG log is flushed in case of asserts. - Removed the internal rpl_semi_sync_slave_status as it is not needed anymore. The @@rpl_semi_sync_slave_status status variable is now mapped to rpl_semi_sync_enabled. - Removed rpl_semi_sync_slave_enabled as it is not needed anymore. Repl_semi_sync_slave::get_slave_enabled() contains the active status. - Added checking that we do not add a slave twice with Ack_receiver::add_slave(). This could happen with old code. - Removed Repl_semi_sync_master::check_and_switch() as it is not needed anymore. - Ensure that when we call Ack_receiver::remove_slave() that the slave is removed from the listener before function returns. - Call listener.listen_on_sockets() outside of mutex for better performance and less contested mutex. - Ensure that listening is ignoring newly added slaves when checking for responses. - Fixed the master ack_receiver listener is not killed if there are no connected slaves (and thus stop semisync handling of future connections). This could happen if all slaves sockets where would be marked as unreliable. - Added unlink() to base_ilist_iterator and remove() to I_List_iterator. This enables us to remove 'dead' slaves in Ack_recever::run(). - kill_zombie_dump_threads() now does killing of dump threads properly. - It can now kill several threads (should be impossible but could happen if IO slaves reconnects very fast). - We now wait until the dump thread is done before starting the dump. - Added an error if kill_zombie_dump_threads() fails. - Set thd->variables.server_id before calling kill_zombie_dump_threads(). This simplies the code. - Added a lot of comments both in code and tests. - Removed DBUG_EVALUATE_IF "failed_slave_start" as it is not used. Test changes: - rpl.rpl_session_var2 added which runs rpl.rpl_session_var test with semisync enabled. - Some timings changed slight with startup of slave which caused rpl_binlog_dump_slave_gtid_state_info.text to fail as it checked the error log file before the slave had started properly. Fixed by adding wait_for_pattern_in_file.inc that allows waiting for the pattern to appear in the log file. - Tests have been updated so that we first set rpl_semi_sync_master_enabled on the master and then set rpl_semi_sync_slave_enabled on the slaves (this is according to how the MariaDB documentation document how to setup semi-sync). - Error text "Master server does not have semi-sync enabled" has been replaced with "Master server does not support semi-sync" for the case when the master supports semi-sync but semi-sync is not enabled. Other things: - Some trivial cleanups in Repl_semi_sync_master::update_sync_header(). - We should in 11.3 changed the default value for rpl-semi-sync-master-wait-no-slave from TRUE to FALSE as the TRUE does not make much sense as default. The main difference with using FALSE is that we do not wait for semisync Ack if there are no slave threads. In the case of TRUE we wait once, which did not bring any notable benefits except slower startup of master configured for using semisync. Co-author: Brandon Nesterenko This solves the problem reported in MDEV-32960 where a new slave may not be registered in time and the master disables semi sync because of that. --- include/mysql_com.h | 2 +- mysql-test/include/search_pattern_in_file.inc | 40 +++- .../include/wait_for_pattern_in_file.inc | 56 ++++++ mysql-test/main/mysqld--help.result | 2 +- .../binlog_encryption/rpl_semi_sync.result | 13 +- ...l_binlog_dump_slave_gtid_state_info.result | 4 + .../suite/rpl/r/rpl_circular_semi_sync.result | 4 + .../suite/rpl/r/rpl_delayed_slave.result | 3 + mysql-test/suite/rpl/r/rpl_semi_sync.result | 13 +- .../rpl/r/rpl_semi_sync_after_sync.result | 13 +- .../rpl/r/rpl_semi_sync_after_sync_row.result | 13 +- .../suite/rpl/r/rpl_semi_sync_event.result | 1 - .../r/rpl_semi_sync_event_after_sync.result | 1 - .../rpl/r/rpl_semi_sync_fail_over.result | 2 +- ..._sync_no_missed_ack_after_add_slave.result | 48 +++++ ..._semi_sync_slave_enabled_consistent.result | 35 ++++ .../r/rpl_semi_sync_slave_reply_fail.result | 5 +- .../rpl/r/rpl_semisync_ali_issues.result | 3 +- mysql-test/suite/rpl/r/rpl_session_var.result | 11 ++ .../suite/rpl/r/rpl_session_var2.result | 69 +++++++ ...rpl_binlog_dump_slave_gtid_state_info.test | 8 +- .../suite/rpl/t/rpl_circular_semi_sync.test | 11 ++ mysql-test/suite/rpl/t/rpl_delayed_slave.test | 6 + .../rpl/t/rpl_mariadb_slave_capability.test | 2 +- mysql-test/suite/rpl/t/rpl_semi_sync.test | 20 +- .../suite/rpl/t/rpl_semi_sync_event.test | 1 - .../suite/rpl/t/rpl_semi_sync_fail_over.test | 2 +- ...emi_sync_no_missed_ack_after_add_slave.cnf | 12 ++ ...mi_sync_no_missed_ack_after_add_slave.test | 122 ++++++++++++ ...pl_semi_sync_slave_enabled_consistent.test | 73 ++++++++ .../rpl/t/rpl_semi_sync_slave_reply_fail.test | 5 +- .../suite/rpl/t/rpl_semisync_ali_issues.test | 1 - mysql-test/suite/rpl/t/rpl_session_var.test | 6 + .../suite/rpl/t/rpl_session_var2-master.opt | 1 + .../suite/rpl/t/rpl_session_var2-slave.opt | 1 + mysql-test/suite/rpl/t/rpl_session_var2.test | 3 + .../t/rpl_shutdown_wait_semisync_slaves.test | 3 + .../r/sysvars_server_notembedded.result | 2 +- sql/log.cc | 2 +- sql/mysqld.cc | 2 +- sql/net_serv.cc | 33 +++- sql/rpl_mi.cc | 2 +- sql/rpl_mi.h | 6 + sql/semisync_master.cc | 175 +++++++++--------- sql/semisync_master.h | 2 - sql/semisync_master_ack_receiver.cc | 120 +++++++++--- sql/semisync_master_ack_receiver.h | 146 ++++++++++++--- sql/semisync_slave.cc | 153 ++++++++------- sql/semisync_slave.h | 22 ++- sql/slave.cc | 59 ++++-- sql/sql_class.cc | 8 - sql/sql_class.h | 9 + sql/sql_list.h | 18 +- sql/sql_parse.cc | 27 ++- sql/sql_repl.cc | 102 +++++++--- sql/sql_repl.h | 2 +- sql/sys_vars.cc | 26 +-- 57 files changed, 1171 insertions(+), 360 deletions(-) create mode 100644 mysql-test/include/wait_for_pattern_in_file.inc create mode 100644 mysql-test/suite/rpl/r/rpl_semi_sync_no_missed_ack_after_add_slave.result create mode 100644 mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result create mode 100644 mysql-test/suite/rpl/r/rpl_session_var2.result create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test create mode 100644 mysql-test/suite/rpl/t/rpl_session_var2-master.opt create mode 100644 mysql-test/suite/rpl/t/rpl_session_var2-slave.opt create mode 100644 mysql-test/suite/rpl/t/rpl_session_var2.test diff --git a/include/mysql_com.h b/include/mysql_com.h index b837704c19d..2cdda8457ea 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -477,7 +477,7 @@ typedef struct st_net { char net_skip_rest_factor; my_bool thread_specific_malloc; unsigned char compress; - my_bool unused3; /* Please remove with the next incompatible ABI change. */ + my_bool pkt_nr_can_be_reset; /* Pointer to query object in query cache, do not equal NULL (0) for queries in cache that have not stored its results yet diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index a899a9294cc..3105f7f9077 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -51,12 +51,15 @@ # Created: 2011-11-11 mleich # +--error 0,1 perl; use strict; die "SEARCH_FILE not set" unless $ENV{SEARCH_FILE}; my @search_files= glob($ENV{SEARCH_FILE}); my $search_pattern= $ENV{SEARCH_PATTERN} or die "SEARCH_PATTERN not set"; my $search_range= $ENV{SEARCH_RANGE}; + my $silent= $ENV{SEARCH_SILENT}; + my $search_result= 0; my $content; foreach my $search_file (@search_files) { open(FILE, '<', $search_file) || die("Can't open file $search_file: $!"); @@ -89,16 +92,39 @@ perl; { @matches=($content =~ /$search_pattern/gm); } - my $res=@matches ? "FOUND " . scalar(@matches) : "NOT FOUND"; + my $res; + if (@matches) + { + $res="FOUND " . scalar(@matches); + $search_result= 1; + } + else + { + $res= "NOT FOUND"; + } $ENV{SEARCH_FILE} =~ s{^.*?([^/\\]+)$}{$1}; - if ($ENV{SEARCH_OUTPUT} eq "matches") { - foreach (@matches) { - print $_ . "\n"; - } - } else { - print "$res /$search_pattern/ in $ENV{SEARCH_FILE}\n"; + if (!$silent || $search_result) + { + if ($ENV{SEARCH_OUTPUT} eq "matches") + { + foreach (@matches) + { + print $_ . "\n"; + } + } + else + { + print "$res /$search_pattern/ in $ENV{SEARCH_FILE}\n"; + } } die "$ENV{SEARCH_ABORT}\n" if $ENV{SEARCH_ABORT} && $res =~ /^$ENV{SEARCH_ABORT}/; + exit($search_result != 1); EOF + +let $SEARCH_RESULT= 1; # Found pattern +if ($errno) +{ + let $SEARCH_RESULT= 0; # Did not find pattern +} diff --git a/mysql-test/include/wait_for_pattern_in_file.inc b/mysql-test/include/wait_for_pattern_in_file.inc new file mode 100644 index 00000000000..52226acd2da --- /dev/null +++ b/mysql-test/include/wait_for_pattern_in_file.inc @@ -0,0 +1,56 @@ +# ==== Purpose ==== +# +# Waits until pattern comes into log file or until a timeout is reached. +# This is a timeout wrapper for search_pattern_in_file.inc +# +# +# ==== Usage ==== +# +# [--let $timeout= NUMBER in seconds] +# For other parameters, check search_pattern_in_file.inc + +--let $wait_save_keep_include_silent=$keep_include_silent +--let $include_filename= wait_for_pattern_in_file.inc +--source include/begin_include_file.inc +--let $keep_include_silent= 1 + +let $_timeout= $timeout; +if (!$_timeout) +{ + let $_timeout= 10; + if ($VALGRIND_TEST) + { + let $_timeout= 30; + } +} + +let $_timeout_counter=`SELECT $_timeout * 10`; +let SEARCH_SILENT=1; + +let $_continue= 1; +while ($_continue) +{ + source include/search_pattern_in_file.inc; + if ($SEARCH_RESULT) + { + # Found match + let $_continue= 0; + } + if (!$SEARCH_RESULT) + { + dec $_timeout_counter; + if ($_timeout_counter == 1) + { + let $SEARCH_SILENT= 0; + } + if (!$_timeout_counter) + { + let $_continue= 0; + } + } +} + +let SEARCH_SILENT=0; + +--source include/end_include_file.inc +--let $keep_include_silent=$wait_save_keep_include_silent diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 62119751ac2..219bad22528 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1138,7 +1138,7 @@ The following specify which files/extra groups are read (specified before remain The tracing level for semi-sync replication. --rpl-semi-sync-master-wait-no-slave Wait until timeout when no semi-synchronous replication - slave available (enabled by default). + slave is available. (Defaults to on; use --skip-rpl-semi-sync-master-wait-no-slave to disable.) --rpl-semi-sync-master-wait-point=name Should transaction wait for semi-sync ack after having diff --git a/mysql-test/suite/binlog_encryption/rpl_semi_sync.result b/mysql-test/suite/binlog_encryption/rpl_semi_sync.result index d18bd1efda7..cff1a73996d 100644 --- a/mysql-test/suite/binlog_encryption/rpl_semi_sync.result +++ b/mysql-test/suite/binlog_encryption/rpl_semi_sync.result @@ -6,7 +6,6 @@ call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); connection master; @@ -26,7 +25,7 @@ set global rpl_semi_sync_slave_enabled= 0; # Main test of semi-sync replication start here # connection master; -set global rpl_semi_sync_master_timeout= 60000; +set global rpl_semi_sync_master_timeout= 2000; [ default state of semi-sync on master should be OFF ] show variables like 'rpl_semi_sync_master_enabled'; Variable_name Value @@ -161,11 +160,15 @@ connection slave; # Test semi-sync master will switch OFF after one transaction # timeout waiting for slave reply. # +connection master; +show status like "Rpl_semi_sync_master_status"; +Variable_name Value +Rpl_semi_sync_master_status ON connection slave; include/stop_slave.inc connection master; include/kill_binlog_dump_threads.inc -set global rpl_semi_sync_master_timeout= 5000; +set global rpl_semi_sync_master_timeout= 2000; [ master status should be ON ] show status like 'Rpl_semi_sync_master_no_tx'; Variable_name Value @@ -315,6 +318,8 @@ include/kill_binlog_dump_threads.inc connection slave; include/start_slave.inc connection master; +connection slave; +connection master; create table t1 (a int) engine = ENGINE_TYPE; insert into t1 values (1); insert into t1 values (2), (3); @@ -357,6 +362,8 @@ show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection master; +connection slave; +connection master; [ master semi-sync should be ON ] show status like 'Rpl_semi_sync_master_clients'; Variable_name Value diff --git a/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result b/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result index 98688df7273..38a9afd4d02 100644 --- a/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result +++ b/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result @@ -8,6 +8,7 @@ CHANGE MASTER TO MASTER_USE_GTID=current_pos; include/start_slave.inc connection master; "Test Case 1: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('')" +include/wait_for_pattern_in_file.inc FOUND 1 /using_gtid\(1\), gtid\(\'\'\).*/ in mysqld.1.err connection slave; include/stop_slave.inc @@ -15,6 +16,7 @@ CHANGE MASTER TO MASTER_USE_GTID=no; include/start_slave.inc connection master; "Test Case 2: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(0), gtid('')" +include/wait_for_pattern_in_file.inc FOUND 1 /using_gtid\(0\), gtid\(\'\'\).*/ in mysqld.1.err CREATE TABLE t (f INT) ENGINE=INNODB; INSERT INTO t VALUES(10); @@ -25,6 +27,7 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos; include/start_slave.inc connection master; "Test Case 3: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2')" +include/wait_for_pattern_in_file.inc FOUND 1 /using_gtid\(1\), gtid\(\'0-1-2\'\).*/ in mysqld.1.err SET @@SESSION.gtid_domain_id=10; INSERT INTO t VALUES(20); @@ -35,6 +38,7 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos; include/start_slave.inc connection master; "Test Case 4: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2,10-1-1')" +include/wait_for_pattern_in_file.inc FOUND 1 /using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).*/ in mysqld.1.err "===== Clean up =====" connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result b/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result index 5664b7913d2..2596d346479 100644 --- a/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result +++ b/mysql-test/suite/rpl/r/rpl_circular_semi_sync.result @@ -1,5 +1,7 @@ include/master-slave.inc [connection master] +connection server_2; +call mtr.add_suppression("Timeout waiting for reply of binlog"); # Master server_1 and Slave server_2 initialization ... connection server_2; include/stop_slave.inc @@ -40,6 +42,8 @@ set @@global.rpl_semi_sync_master_enabled = 1; INSERT INTO t1(a) VALUES (2); include/save_master_gtid.inc connection server_1; +include/stop_slave.inc +include/start_slave.inc # # the successful sync is a required proof # diff --git a/mysql-test/suite/rpl/r/rpl_delayed_slave.result b/mysql-test/suite/rpl/r/rpl_delayed_slave.result index e7daa3328ce..a48e98b0006 100644 --- a/mysql-test/suite/rpl/r/rpl_delayed_slave.result +++ b/mysql-test/suite/rpl/r/rpl_delayed_slave.result @@ -67,6 +67,9 @@ include/stop_slave.inc # CHANGE MASTER TO MASTER_DELAY = 2*T include/start_slave.inc connection master; +INSERT INTO t1 VALUES ('Syncing slave', 5); +connection slave; +connection master; INSERT INTO t1 VALUES (delay_on_slave(1), 6); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync.result b/mysql-test/suite/rpl/r/rpl_semi_sync.result index d18bd1efda7..cff1a73996d 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync.result @@ -6,7 +6,6 @@ call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); connection master; @@ -26,7 +25,7 @@ set global rpl_semi_sync_slave_enabled= 0; # Main test of semi-sync replication start here # connection master; -set global rpl_semi_sync_master_timeout= 60000; +set global rpl_semi_sync_master_timeout= 2000; [ default state of semi-sync on master should be OFF ] show variables like 'rpl_semi_sync_master_enabled'; Variable_name Value @@ -161,11 +160,15 @@ connection slave; # Test semi-sync master will switch OFF after one transaction # timeout waiting for slave reply. # +connection master; +show status like "Rpl_semi_sync_master_status"; +Variable_name Value +Rpl_semi_sync_master_status ON connection slave; include/stop_slave.inc connection master; include/kill_binlog_dump_threads.inc -set global rpl_semi_sync_master_timeout= 5000; +set global rpl_semi_sync_master_timeout= 2000; [ master status should be ON ] show status like 'Rpl_semi_sync_master_no_tx'; Variable_name Value @@ -315,6 +318,8 @@ include/kill_binlog_dump_threads.inc connection slave; include/start_slave.inc connection master; +connection slave; +connection master; create table t1 (a int) engine = ENGINE_TYPE; insert into t1 values (1); insert into t1 values (2), (3); @@ -357,6 +362,8 @@ show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection master; +connection slave; +connection master; [ master semi-sync should be ON ] show status like 'Rpl_semi_sync_master_clients'; Variable_name Value diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync.result b/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync.result index f2240817489..301e4c819e4 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync.result @@ -7,7 +7,6 @@ call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); connection master; @@ -27,7 +26,7 @@ set global rpl_semi_sync_slave_enabled= 0; # Main test of semi-sync replication start here # connection master; -set global rpl_semi_sync_master_timeout= 60000; +set global rpl_semi_sync_master_timeout= 2000; [ default state of semi-sync on master should be OFF ] show variables like 'rpl_semi_sync_master_enabled'; Variable_name Value @@ -162,11 +161,15 @@ connection slave; # Test semi-sync master will switch OFF after one transaction # timeout waiting for slave reply. # +connection master; +show status like "Rpl_semi_sync_master_status"; +Variable_name Value +Rpl_semi_sync_master_status ON connection slave; include/stop_slave.inc connection master; include/kill_binlog_dump_threads.inc -set global rpl_semi_sync_master_timeout= 5000; +set global rpl_semi_sync_master_timeout= 2000; [ master status should be ON ] show status like 'Rpl_semi_sync_master_no_tx'; Variable_name Value @@ -316,6 +319,8 @@ include/kill_binlog_dump_threads.inc connection slave; include/start_slave.inc connection master; +connection slave; +connection master; create table t1 (a int) engine = ENGINE_TYPE; insert into t1 values (1); insert into t1 values (2), (3); @@ -358,6 +363,8 @@ show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection master; +connection slave; +connection master; [ master semi-sync should be ON ] show status like 'Rpl_semi_sync_master_clients'; Variable_name Value diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync_row.result b/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync_row.result index fcced801d65..6c7db8ca342 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync_row.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_after_sync_row.result @@ -7,7 +7,6 @@ call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); connection master; @@ -27,7 +26,7 @@ set global rpl_semi_sync_slave_enabled= 0; # Main test of semi-sync replication start here # connection master; -set global rpl_semi_sync_master_timeout= 60000; +set global rpl_semi_sync_master_timeout= 2000; [ default state of semi-sync on master should be OFF ] show variables like 'rpl_semi_sync_master_enabled'; Variable_name Value @@ -162,11 +161,15 @@ connection slave; # Test semi-sync master will switch OFF after one transaction # timeout waiting for slave reply. # +connection master; +show status like "Rpl_semi_sync_master_status"; +Variable_name Value +Rpl_semi_sync_master_status ON connection slave; include/stop_slave.inc connection master; include/kill_binlog_dump_threads.inc -set global rpl_semi_sync_master_timeout= 5000; +set global rpl_semi_sync_master_timeout= 2000; [ master status should be ON ] show status like 'Rpl_semi_sync_master_no_tx'; Variable_name Value @@ -316,6 +319,8 @@ include/kill_binlog_dump_threads.inc connection slave; include/start_slave.inc connection master; +connection slave; +connection master; create table t1 (a int) engine = ENGINE_TYPE; insert into t1 values (1); insert into t1 values (2), (3); @@ -358,6 +363,8 @@ show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection master; +connection slave; +connection master; [ master semi-sync should be ON ] show status like 'Rpl_semi_sync_master_clients'; Variable_name Value diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_event.result b/mysql-test/suite/rpl/r/rpl_semi_sync_event.result index 917e7c2b02b..b1eb623cc99 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_event.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_event.result @@ -7,7 +7,6 @@ call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); connection master; diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_event_after_sync.result b/mysql-test/suite/rpl/r/rpl_semi_sync_event_after_sync.result index 24daf0d72b5..34af8d31315 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_event_after_sync.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_event_after_sync.result @@ -8,7 +8,6 @@ call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); connection master; diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result index 8956eee2d2f..1c94c239fc6 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result @@ -5,6 +5,7 @@ include/stop_slave.inc connection server_1; RESET MASTER; SET @@global.max_binlog_size= 4096; +set @@global.rpl_semi_sync_master_enabled = 1; connection server_2; RESET MASTER; SET @@global.max_binlog_size= 4096; @@ -14,7 +15,6 @@ CHANGE MASTER TO master_use_gtid= slave_pos; include/start_slave.inc connection server_1; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; -set @@global.rpl_semi_sync_master_enabled = 1; set @@global.rpl_semi_sync_master_wait_point=AFTER_SYNC; CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; INSERT INTO t1 VALUES (1, 'dummy1'); diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_no_missed_ack_after_add_slave.result b/mysql-test/suite/rpl/r/rpl_semi_sync_no_missed_ack_after_add_slave.result new file mode 100644 index 00000000000..19fed30ffb7 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_no_missed_ack_after_add_slave.result @@ -0,0 +1,48 @@ +include/rpl_init.inc [topology=1->2,1->3] +connection server_1; +set @old_enabled= @@global.rpl_semi_sync_master_enabled; +set @old_timeout= @@global.rpl_semi_sync_master_timeout; +set global rpl_semi_sync_master_enabled= 1; +set global rpl_semi_sync_master_timeout= 500; +connection server_2; +include/stop_slave.inc +set @old_enabled= @@global.rpl_semi_sync_slave_enabled; +set @old_dbug= @@global.debug_dbug; +set global rpl_semi_sync_slave_enabled= 1; +set global debug_dbug="+d,simulate_delay_semisync_slave_reply"; +include/start_slave.inc +connection server_3; +include/stop_slave.inc +set @old_enabled= @@global.rpl_semi_sync_slave_enabled; +set global rpl_semi_sync_slave_enabled= 1; +include/start_slave.inc +# Ensure primary recognizes both replicas are semi-sync +connection server_1; +connection server_1; +create table t1 (a int); +connection server_2; +# Verifying server_2 did not send ACK +connection server_3; +# Verifying server_3 did send ACK +connection server_1; +# Verifying master's semi-sync status is still ON (This failed pre-MDEV-32960 fixes) +# Verifying rpl_semi_sync_master_yes_tx incremented +# +# Cleanup +connection server_2; +set global rpl_semi_sync_slave_enabled= @old_enabled; +set global debug_dbug= @old_dbug; +include/stop_slave.inc +connection server_3; +set global rpl_semi_sync_slave_enabled= @old_enabled; +include/stop_slave.inc +connection server_1; +set global rpl_semi_sync_master_enabled= @old_enabled; +set global rpl_semi_sync_master_timeout= @old_timeout; +drop table t1; +connection server_2; +include/start_slave.inc +connection server_3; +include/start_slave.inc +include/rpl_end.inc +# End of rpl_semi_sync_no_missed_ack_after_add_slave.test diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result new file mode 100644 index 00000000000..99c3124957f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result @@ -0,0 +1,35 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression("Replication event checksum verification failed"); +call mtr.add_suppression("could not queue event from master"); +# +# Set up a semisync connection +connection master; +set @@global.rpl_semi_sync_master_enabled= ON; +connection slave; +stop slave io_thread; +set @@global.rpl_semi_sync_slave_enabled= ON; +set @old_dbug= @@global.debug_dbug; +set @@global.debug_dbug= "+d,corrupt_queue_event"; +set @@global.debug_dbug= "+d,pause_before_io_read_event"; +set @@global.debug_dbug= "+d,placeholder"; +start slave io_thread; +# Disable semi-sync on the slave while the IO thread is active +set debug_sync='now wait_for io_thread_at_read_event'; +set @@global.rpl_semi_sync_slave_enabled= OFF; +set debug_sync='now signal io_thread_continue_read_event'; +# Waiting for the slave to stop with the error from corrupt_queue_event +connection slave; +include/wait_for_slave_io_error.inc [errno=1595,1743] +# Sleep 1 to give time for Ack_receiver to receive COM_QUIT +include/assert_grep.inc [Check that there is no 'Read semi-sync reply magic number error' in error log.] +# +# Cleanup +connection slave; +include/stop_slave.inc +set @@global.debug_dbug= @old_dbug; +include/start_slave.inc +connection master; +set @@global.rpl_semi_sync_master_enabled= default; +include/rpl_end.inc +# End of rpl_semi_sync_slave_enabled_consistent.test diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result index e482da7d0fc..3c9cf71aeca 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_reply_fail.result @@ -4,6 +4,7 @@ connection slave; include/stop_slave.inc connection master; call mtr.add_suppression("Timeout waiting for reply of binlog*"); +call mtr.add_suppression("Master server does not read semi-sync messages*"); set global rpl_semi_sync_master_enabled = ON; SET @@GLOBAL.rpl_semi_sync_master_timeout=100; create table t1 (i int); @@ -15,8 +16,8 @@ SET GLOBAL debug_dbug="+d,semislave_failed_net_flush"; include/start_slave.inc connection master; connection slave; -"Assert that the net_fulsh() reply failed is present in slave error log. -FOUND 1 /Semi-sync slave net_flush\(\) reply failed/ in mysqld.2.err +"Assert that Master server does not read semi-sync messages" is present in slave error log. +FOUND 1 /Master server does not read semi-sync messages/ in mysqld.2.err "Assert that Slave IO thread is up and running." SHOW STATUS LIKE 'Slave_running'; Variable_name Value diff --git a/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result b/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result index 530bbac633b..d7f87ae5fd3 100644 --- a/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result +++ b/mysql-test/suite/rpl/r/rpl_semisync_ali_issues.result @@ -14,7 +14,6 @@ CALL mtr.add_suppression("Failed on request_dump()*"); CALL mtr.add_suppression("Semi-sync master failed on*"); CALL mtr.add_suppression("Master command COM_BINLOG_DUMP failed*"); CALL mtr.add_suppression("on master failed*"); -CALL mtr.add_suppression("Master server does not support semi-sync*"); CALL mtr.add_suppression("Semi-sync slave net_flush*"); CALL mtr.add_suppression("Failed to flush master info*"); CALL mtr.add_suppression("Request to stop slave SQL Thread received while apply*"); @@ -196,7 +195,7 @@ Variable_name Value Rpl_semi_sync_master_clients 0 show status like 'Rpl_semi_sync_master_status'; Variable_name Value -Rpl_semi_sync_master_status OFF +Rpl_semi_sync_master_status ON connection slave; START SLAVE IO_THREAD; include/wait_for_slave_io_to_start.inc diff --git a/mysql-test/suite/rpl/r/rpl_session_var.result b/mysql-test/suite/rpl/r/rpl_session_var.result index 67863583f8d..f9794df3be7 100644 --- a/mysql-test/suite/rpl/r/rpl_session_var.result +++ b/mysql-test/suite/rpl/r/rpl_session_var.result @@ -1,5 +1,16 @@ include/master-slave.inc [connection master] +select @@rpl_semi_sync_master_enabled; +@@rpl_semi_sync_master_enabled +0 +connection slave; +select @@rpl_semi_sync_slave_enabled; +@@rpl_semi_sync_slave_enabled +0 +show status like "rpl_semi_sync_slave_status"; +Variable_name Value +Rpl_semi_sync_slave_status OFF +connection master; drop table if exists t1; Warnings: Note 1051 Unknown table 'test.t1' diff --git a/mysql-test/suite/rpl/r/rpl_session_var2.result b/mysql-test/suite/rpl/r/rpl_session_var2.result new file mode 100644 index 00000000000..645eca02492 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_session_var2.result @@ -0,0 +1,69 @@ +include/master-slave.inc +[connection master] +select @@rpl_semi_sync_master_enabled; +@@rpl_semi_sync_master_enabled +1 +connection slave; +select @@rpl_semi_sync_slave_enabled; +@@rpl_semi_sync_slave_enabled +1 +show status like "rpl_semi_sync_slave_status"; +Variable_name Value +Rpl_semi_sync_slave_status ON +connection master; +drop table if exists t1; +Warnings: +Note 1051 Unknown table 'test.t1' +create table t1(a varchar(100),b int); +set @@session.sql_mode=pipes_as_concat; +insert into t1 values('My'||'SQL', 1); +set @@session.sql_mode=default; +insert into t1 values('1'||'2', 2); +select * from t1 where b<3 order by a; +a b +1 2 +MySQL 1 +connection slave; +select * from t1 where b<3 order by a; +a b +1 2 +MySQL 1 +connection master; +set @@session.sql_mode=ignore_space; +insert into t1 values(password ('MySQL'), 3); +set @@session.sql_mode=ansi_quotes; +create table "t2" ("a" int); +drop table t1, t2; +set @@session.sql_mode=default; +create table t1(a int auto_increment primary key); +create table t2(b int, a int); +set @@session.sql_auto_is_null=1; +insert into t1 values(null); +insert into t2 select 1,a from t1 where a is null; +set @@session.sql_auto_is_null=0; +insert into t1 values(null); +insert into t2 select 2,a from t1 where a is null; +select * from t2 order by b; +b a +1 1 +connection slave; +select * from t2 order by b; +b a +1 1 +connection master; +drop table t1,t2; +connection slave; +connection master; +CREATE TABLE t1 ( +`id` int(11) NOT NULL auto_increment, +`data` varchar(100), +PRIMARY KEY (`id`) +) ENGINE=MyISAM; +INSERT INTO t1(data) VALUES(SESSION_USER()); +connection slave; +SELECT length(data) < 100 FROM t1; +length(data) < 100 +1 +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test index f26e9565671..942a23576c4 100644 --- a/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test +++ b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test @@ -59,7 +59,7 @@ if(!$log_error_) --let SEARCH_FILE=$log_error_ --let SEARCH_RANGE=-50000 --let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'\'\).* ---source include/search_pattern_in_file.inc +--source include/wait_for_pattern_in_file.inc --connection slave --source include/stop_slave.inc @@ -71,7 +71,7 @@ CHANGE MASTER TO MASTER_USE_GTID=no; --let SEARCH_FILE=$log_error_ --let SEARCH_RANGE=-50000 --let SEARCH_PATTERN=using_gtid\(0\), gtid\(\'\'\).* ---source include/search_pattern_in_file.inc +--source include/wait_for_pattern_in_file.inc CREATE TABLE t (f INT) ENGINE=INNODB; INSERT INTO t VALUES(10); save_master_pos; @@ -89,7 +89,7 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos; --let SEARCH_FILE=$log_error_ --let SEARCH_RANGE=-50000 --let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2\'\).* ---source include/search_pattern_in_file.inc +--source include/wait_for_pattern_in_file.inc SET @@SESSION.gtid_domain_id=10; INSERT INTO t VALUES(20); save_master_pos; @@ -107,7 +107,7 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos; --let SEARCH_FILE=$log_error_ --let SEARCH_RANGE=-50000 --let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).* ---source include/search_pattern_in_file.inc +--source include/wait_for_pattern_in_file.inc --echo "===== Clean up =====" --connection slave diff --git a/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test index 267fa621945..e533c54bdc1 100644 --- a/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test +++ b/mysql-test/suite/rpl/t/rpl_circular_semi_sync.test @@ -7,6 +7,9 @@ --source include/have_binlog_format_mixed.inc --source include/master-slave.inc +connection server_2; +call mtr.add_suppression("Timeout waiting for reply of binlog"); + # The following tests prove # A. # no out-of-order gtid error is done to the stict gtid mode semisync @@ -66,10 +69,18 @@ evalp CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, ma --connection server_2 set @@global.gtid_strict_mode = true; set @@global.rpl_semi_sync_master_enabled = 1; + +# The following command is likely to cause the slave master is not yet setup +# for semi-sync + INSERT INTO t1(a) VALUES (2); --source include/save_master_gtid.inc --connection server_1 +# Update slave to notice that server_2 now has rpl_semi_sync_master_enabled +--source include/stop_slave.inc +--source include/start_slave.inc + --echo # --echo # the successful sync is a required proof --echo # diff --git a/mysql-test/suite/rpl/t/rpl_delayed_slave.test b/mysql-test/suite/rpl/t/rpl_delayed_slave.test index 7dd7b9cf6d9..b1a5a2eaee2 100644 --- a/mysql-test/suite/rpl/t/rpl_delayed_slave.test +++ b/mysql-test/suite/rpl/t/rpl_delayed_slave.test @@ -189,6 +189,12 @@ eval CHANGE MASTER TO MASTER_DELAY = $time2; --enable_query_log --source include/start_slave.inc +# Ensure that slave has started properly +--connection master +INSERT INTO t1 VALUES ('Syncing slave', 5); +--save_master_pos +--sync_slave_with_master + --connection master INSERT INTO t1 VALUES (delay_on_slave(1), 6); --save_master_pos diff --git a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test index 18228e75e2e..de6af2f7b2e 100644 --- a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test +++ b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test @@ -11,7 +11,7 @@ set @old_master_binlog_checksum= @@global.binlog_checksum; # empty Gtid_list event # # Test this by binlog rotation before we log any GTIDs. -connection slave; +sync_slave_with_master; --source include/stop_slave.inc --echo # Test slave with no capability gets dummy event, which is ignored. set @old_dbug= @@global.debug_dbug; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync.test index c3cd918b5fc..12f2d473c2b 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync.test @@ -17,7 +17,6 @@ call mtr.add_suppression("Read semi-sync reply"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); connection master; @@ -51,7 +50,7 @@ set global rpl_semi_sync_slave_enabled= 0; connection master; -set global rpl_semi_sync_master_timeout= 60000; # 60s +set global rpl_semi_sync_master_timeout= 2000; # 2s echo [ default state of semi-sync on master should be OFF ]; show variables like 'rpl_semi_sync_master_enabled'; @@ -195,12 +194,16 @@ sync_slave_with_master; --echo # Test semi-sync master will switch OFF after one transaction --echo # timeout waiting for slave reply. --echo # + +connection master; +show status like "Rpl_semi_sync_master_status"; + connection slave; source include/stop_slave.inc; connection master; --source include/kill_binlog_dump_threads.inc -set global rpl_semi_sync_master_timeout= 5000; +set global rpl_semi_sync_master_timeout= 2000; # The first semi-sync check should be on because after slave stop, # there are no transactions on the master. @@ -232,8 +235,8 @@ show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_no_tx'; show status like 'Rpl_semi_sync_master_yes_tx'; -# Semi-sync status on master is now OFF, so all these transactions -# will be replicated asynchronously. +# Semi-sync status on master is now ON, but there are no slaves attached, +# so all these transactions will be replicated asynchronously. delete from t1 where a=10; delete from t1 where a=9; delete from t1 where a=8; @@ -367,6 +370,9 @@ let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 1; source include/wait_for_status_var.inc; +sync_slave_with_master; +connection master; + replace_result $engine_type ENGINE_TYPE; eval create table t1 (a int) engine = $engine_type; insert into t1 values (1); @@ -413,6 +419,10 @@ connection master; let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 1; source include/wait_for_status_var.inc; + +sync_slave_with_master; +connection master; + echo [ master semi-sync should be ON ]; show status like 'Rpl_semi_sync_master_clients'; show status like 'Rpl_semi_sync_master_status'; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test index d4df9b4041b..86e1522e6c4 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test @@ -14,7 +14,6 @@ call mtr.add_suppression("Unsafe statement written to the binary log using state call mtr.add_suppression("mysqld: Got an error reading communication packets"); connection slave; -call mtr.add_suppression("Master server does not support semi-sync"); call mtr.add_suppression("Semi-sync slave .* reply"); call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test index 6a691ae04f6..17d7b50d614 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test @@ -18,6 +18,7 @@ --connection server_1 RESET MASTER; SET @@global.max_binlog_size= 4096; +set @@global.rpl_semi_sync_master_enabled = 1; --connection server_2 RESET MASTER; @@ -29,7 +30,6 @@ CHANGE MASTER TO master_use_gtid= slave_pos; --connection server_1 ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; -set @@global.rpl_semi_sync_master_enabled = 1; set @@global.rpl_semi_sync_master_wait_point=AFTER_SYNC; CREATE TABLE t1 (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.cnf b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.cnf new file mode 100644 index 00000000000..cb7062d5602 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.cnf @@ -0,0 +1,12 @@ +!include include/default_mysqld.cnf + +[mysqld.1] + +[mysqld.2] + +[mysqld.3] + +[ENV] +SERVER_MYPORT_1= @mysqld.1.port +SERVER_MYPORT_2= @mysqld.2.port +SERVER_MYPORT_3= @mysqld.3.port diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test new file mode 100644 index 00000000000..c8870e47e00 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test @@ -0,0 +1,122 @@ +# +# This test ensures that a primary will listen for ACKs by newly added +# semi-sync connections connections, after a pre-existing connection is already +# established. MDEV-32960 reported that the newly added slave's ACK can be +# ignored if listen_on_sockets() does not timeout before +# rpl_semi_sync_master_timeout, and if the existing semi-sync connections fail +# to send ACKs, semi-sync is switched off. +# +# This test ensures this in a two-replica setup with a semi-sync timeout of +# 500ms, and delaying the ACK reply of the first-established replica by 800ms +# to force a timeout, and allowing the second replica to immediately ACK. +# +# References: +# MDEV-32960: Semi-sync ACKed Transaction can Timeout and Switch Off +# Semi-sync with Multiple Replicas +# +--source include/have_debug.inc +# binlog_format independent +--source include/have_binlog_format_statement.inc + +--let $rpl_topology= 1->2,1->3 +--source include/rpl_init.inc + + +--connection server_1 +set @old_enabled= @@global.rpl_semi_sync_master_enabled; +set @old_timeout= @@global.rpl_semi_sync_master_timeout; +set global rpl_semi_sync_master_enabled= 1; +set global rpl_semi_sync_master_timeout= 500; + +--connection server_2 +--source include/stop_slave.inc +set @old_enabled= @@global.rpl_semi_sync_slave_enabled; +set @old_dbug= @@global.debug_dbug; +set global rpl_semi_sync_slave_enabled= 1; +set global debug_dbug="+d,simulate_delay_semisync_slave_reply"; +--source include/start_slave.inc + +--connection server_3 +--source include/stop_slave.inc +set @old_enabled= @@global.rpl_semi_sync_slave_enabled; +set global rpl_semi_sync_slave_enabled= 1; +--source include/start_slave.inc + +--echo # Ensure primary recognizes both replicas are semi-sync +--connection server_1 +--let $status_var_value= 2 +--let $status_var= rpl_semi_sync_master_clients +--source include/wait_for_status_var.inc + +--let $master_ss_status= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_master_status', Value, 1) +if (`SELECT strcmp("$master_ss_status", "ON") != 0`) +{ + SHOW STATUS LIKE 'rpl_semi_sync_master_status'; + --die rpl_semi_sync_master_status should be ON to start +} + +--connection server_1 +--let $init_master_yes_tx= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_master_yes_tx', Value, 1) +create table t1 (a int); + +--connection server_2 +--echo # Verifying server_2 did not send ACK +--let $slave1_sent_ack= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_slave_send_ack', Value, 1) +if (`SELECT $slave1_sent_ack`) +{ + SHOW STATUS LIKE 'rpl_semi_sync_slave_send_ack'; + --die server_2 should not have sent semi-sync ACK to primary +} + +--connection server_3 +--echo # Verifying server_3 did send ACK +--let $slave2_sent_ack= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_slave_send_ack', Value, 1) +if (`SELECT NOT $slave2_sent_ack`) +{ + SHOW STATUS LIKE 'rpl_semi_sync_slave_send_ack'; + --die server_3 should have sent semi-sync ACK to primary +} + +--connection server_1 +--echo # Verifying master's semi-sync status is still ON (This failed pre-MDEV-32960 fixes) +let $master_ss_status= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_master_status', Value, 1); +if (`SELECT strcmp("$master_ss_status", "ON") != 0`) +{ + SHOW STATUS LIKE 'rpl_semi_sync_master_status'; + --die rpl_semi_sync_master_status should not have switched off after server_3 ACKed transaction +} + +--echo # Verifying rpl_semi_sync_master_yes_tx incremented +--let $cur_master_yes_tx= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_master_yes_tx', Value, 1) +if (`SELECT $cur_master_yes_tx != ($init_master_yes_tx + 1)`) +{ + --echo # Initial yes_tx: $init_master_yes_tx + --echo # Current yes_tx: $cur_master_yes_tx + --die rpl_semi_sync_master_yes_tx should have been incremented by primary +} + + +--echo # +--echo # Cleanup + +--connection server_2 +set global rpl_semi_sync_slave_enabled= @old_enabled; +set global debug_dbug= @old_dbug; +--source include/stop_slave.inc + +--connection server_3 +set global rpl_semi_sync_slave_enabled= @old_enabled; +--source include/stop_slave.inc + +--connection server_1 +set global rpl_semi_sync_master_enabled= @old_enabled; +set global rpl_semi_sync_master_timeout= @old_timeout; +drop table t1; + +--connection server_2 +--source include/start_slave.inc +--connection server_3 +--source include/start_slave.inc + +--source include/rpl_end.inc +--echo # End of rpl_semi_sync_no_missed_ack_after_add_slave.test diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test new file mode 100644 index 00000000000..9e388ab4419 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test @@ -0,0 +1,73 @@ +# +# MDEV-32551: "Read semi-sync reply magic number error" warnings on master +# +# Test that changing rpl_semi_sync_master_enabled after startup does not +# cause problems with semi-sync cleanup. +# + +--source include/have_debug.inc +--source include/have_debug_sync.inc + +# Test is binlog format independent, so save resources +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +call mtr.add_suppression("Replication event checksum verification failed"); +call mtr.add_suppression("could not queue event from master"); + +--echo # +--echo # Set up a semisync connection +--connection master +set @@global.rpl_semi_sync_master_enabled= ON; + +--connection slave +stop slave io_thread; +set @@global.rpl_semi_sync_slave_enabled= ON; +set @old_dbug= @@global.debug_dbug; + +# Force an error to abort out of the main IO thread loop +set @@global.debug_dbug= "+d,corrupt_queue_event"; + +# Pause the IO thread as soon as the main loop starts. Note we can't use +# processlist where "Waiting for master to send event" because the +# "corrupt_queue_event" will trigger before we can turn semisync OFF +set @@global.debug_dbug= "+d,pause_before_io_read_event"; + +# Because the other debug_dbug points are automatically negated when they are +# run, and there is a bug that if "-d" takes us to an empty debug string state, +# _all_ debug_print statements are output +set @@global.debug_dbug= "+d,placeholder"; + +start slave io_thread; + +--echo # Disable semi-sync on the slave while the IO thread is active +set debug_sync='now wait_for io_thread_at_read_event'; +set @@global.rpl_semi_sync_slave_enabled= OFF; +set debug_sync='now signal io_thread_continue_read_event'; + +--echo # Waiting for the slave to stop with the error from corrupt_queue_event +--connection slave +--let $slave_io_errno= 1595,1743 +--source include/wait_for_slave_io_error.inc + +--echo # Sleep 1 to give time for Ack_receiver to receive COM_QUIT +--sleep 1 + +--let $assert_text= Check that there is no 'Read semi-sync reply magic number error' in error log. +--let $assert_select=magic number error +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_count= 0 +--let $assert_only_after=CURRENT_TEST +--source include/assert_grep.inc + +--echo # +--echo # Cleanup +--connection slave +--source include/stop_slave.inc +set @@global.debug_dbug= @old_dbug; +--source include/start_slave.inc +--connection master +set @@global.rpl_semi_sync_master_enabled= default; + +--source include/rpl_end.inc +--echo # End of rpl_semi_sync_slave_enabled_consistent.test diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test index 2ebc092e33d..84462ed6426 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test @@ -31,6 +31,7 @@ --connection master call mtr.add_suppression("Timeout waiting for reply of binlog*"); +call mtr.add_suppression("Master server does not read semi-sync messages*"); --let $sav_timeout_master=`SELECT @@GLOBAL.rpl_semi_sync_master_timeout` set global rpl_semi_sync_master_enabled = ON; SET @@GLOBAL.rpl_semi_sync_master_timeout=100; @@ -54,9 +55,9 @@ if(!$log_error_) # does not know the location of its .err log, use default location let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; } ---echo "Assert that the net_fulsh() reply failed is present in slave error log. +--echo "Assert that Master server does not read semi-sync messages" is present in slave error log. --let SEARCH_FILE=$log_error_ ---let SEARCH_PATTERN=Semi-sync slave net_flush\(\) reply failed +--let SEARCH_PATTERN=Master server does not read semi-sync messages --source include/search_pattern_in_file.inc --echo "Assert that Slave IO thread is up and running." diff --git a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test index 5e6f350b191..c5c1daa4672 100644 --- a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test +++ b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test @@ -16,7 +16,6 @@ CALL mtr.add_suppression("Failed on request_dump()*"); CALL mtr.add_suppression("Semi-sync master failed on*"); CALL mtr.add_suppression("Master command COM_BINLOG_DUMP failed*"); CALL mtr.add_suppression("on master failed*"); -CALL mtr.add_suppression("Master server does not support semi-sync*"); CALL mtr.add_suppression("Semi-sync slave net_flush*"); CALL mtr.add_suppression("Failed to flush master info*"); CALL mtr.add_suppression("Request to stop slave SQL Thread received while apply*"); diff --git a/mysql-test/suite/rpl/t/rpl_session_var.test b/mysql-test/suite/rpl/t/rpl_session_var.test index cf3faa6578c..3ea6d5dabae 100644 --- a/mysql-test/suite/rpl/t/rpl_session_var.test +++ b/mysql-test/suite/rpl/t/rpl_session_var.test @@ -7,6 +7,12 @@ disable_query_log; call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); enable_query_log; +select @@rpl_semi_sync_master_enabled; +connection slave; +select @@rpl_semi_sync_slave_enabled; +show status like "rpl_semi_sync_slave_status"; +connection master; + drop table if exists t1; create table t1(a varchar(100),b int); set @@session.sql_mode=pipes_as_concat; diff --git a/mysql-test/suite/rpl/t/rpl_session_var2-master.opt b/mysql-test/suite/rpl/t/rpl_session_var2-master.opt new file mode 100644 index 00000000000..edb0c915bd6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_session_var2-master.opt @@ -0,0 +1 @@ +--rpl_semi_sync_master_enabled=1 --rpl_semi_sync_slave_enabled=1 diff --git a/mysql-test/suite/rpl/t/rpl_session_var2-slave.opt b/mysql-test/suite/rpl/t/rpl_session_var2-slave.opt new file mode 100644 index 00000000000..c9f3082ed07 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_session_var2-slave.opt @@ -0,0 +1 @@ +--rpl_semi_sync_slave_enabled=1 diff --git a/mysql-test/suite/rpl/t/rpl_session_var2.test b/mysql-test/suite/rpl/t/rpl_session_var2.test new file mode 100644 index 00000000000..cbf8a5cf316 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_session_var2.test @@ -0,0 +1,3 @@ +# Replication of session variables when semi-sync is on + +--source rpl_session_var.test diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test index 2c63df30fde..0547a97f681 100644 --- a/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test +++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test @@ -28,6 +28,9 @@ while (`SELECT $i <= $slaves`) --inc $i } +# The following script will restart master and slaves. This will also set +# rpl_semi_sync_master_enabled=0 + --source include/rpl_shutdown_wait_slaves.inc --let i= 2 while (`SELECT $i <= $slaves`) 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 319b86583fc..00c66ddf072 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3465,7 +3465,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME RPL_SEMI_SYNC_MASTER_WAIT_NO_SLAVE VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Wait until timeout when no semi-synchronous replication slave available (enabled by default). +VARIABLE_COMMENT Wait until timeout when no semi-synchronous replication slave is available. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/sql/log.cc b/sql/log.cc index 518f4df3f94..3ca387d5ab9 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -11011,7 +11011,7 @@ Recovery_context::Recovery_context() : prev_event_pos(0), last_gtid_standalone(false), last_gtid_valid(false), last_gtid_no2pc(false), last_gtid_engines(0), - do_truncate(rpl_semi_sync_slave_enabled), + do_truncate(repl_semisync_slave.get_slave_enabled()), truncate_validated(false), truncate_reset_done(false), truncate_set_in_1st(false), id_binlog(MAX_binlog_id), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF), gtid_maybe_to_truncate(NULL) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8b7888dfb79..2766bc00e3a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7404,7 +7404,7 @@ SHOW_VAR status_vars[]= { SHOW_FUNC_ENTRY("Rpl_semi_sync_master_net_avg_wait_time", &SHOW_FNAME(avg_net_wait_time)), {"Rpl_semi_sync_master_request_ack", (char*) &rpl_semi_sync_master_request_ack, SHOW_LONGLONG}, {"Rpl_semi_sync_master_get_ack", (char*)&rpl_semi_sync_master_get_ack, SHOW_LONGLONG}, - {"Rpl_semi_sync_slave_status", (char*) &rpl_semi_sync_slave_status, SHOW_BOOL}, + SHOW_FUNC_ENTRY("Rpl_semi_sync_slave_status", &rpl_semi_sync_enabled), {"Rpl_semi_sync_slave_send_ack", (char*) &rpl_semi_sync_slave_send_ack, SHOW_LONGLONG}, #endif /* HAVE_REPLICATION */ #ifdef HAVE_QUERY_CACHE diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 70e71d9a21b..3dff8442c6a 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -156,6 +156,7 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags) net->where_b = net->remain_in_buf=0; net->net_skip_rest_factor= 0; net->last_errno=0; + net->pkt_nr_can_be_reset= 0; net->thread_specific_malloc= MY_TEST(my_flags & MY_THREAD_SPECIFIC); net->thd= 0; #ifdef MYSQL_SERVER @@ -1057,8 +1058,10 @@ retry: { /* Probably in MIT threads */ if (retry_count++ < net->retry_count) continue; - EXTRA_DEBUG_fprintf(stderr, "%s: read looped with error %d, aborting thread\n", - my_progname,vio_errno(net->vio)); + EXTRA_DEBUG_fprintf(stderr, "%s: read looped with error %d on " + "file %lld, aborting thread\n", + my_progname, vio_errno(net->vio), + (longlong) vio_fd(net->vio)); } #ifndef MYSQL_SERVER if (length != 0 && vio_errno(net->vio) == SOCKET_EINTR) @@ -1094,19 +1097,31 @@ retry: #endif if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr) { -#ifndef MYSQL_SERVER - if (net->buff[net->where_b + 3] == (uchar) (net->pkt_nr -1)) + if (net->pkt_nr_can_be_reset) { /* - If the server was killed then the server may have missed the - last sent client packet and the packet numbering may be one off. + We are using a protocol like semi-sync where master and slave + sends packets in parallel. + Copy current one as it can be useful for debugging. */ - DBUG_PRINT("warning", ("Found possible out of order packets")); - expect_error_packet= 1; + net->pkt_nr= net->buff[net->where_b + 3]; } else + { +#ifndef MYSQL_SERVER + if (net->buff[net->where_b + 3] == (uchar) (net->pkt_nr -1)) + { + /* + If the server was killed then the server may have missed the + last sent client packet and the packet numbering may be one off. + */ + DBUG_PRINT("warning", ("Found possible out of order packets")); + expect_error_packet= 1; + } + else #endif - goto packets_out_of_order; + goto packets_out_of_order; + } } net->compress_pkt_nr= ++net->pkt_nr; #ifdef HAVE_COMPRESS diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 8322bcd3042..73c61af92c9 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -44,7 +44,7 @@ Master_info::Master_info(LEX_CSTRING *connection_name_arg, in_start_all_slaves(0), in_stop_all_slaves(0), in_flush_all_relay_logs(0), users(0), killed(0), total_ddl_groups(0), total_non_trans_groups(0), total_trans_groups(0), - do_accept_own_server_id(false) + do_accept_own_server_id(false), semi_sync_reply_enabled(0) { char *tmp; host[0] = 0; user[0] = 0; password[0] = 0; diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 92938ac2f94..5857e8e043d 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -376,6 +376,12 @@ class Master_info : public Slave_reporting_capability it must be ignored similarly to the replicate-same-server-id rule. */ bool do_accept_own_server_id; + /* + Set to 1 when semi_sync is enabled. Set to 0 if there is any transmit + problems to the slave, in which case any furter semi-sync reply is + ignored + */ + bool semi_sync_reply_enabled; }; int init_master_info(Master_info* mi, const char* master_info_fname, diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 670a6d8d9ed..9f30a8206a4 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -91,7 +91,9 @@ Active_tranx::Active_tranx(mysql_mutex_t *lock, for (int idx = 0; idx < m_num_entries; ++idx) m_trx_htb[idx] = NULL; +#ifdef EXTRA_DEBUG sql_print_information("Semi-sync replication initialized for transactions."); +#endif } Active_tranx::~Active_tranx() @@ -352,8 +354,7 @@ Repl_semi_sync_master::Repl_semi_sync_master() m_state(0), m_wait_point(0) { - strcpy(m_reply_file_name, ""); - strcpy(m_wait_file_name, ""); + m_reply_file_name[0]= m_wait_file_name[0]= 0; } int Repl_semi_sync_master::init_object() @@ -379,20 +380,10 @@ int Repl_semi_sync_master::init_object() { result = enable_master(); if (!result) - { result= ack_receiver.start(); /* Start the ACK thread. */ - /* - If rpl_semi_sync_master_wait_no_slave is disabled, let's temporarily - switch off semisync to avoid hang if there's none active slave. - */ - if (!rpl_semi_sync_master_wait_no_slave) - switch_off(); - } } else - { disable_master(); - } return result; } @@ -441,7 +432,7 @@ void Repl_semi_sync_master::disable_master() */ switch_off(); - assert(m_active_tranxs != NULL); + DBUG_ASSERT(m_active_tranxs != NULL); delete m_active_tranxs; m_active_tranxs = NULL; @@ -450,7 +441,6 @@ void Repl_semi_sync_master::disable_master() m_commit_file_name_inited = false; set_master_enabled(false); - sql_print_information("Semi-sync replication disabled on the master."); } unlock(); @@ -537,31 +527,34 @@ void Repl_semi_sync_master::add_slave() void Repl_semi_sync_master::remove_slave() { lock(); - rpl_semi_sync_master_clients--; - - /* Only switch off if semi-sync is enabled and is on */ - if (get_master_enabled() && is_on()) + if (!(--rpl_semi_sync_master_clients) && !rpl_semi_sync_master_wait_no_slave) { - /* If user has chosen not to wait if no semi-sync slave available - and the last semi-sync slave exits, turn off semi-sync on master - immediately. - */ - if (!rpl_semi_sync_master_wait_no_slave && - rpl_semi_sync_master_clients == 0) - switch_off(); + /* + Signal transactions waiting in commit_trx() that they do not have to + wait anymore. + */ + cond_broadcast(); } unlock(); } + +/* + Check report package + + @retval 0 ok + @retval 1 Error + @retval -1 Slave is going down (ok) +*/ + int Repl_semi_sync_master::report_reply_packet(uint32 server_id, const uchar *packet, ulong packet_len) { - int result= -1; + int result= 1; // Assume error char log_file_name[FN_REFLEN+1]; my_off_t log_file_pos; ulong log_file_len = 0; - DBUG_ENTER("Repl_semi_sync_master::report_reply_packet"); DBUG_EXECUTE_IF("semisync_corrupt_magic", @@ -569,7 +562,14 @@ int Repl_semi_sync_master::report_reply_packet(uint32 server_id, if (unlikely(packet[REPLY_MAGIC_NUM_OFFSET] != Repl_semi_sync_master::k_packet_magic_num)) { - sql_print_error("Read semi-sync reply magic number error"); + if (packet[0] == COM_QUIT && packet_len == 1) + { + /* Slave sent COM_QUIT as part of IO thread going down */ + sql_print_information("slave IO thread has stopped"); + DBUG_RETURN(-1); + } + else + sql_print_error("Read semi-sync reply magic number error"); goto l_end; } @@ -597,14 +597,13 @@ int Repl_semi_sync_master::report_reply_packet(uint32 server_id, rpl_semi_sync_master_get_ack++; report_reply_binlog(server_id, log_file_name, log_file_pos); - result= 0; + DBUG_RETURN(0); l_end: - if (result == -1) { char buf[256]; - octet2hex(buf, (const char*) packet, std::min(static_cast(sizeof(buf)-1), - packet_len)); + octet2hex(buf, (const char*) packet, + MY_MIN(sizeof(buf)-1, (size_t) packet_len)); sql_print_information("First bytes of the packet from semisync slave " "server-id %d: %s", server_id, buf); @@ -668,7 +667,7 @@ int Repl_semi_sync_master::report_reply_binlog(uint32 server_id, m_reply_file_name_inited = true; /* Remove all active transaction nodes before this point. */ - assert(m_active_tranxs != NULL); + DBUG_ASSERT(m_active_tranxs != NULL); m_active_tranxs->clear_active_tranx_nodes(log_file_name, log_file_pos); DBUG_PRINT("semisync", ("%s: Got reply at (%s, %lu)", @@ -809,6 +808,8 @@ int Repl_semi_sync_master::dump_start(THD* thd, (long) thd->variables.server_id, log_file, (ulong) log_pos); + /* Mark that semi-sync net->pkt_nr is not reliable */ + thd->net.pkt_nr_can_be_reset= 1; return 0; } @@ -827,8 +828,15 @@ void Repl_semi_sync_master::dump_end(THD* thd) int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, my_off_t trx_wait_binlog_pos) { + bool success= 0; DBUG_ENTER("Repl_semi_sync_master::commit_trx"); + if (!rpl_semi_sync_master_clients && !rpl_semi_sync_master_wait_no_slave) + { + rpl_semi_sync_master_no_transactions++; + DBUG_RETURN(0); + } + if (get_master_enabled() && trx_wait_binlog_name) { struct timespec start_ts; @@ -836,7 +844,7 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, int wait_result; PSI_stage_info old_stage; THD *thd= current_thd; - + bool aborted= 0; set_timespec(start_ts, 0); DEBUG_SYNC(thd, "rpl_semisync_master_commit_trx_before_lock"); @@ -859,6 +867,13 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, while (is_on() && !thd_killed(thd)) { + /* We have to check these again as things may have changed */ + if (!rpl_semi_sync_master_clients && !rpl_semi_sync_master_wait_no_slave) + { + aborted= 1; + break; + } + if (m_reply_file_name_inited) { int cmp = Active_tranx::compare(m_reply_file_name, m_reply_file_pos, @@ -873,6 +888,7 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, "Repl_semi_sync_master::commit_trx", m_reply_file_name, (ulong)m_reply_file_pos)); + success= 1; break; } } @@ -973,13 +989,13 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, m_active_tranxs may be NULL if someone disabled semi sync during cond_timewait() */ - assert(thd_killed(thd) || !m_active_tranxs || - !m_active_tranxs->is_tranx_end_pos(trx_wait_binlog_name, - trx_wait_binlog_pos)); + DBUG_ASSERT(thd_killed(thd) || !m_active_tranxs || aborted || + !m_active_tranxs->is_tranx_end_pos(trx_wait_binlog_name, + trx_wait_binlog_pos)); l_end: /* Update the status counter. */ - if (is_on()) + if (success) rpl_semi_sync_master_yes_transactions++; else rpl_semi_sync_master_no_transactions++; @@ -1014,18 +1030,20 @@ void Repl_semi_sync_master::switch_off() { DBUG_ENTER("Repl_semi_sync_master::switch_off"); - m_state = false; + if (m_state) + { + m_state = false; - /* Clear the active transaction list. */ - assert(m_active_tranxs != NULL); - m_active_tranxs->clear_active_tranx_nodes(NULL, 0); - - rpl_semi_sync_master_off_times++; - m_wait_file_name_inited = false; - m_reply_file_name_inited = false; - sql_print_information("Semi-sync replication switched OFF."); - cond_broadcast(); /* wake up all waiting threads */ + /* Clear the active transaction list. */ + DBUG_ASSERT(m_active_tranxs != NULL); + m_active_tranxs->clear_active_tranx_nodes(NULL, 0); + rpl_semi_sync_master_off_times++; + m_wait_file_name_inited = false; + m_reply_file_name_inited = false; + sql_print_information("Semi-sync replication switched OFF."); + } + cond_broadcast(); /* wake up all waiting threads */ DBUG_VOID_RETURN; } @@ -1072,9 +1090,10 @@ int Repl_semi_sync_master::reserve_sync_header(String* packet) { DBUG_ENTER("Repl_semi_sync_master::reserve_sync_header"); - /* Set the magic number and the sync status. By default, no sync - * is required. - */ + /* + Set the magic number and the sync status. By default, no sync + is required. + */ packet->append(reinterpret_cast(k_sync_header), sizeof(k_sync_header)); DBUG_RETURN(0); @@ -1087,7 +1106,6 @@ int Repl_semi_sync_master::update_sync_header(THD* thd, unsigned char *packet, { int cmp = 0; bool sync = false; - DBUG_ENTER("Repl_semi_sync_master::update_sync_header"); /* If the semi-sync master is not enabled, or the slave is not a semi-sync @@ -1103,16 +1121,11 @@ int Repl_semi_sync_master::update_sync_header(THD* thd, unsigned char *packet, /* This is the real check inside the mutex. */ if (!get_master_enabled()) - { - assert(sync == false); goto l_end; - } if (is_on()) { /* semi-sync is ON */ - sync = false; /* No sync unless a transaction is involved. */ - if (m_reply_file_name_inited) { cmp = Active_tranx::compare(log_file_name, log_file_pos, @@ -1126,15 +1139,10 @@ int Repl_semi_sync_master::update_sync_header(THD* thd, unsigned char *packet, } } + cmp = 1; if (m_wait_file_name_inited) - { cmp = Active_tranx::compare(log_file_name, log_file_pos, m_wait_file_name, m_wait_file_pos); - } - else - { - cmp = 1; - } /* If we are already waiting for some transaction replies which * are later in binlog, do not wait for this one event. @@ -1144,7 +1152,7 @@ int Repl_semi_sync_master::update_sync_header(THD* thd, unsigned char *packet, /* * We only wait if the event is a transaction's ending event. */ - assert(m_active_tranxs != NULL); + DBUG_ASSERT(m_active_tranxs != NULL); sync = m_active_tranxs->is_tranx_end_pos(log_file_name, log_file_pos); } @@ -1172,13 +1180,12 @@ int Repl_semi_sync_master::update_sync_header(THD* thd, unsigned char *packet, l_end: unlock(); - /* We do not need to clear sync flag because we set it to 0 when we - * reserve the packet header. - */ + /* + We do not need to clear sync flag in packet because we set it to 0 when we + reserve the packet header. + */ if (sync) - { - (packet)[2] = k_packet_flag_sync; - } + packet[2]= k_packet_flag_sync; DBUG_RETURN(0); } @@ -1225,7 +1232,7 @@ int Repl_semi_sync_master::write_tranx_in_binlog(const char* log_file_name, if (is_on()) { - assert(m_active_tranxs != NULL); + DBUG_ASSERT(m_active_tranxs != NULL); if(m_active_tranxs->insert_tranx_node(log_file_name, log_file_pos)) { /* @@ -1256,7 +1263,7 @@ int Repl_semi_sync_master::flush_net(THD *thd, DBUG_ENTER("Repl_semi_sync_master::flush_net"); - assert((unsigned char)event_buf[1] == k_packet_magic_num); + DBUG_ASSERT((unsigned char)event_buf[1] == k_packet_magic_num); if ((unsigned char)event_buf[2] != k_packet_flag_sync) { /* current event does not require reply */ @@ -1274,6 +1281,11 @@ int Repl_semi_sync_master::flush_net(THD *thd, goto l_end; } + /* + We have to do a net_clear() as with semi-sync the slave_reply's are + interleaved with data from the master and then the net->pkt_nr + cannot be kept in sync. Better to start pkt_nr from 0 again. + */ net_clear(net, 0); net->pkt_nr++; net->compress_pkt_nr++; @@ -1300,11 +1312,7 @@ int Repl_semi_sync_master::after_reset_master() lock(); - if (rpl_semi_sync_master_clients == 0 && - !rpl_semi_sync_master_wait_no_slave) - m_state = 0; - else - m_state = get_master_enabled()? 1 : 0; + m_state = get_master_enabled() ? 1 : 0; m_wait_file_name_inited = false; m_reply_file_name_inited = false; @@ -1338,18 +1346,6 @@ int Repl_semi_sync_master::before_reset_master() DBUG_RETURN(result); } -void Repl_semi_sync_master::check_and_switch() -{ - lock(); - if (get_master_enabled() && is_on()) - { - if (!rpl_semi_sync_master_wait_no_slave - && rpl_semi_sync_master_clients == 0) - switch_off(); - } - unlock(); -} - void Repl_semi_sync_master::set_export_stats() { lock(); @@ -1363,7 +1359,6 @@ void Repl_semi_sync_master::set_export_stats() ((rpl_semi_sync_master_net_wait_num) ? (ulong)((double)rpl_semi_sync_master_net_wait_time / ((double)rpl_semi_sync_master_net_wait_num)) : 0); - unlock(); } diff --git a/sql/semisync_master.h b/sql/semisync_master.h index 5451ad512c6..99f46869354 100644 --- a/sql/semisync_master.h +++ b/sql/semisync_master.h @@ -633,8 +633,6 @@ class Repl_semi_sync_master /*called before reset master*/ int before_reset_master(); - void check_and_switch(); - /* Determines if the given thread is currently awaiting a semisync_ack. Note that the thread's value is protected by this class's LOCK_binlog, so this diff --git a/sql/semisync_master_ack_receiver.cc b/sql/semisync_master_ack_receiver.cc index a76e3447ac8..6453b7ef32a 100644 --- a/sql/semisync_master_ack_receiver.cc +++ b/sql/semisync_master_ack_receiver.cc @@ -24,7 +24,8 @@ extern PSI_cond_key key_COND_ack_receiver; #ifdef HAVE_PSI_THREAD_INTERFACE extern PSI_thread_key key_thread_ack_receiver; #endif -extern Repl_semi_sync_master repl_semisync; + +int global_ack_signal_fd= -1; /* Callback function of ack receive thread */ pthread_handler_t ack_receive_handler(void *arg) @@ -45,6 +46,7 @@ Ack_receiver::Ack_receiver() m_status= ST_DOWN; mysql_mutex_init(key_LOCK_ack_receiver, &m_mutex, NULL); mysql_cond_init(key_COND_ack_receiver, &m_cond, NULL); + mysql_cond_init(key_COND_ack_receiver, &m_cond_reply, NULL); m_pid= 0; DBUG_VOID_RETURN; @@ -57,6 +59,7 @@ void Ack_receiver::cleanup() stop(); mysql_mutex_destroy(&m_mutex); mysql_cond_destroy(&m_cond); + mysql_cond_destroy(&m_cond_reply); DBUG_VOID_RETURN; } @@ -104,6 +107,7 @@ void Ack_receiver::stop() if (m_status == ST_UP) { m_status= ST_STOPPING; + signal_listener(); // Signal listener thread to stop mysql_cond_broadcast(&m_cond); while (m_status == ST_STOPPING) @@ -118,6 +122,21 @@ void Ack_receiver::stop() DBUG_VOID_RETURN; } +#ifndef DBUG_OFF +void static dbug_verify_no_duplicate_slaves(Slave_ilist *m_slaves, THD *thd) +{ + I_List_iterator it(*m_slaves); + Slave *slave; + while ((slave= it++)) + { + DBUG_ASSERT(slave->thd->variables.server_id != thd->variables.server_id); + } +} +#else +#define dbug_verify_no_duplicate_slaves(A,B) do {} while(0) +#endif + + bool Ack_receiver::add_slave(THD *thd) { Slave *slave; @@ -126,17 +145,23 @@ bool Ack_receiver::add_slave(THD *thd) if (!(slave= new Slave)) DBUG_RETURN(true); + slave->active= 0; slave->thd= thd; slave->vio= *thd->net.vio; slave->vio.mysql_socket.m_psi= NULL; slave->vio.read_timeout= 1; mysql_mutex_lock(&m_mutex); + + dbug_verify_no_duplicate_slaves(&m_slaves, thd); + m_slaves.push_back(slave); m_slaves_changed= true; mysql_cond_broadcast(&m_cond); mysql_mutex_unlock(&m_mutex); + signal_listener(); // Inform listener that there are new slaves + DBUG_RETURN(false); } @@ -144,6 +169,7 @@ void Ack_receiver::remove_slave(THD *thd) { I_List_iterator it(m_slaves); Slave *slave; + bool slaves_changed= 0; DBUG_ENTER("Ack_receiver::remove_slave"); mysql_mutex_lock(&m_mutex); @@ -153,10 +179,23 @@ void Ack_receiver::remove_slave(THD *thd) if (slave->thd == thd) { delete slave; - m_slaves_changed= true; + slaves_changed= true; break; } } + if (slaves_changed) + { + m_slaves_changed= true; + mysql_cond_broadcast(&m_cond); + /* + Wait until Ack_receiver::run() acknowledges remove of slave + As this is only sent under the mutex and after listners has + been collected, we know that listener has ignored the found + slave. + */ + if (m_status != ST_DOWN) + mysql_cond_wait(&m_cond_reply, &m_mutex); + } mysql_mutex_unlock(&m_mutex); DBUG_VOID_RETURN; @@ -167,10 +206,15 @@ inline void Ack_receiver::set_stage_info(const PSI_stage_info &stage) (void)MYSQL_SET_STAGE(stage.m_key, __FILE__, __LINE__); } -inline void Ack_receiver::wait_for_slave_connection() +void Ack_receiver::wait_for_slave_connection(THD *thd) { - set_stage_info(stage_waiting_for_semi_sync_slave); - mysql_cond_wait(&m_cond, &m_mutex); + thd->enter_cond(&m_cond, &m_mutex, &stage_waiting_for_semi_sync_slave, + 0, __func__, __FILE__, __LINE__); + + while (m_status == ST_UP && m_slaves.is_empty()) + mysql_cond_wait(&m_cond, &m_mutex); + + thd->exit_cond(0, __func__, __FILE__, __LINE__); } /* Auxilary function to initialize a NET object with given net buffer. */ @@ -188,11 +232,10 @@ void Ack_receiver::run() THD *thd= new THD(next_thread_id()); NET net; unsigned char net_buff[REPLY_MESSAGE_MAX_LENGTH]; + DBUG_ENTER("Ack_receiver::run"); my_thread_init(); - DBUG_ENTER("Ack_receiver::run"); - #ifdef HAVE_POLL Poll_socket_listener listener(m_slaves); #else @@ -207,64 +250,76 @@ void Ack_receiver::run() thd->set_command(COM_DAEMON); init_net(&net, net_buff, REPLY_MESSAGE_MAX_LENGTH); - mysql_mutex_lock(&m_mutex); + /* + Mark that we have to setup the listener. Note that only this functions can + set m_slaves_changed to false + */ m_slaves_changed= true; - mysql_mutex_unlock(&m_mutex); while (1) { - int ret; - uint slave_count __attribute__((unused))= 0; + int ret, slave_count; Slave *slave; mysql_mutex_lock(&m_mutex); - if (unlikely(m_status == ST_STOPPING)) + if (unlikely(m_status != ST_UP)) goto end; - set_stage_info(stage_waiting_for_semi_sync_ack_from_slave); if (unlikely(m_slaves_changed)) { if (unlikely(m_slaves.is_empty())) { - wait_for_slave_connection(); - mysql_mutex_unlock(&m_mutex); + m_slaves_changed= false; + mysql_cond_broadcast(&m_cond_reply); // Signal remove_slave + wait_for_slave_connection(thd); + /* Wait for slave unlocks m_mutex */ continue; } + set_stage_info(stage_waiting_for_semi_sync_ack_from_slave); if ((slave_count= listener.init_slave_sockets()) == 0) + { + mysql_mutex_unlock(&m_mutex); + m_slaves_changed= true; + continue; // Retry + } + if (slave_count < 0) goto end; m_slaves_changed= false; + mysql_cond_broadcast(&m_cond_reply); // Signal remove_slave + } + #ifdef HAVE_POLL DBUG_PRINT("info", ("fd count %u", slave_count)); #else DBUG_PRINT("info", ("fd count %u, max_fd %d", slave_count, (int) listener.get_max_fd())); #endif - } + mysql_mutex_unlock(&m_mutex); ret= listener.listen_on_sockets(); + if (ret <= 0) { - mysql_mutex_unlock(&m_mutex); - ret= DBUG_EVALUATE_IF("rpl_semisync_simulate_select_error", -1, ret); if (ret == -1 && errno != EINTR) sql_print_information("Failed to wait on semi-sync sockets, " "error: errno=%d", socket_errno); - /* Sleep 1us, so other threads can catch the m_mutex easily. */ - my_sleep(1); continue; } + listener.clear_signal(); + mysql_mutex_lock(&m_mutex); set_stage_info(stage_reading_semi_sync_ack); Slave_ilist_iterator it(m_slaves); while ((slave= it++)) { - if (listener.is_socket_active(slave)) + if (slave->active) // Set in init_slave_sockets() { ulong len; + /* Semi-sync packets will always be sent with pkt_nr == 1 */ net_clear(&net, 0); net.vio= &slave->vio; /* @@ -275,29 +330,40 @@ void Ack_receiver::run() len= my_net_read(&net); if (likely(len != packet_error)) - repl_semisync_master.report_reply_packet(slave->server_id(), - net.read_pos, len); - else { - if (net.last_errno == ER_NET_READ_ERROR) + int res; + res= repl_semisync_master.report_reply_packet(slave->server_id(), + net.read_pos, len); + if (unlikely(res < 0)) { - listener.clear_socket_info(slave); + /* + Slave has sent COM_QUIT or other failure. + Delete it from listener + */ + it.remove(); } + } + else if (net.last_errno == ER_NET_READ_ERROR) + { if (net.last_errno > 0 && global_system_variables.log_warnings > 2) sql_print_warning("Semisync ack receiver got error %d \"%s\" " "from slave server-id %d", net.last_errno, ER_DEFAULT(net.last_errno), slave->server_id()); + it.remove(); } } } mysql_mutex_unlock(&m_mutex); } + end: sql_print_information("Stopping ack receiver thread"); m_status= ST_DOWN; - delete thd; mysql_cond_broadcast(&m_cond); + mysql_cond_broadcast(&m_cond_reply); mysql_mutex_unlock(&m_mutex); + + delete thd; DBUG_VOID_RETURN; } diff --git a/sql/semisync_master_ack_receiver.h b/sql/semisync_master_ack_receiver.h index d869bd2e6d4..d3d9de27b89 100644 --- a/sql/semisync_master_ack_receiver.h +++ b/sql/semisync_master_ack_receiver.h @@ -29,6 +29,7 @@ struct Slave :public ilink #ifdef HAVE_POLL uint m_fds_index; #endif + bool active; my_socket sock_fd() const { return vio.mysql_socket.fd; } uint server_id() const { return thd->variables.server_id; } }; @@ -46,6 +47,7 @@ typedef I_List_iterator Slave_ilist_iterator; add_slave: maintain a new semisync slave's information remove_slave: remove a semisync slave's information */ + class Ack_receiver : public Repl_semi_sync_base { public: @@ -96,15 +98,20 @@ public: { m_trace_level= trace_level; } + bool running() + { + return m_status != ST_DOWN; + } + private: enum status {ST_UP, ST_DOWN, ST_STOPPING}; - uint8 m_status; + enum status m_status; /* Protect m_status, m_slaves_changed and m_slaves. ack thread and other session may access the variables at the same time. */ mysql_mutex_t m_mutex; - mysql_cond_t m_cond; + mysql_cond_t m_cond, m_cond_reply; /* If slave list is updated(add or remove). */ bool m_slaves_changed; @@ -116,25 +123,73 @@ private: Ack_receiver& operator=(const Ack_receiver &ack_receiver); void set_stage_info(const PSI_stage_info &stage); - void wait_for_slave_connection(); + void wait_for_slave_connection(THD *thd); }; -#ifdef HAVE_POLL -#include -#include +extern int global_ack_signal_fd; -class Poll_socket_listener +class Ack_listener { public: - Poll_socket_listener(const Slave_ilist &slaves) + int local_read_signal; + const Slave_ilist &m_slaves; + + Ack_listener(const Slave_ilist &slaves) :m_slaves(slaves) { + int pipes[2]; + pipe(pipes); + global_ack_signal_fd= pipes[1]; + local_read_signal= pipes[0]; + fcntl(pipes[0], F_SETFL, O_NONBLOCK); + fcntl(pipes[1], F_SETFL, O_NONBLOCK); } + virtual ~Ack_listener() + { + close(global_ack_signal_fd); + close(local_read_signal); + global_ack_signal_fd= -1; + } + + virtual bool has_signal_data()= 0; + + /* Clear data sent by signal_listener() to abort read */ + void clear_signal() + { + if (has_signal_data()) + { + char buff[100]; + /* Clear the signal message */ + read(local_read_signal, buff, sizeof(buff)); + } + } +}; + +static inline void signal_listener() +{ + my_write(global_ack_signal_fd, (uchar*) "a", 1, MYF(0)); +} + +#ifdef HAVE_POLL +#include + +class Poll_socket_listener final : public Ack_listener +{ +private: + std::vector m_fds; + +public: + Poll_socket_listener(const Slave_ilist &slaves) + :Ack_listener(slaves) + {} + + virtual ~Poll_socket_listener() = default; + bool listen_on_sockets() { - return poll(m_fds.data(), m_fds.size(), 1000 /*1 Second timeout*/); + return poll(m_fds.data(), m_fds.size(), -1); } bool is_socket_active(const Slave *slave) @@ -148,15 +203,29 @@ public: m_fds[slave->m_fds_index].events= 0; } - uint init_slave_sockets() + bool has_signal_data() override + { + /* The signal fd is always first */ + return (m_fds[0].revents & POLLIN); + } + + int init_slave_sockets() { Slave_ilist_iterator it(const_cast(m_slaves)); Slave *slave; uint fds_index= 0; + pollfd poll_fd; m_fds.clear(); + /* First put in the signal socket */ + poll_fd.fd= local_read_signal; + poll_fd.events= POLLIN; + m_fds.push_back(poll_fd); + fds_index++; + while ((slave= it++)) { + slave->active= 1; pollfd poll_fd; poll_fd.fd= slave->sock_fd(); poll_fd.events= POLLIN; @@ -165,29 +234,30 @@ public: } return fds_index; } - -private: - const Slave_ilist &m_slaves; - std::vector m_fds; }; #else //NO POLL -class Select_socket_listener +class Select_socket_listener final : public Ack_listener { +private: + my_socket m_max_fd; + fd_set m_init_fds; + fd_set m_fds; + public: Select_socket_listener(const Slave_ilist &slaves) - :m_slaves(slaves), m_max_fd(INVALID_SOCKET) - { - } + :Ack_listener(slaves), m_max_fd(INVALID_SOCKET) + {} + + virtual ~Select_socket_listener() = default; bool listen_on_sockets() { /* Reinitialize the fds with active fds before calling select */ m_fds= m_init_fds; - struct timeval tv= {1,0}; /* select requires max fd + 1 for the first argument */ - return select((int) m_max_fd+1, &m_fds, NULL, NULL, &tv); + return select((int) m_max_fd+1, &m_fds, NULL, NULL, NULL); } bool is_socket_active(const Slave *slave) @@ -195,43 +265,61 @@ public: return FD_ISSET(slave->sock_fd(), &m_fds); } + bool has_signal_data() override + { + return FD_ISSET(local_read_signal, &m_fds); + } + void clear_socket_info(const Slave *slave) { FD_CLR(slave->sock_fd(), &m_init_fds); } - uint init_slave_sockets() + int init_slave_sockets() { Slave_ilist_iterator it(const_cast(m_slaves)); Slave *slave; uint fds_index= 0; FD_ZERO(&m_init_fds); + m_max_fd= -1; + + /* First put in the signal socket */ + FD_SET(local_read_signal, &m_init_fds); + fds_index++; + set_if_bigger(m_max_fd, local_read_signal); +#ifndef _WIN32 + if (local_read_signal > FD_SETSIZE) + { + int socket_id= local_read_signal; + sql_print_error("Semisync slave socket fd is %u. " + "select() cannot handle if the socket fd is " + "greater than %u (FD_SETSIZE).", socket_id, FD_SETSIZE); + return -1; + } +#endif + while ((slave= it++)) { my_socket socket_id= slave->sock_fd(); - m_max_fd= (socket_id > m_max_fd ? socket_id : m_max_fd); + set_if_bigger(m_max_fd, socket_id); #ifndef _WIN32 if (socket_id > FD_SETSIZE) { sql_print_error("Semisync slave socket fd is %u. " "select() cannot handle if the socket fd is " "greater than %u (FD_SETSIZE).", socket_id, FD_SETSIZE); - return 0; + it.remove(); + continue; } #endif //_WIN32 FD_SET(socket_id, &m_init_fds); fds_index++; + slave->active= 1; } return fds_index; } my_socket get_max_fd() { return m_max_fd; } - -private: - const Slave_ilist &m_slaves; - my_socket m_max_fd; - fd_set m_init_fds; - fd_set m_fds; }; #endif //HAVE_POLL diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc index 3e7578b6a53..a56e22eab3e 100644 --- a/sql/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -20,20 +20,9 @@ Repl_semi_sync_slave repl_semisync_slave; -my_bool rpl_semi_sync_slave_enabled= 0; - +my_bool global_rpl_semi_sync_slave_enabled= 0; char rpl_semi_sync_slave_delay_master; -my_bool rpl_semi_sync_slave_status= 0; ulong rpl_semi_sync_slave_trace_level; - -/* - indicate whether or not the slave should send a reply to the master. - - This is set to true in repl_semi_slave_read_event if the current - event read is the last event of a transaction. And the value is - checked in repl_semi_slave_queue_event. -*/ -bool semi_sync_need_reply= false; unsigned int rpl_semi_sync_slave_kill_conn_timeout; unsigned long long rpl_semi_sync_slave_send_ack = 0; @@ -44,14 +33,26 @@ int Repl_semi_sync_slave::init_object() m_init_done = true; /* References to the parameter works after set_options(). */ - set_slave_enabled(rpl_semi_sync_slave_enabled); + set_slave_enabled(global_rpl_semi_sync_slave_enabled); set_trace_level(rpl_semi_sync_slave_trace_level); set_delay_master(rpl_semi_sync_slave_delay_master); set_kill_conn_timeout(rpl_semi_sync_slave_kill_conn_timeout); - return result; } +static bool local_semi_sync_enabled; + +int rpl_semi_sync_enabled(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *status_var, + enum_var_type scope) +{ + local_semi_sync_enabled= repl_semisync_slave.get_slave_enabled(); + var->type= SHOW_BOOL; + var->value= (char*) &local_semi_sync_enabled; + return 0; +} + + int Repl_semi_sync_slave::slave_read_sync_header(const uchar *header, unsigned long total_len, int *semi_flags, @@ -61,12 +62,12 @@ int Repl_semi_sync_slave::slave_read_sync_header(const uchar *header, int read_res = 0; DBUG_ENTER("Repl_semi_sync_slave::slave_read_sync_header"); - if (rpl_semi_sync_slave_status) + if (get_slave_enabled()) { if (DBUG_EVALUATE_IF("semislave_corrupt_log", 0, 1) && header[0] == k_packet_magic_num) { - semi_sync_need_reply = (header[1] & k_packet_flag_sync); + bool semi_sync_need_reply = (header[1] & k_packet_flag_sync); *payload_len = total_len - 2; *payload = header + 2; @@ -85,7 +86,9 @@ int Repl_semi_sync_slave::slave_read_sync_header(const uchar *header, "len: %lu", total_len); read_res = -1; } - } else { + } + else + { *payload= header; *payload_len= total_len; } @@ -93,9 +96,23 @@ int Repl_semi_sync_slave::slave_read_sync_header(const uchar *header, DBUG_RETURN(read_res); } -int Repl_semi_sync_slave::slave_start(Master_info *mi) +/* + Set default semisync variables and print some replication info to the log + + Note that the main setup is done in request_transmit() +*/ + +void Repl_semi_sync_slave::slave_start(Master_info *mi) { - bool semi_sync= get_slave_enabled(); + + /* + Set semi_sync_enabled at slave start. This is not changed until next + slave start or reconnect. + */ + bool semi_sync= global_rpl_semi_sync_slave_enabled; + + set_slave_enabled(semi_sync); + mi->semi_sync_reply_enabled= 0; sql_print_information("Slave I/O thread: Start %s replication to\ master '%s@%s:%d' in log '%s' at position %lu", @@ -104,30 +121,29 @@ int Repl_semi_sync_slave::slave_start(Master_info *mi) const_cast(mi->master_log_name), (unsigned long)(mi->master_log_pos)); - if (semi_sync && !rpl_semi_sync_slave_status) - rpl_semi_sync_slave_status= 1; - /*clear the counter*/ rpl_semi_sync_slave_send_ack= 0; - return 0; } -int Repl_semi_sync_slave::slave_stop(Master_info *mi) +void Repl_semi_sync_slave::slave_stop(Master_info *mi) { if (get_slave_enabled()) kill_connection(mi->mysql); - if (rpl_semi_sync_slave_status) - rpl_semi_sync_slave_status= 0; - - return 0; + set_slave_enabled(0); } -int Repl_semi_sync_slave::reset_slave(Master_info *mi) +void Repl_semi_sync_slave::slave_reconnect(Master_info *mi) { - return 0; + /* + Start semi-sync either if it globally enabled or if was enabled + before the reconnect. + */ + if (global_rpl_semi_sync_slave_enabled || get_slave_enabled()) + slave_start(mi); } + void Repl_semi_sync_slave::kill_connection(MYSQL *mysql) { if (!mysql) @@ -194,34 +210,44 @@ int Repl_semi_sync_slave::request_transmit(Master_info *mi) !(res= mysql_store_result(mysql))) { sql_print_error("Execution failed on master: %s, error :%s", query, mysql_error(mysql)); + set_slave_enabled(0); return 1; } row= mysql_fetch_row(res); if (DBUG_EVALUATE_IF("master_not_support_semisync", 1, 0) - || !row) + || (!row || ! row[1])) { /* Master does not support semi-sync */ - sql_print_warning("Master server does not support semi-sync, " - "fallback to asynchronous replication"); - rpl_semi_sync_slave_status= 0; + if (!row) + sql_print_warning("Master server does not support semi-sync, " + "fallback to asynchronous replication"); + set_slave_enabled(0); mysql_free_result(res); return 0; } + if (strcmp(row[1], "ON")) + sql_print_information("Slave has semi-sync enabled but master server does " + "not. Semi-sync will be activated when master " + "enables it"); mysql_free_result(res); /* Tell master dump thread that we want to do semi-sync - replication + replication. This is done by setting a thread local variable in + the master connection. */ query= "SET @rpl_semi_sync_slave= 1"; if (mysql_real_query(mysql, query, (ulong)strlen(query))) { - sql_print_error("Set 'rpl_semi_sync_slave=1' on master failed"); + sql_print_error("%s on master failed", query); + set_slave_enabled(0); return 1; } + mi->semi_sync_reply_enabled= 1; + /* Inform net_server that pkt_nr can come out of order */ + mi->mysql->net.pkt_nr_can_be_reset= 1; mysql_free_result(mysql_store_result(mysql)); - rpl_semi_sync_slave_status= 1; return 0; } @@ -231,46 +257,41 @@ int Repl_semi_sync_slave::slave_reply(Master_info *mi) MYSQL* mysql= mi->mysql; const char *binlog_filename= const_cast(mi->master_log_name); my_off_t binlog_filepos= mi->master_log_pos; - NET *net= &mysql->net; uchar reply_buffer[REPLY_MAGIC_NUM_LEN + REPLY_BINLOG_POS_LEN + REPLY_BINLOG_NAME_LEN]; int reply_res = 0; size_t name_len = strlen(binlog_filename); - DBUG_ENTER("Repl_semi_sync_slave::slave_reply"); + DBUG_ASSERT(get_slave_enabled() && mi->semi_sync_reply_enabled); - if (rpl_semi_sync_slave_status && semi_sync_need_reply) + /* Prepare the buffer of the reply. */ + reply_buffer[REPLY_MAGIC_NUM_OFFSET] = k_packet_magic_num; + int8store(reply_buffer + REPLY_BINLOG_POS_OFFSET, binlog_filepos); + memcpy(reply_buffer + REPLY_BINLOG_NAME_OFFSET, + binlog_filename, + name_len + 1 /* including trailing '\0' */); + + DBUG_PRINT("semisync", ("%s: reply (%s, %lu)", + "Repl_semi_sync_slave::slave_reply", + binlog_filename, (ulong)binlog_filepos)); + + /* + We have to do a net_clear() as with semi-sync the slave_reply's are + interleaved with data from the master and then the net->pkt_nr + cannot be kept in sync. Better to start pkt_nr from 0 again. + */ + net_clear(net, 0); + /* Send the reply. */ + reply_res = my_net_write(net, reply_buffer, + name_len + REPLY_BINLOG_NAME_OFFSET); + if (!reply_res) { - /* Prepare the buffer of the reply. */ - reply_buffer[REPLY_MAGIC_NUM_OFFSET] = k_packet_magic_num; - int8store(reply_buffer + REPLY_BINLOG_POS_OFFSET, binlog_filepos); - memcpy(reply_buffer + REPLY_BINLOG_NAME_OFFSET, - binlog_filename, - name_len + 1 /* including trailing '\0' */); - - DBUG_PRINT("semisync", ("%s: reply (%s, %lu)", - "Repl_semi_sync_slave::slave_reply", - binlog_filename, (ulong)binlog_filepos)); - - net_clear(net, 0); - /* Send the reply. */ - reply_res = my_net_write(net, reply_buffer, - name_len + REPLY_BINLOG_NAME_OFFSET); + reply_res= DBUG_EVALUATE_IF("semislave_failed_net_flush", 1, + net_flush(net)); if (!reply_res) - { - reply_res = DBUG_EVALUATE_IF("semislave_failed_net_flush", 1, net_flush(net)); - if (reply_res) - sql_print_error("Semi-sync slave net_flush() reply failed"); rpl_semi_sync_slave_send_ack++; - } - else - { - sql_print_error("Semi-sync slave send reply failed: %s (%d)", - net->last_error, net->last_errno); - } } - DBUG_RETURN(reply_res); } diff --git a/sql/semisync_slave.h b/sql/semisync_slave.h index a8229245ab1..6811584c9c8 100644 --- a/sql/semisync_slave.h +++ b/sql/semisync_slave.h @@ -33,7 +33,7 @@ class Master_info; class Repl_semi_sync_slave :public Repl_semi_sync_base { public: - Repl_semi_sync_slave() :m_slave_enabled(false) {} + Repl_semi_sync_slave() :m_slave_enabled(false) {} ~Repl_semi_sync_slave() = default; void set_trace_level(unsigned long trace_level) { @@ -45,7 +45,7 @@ public: */ int init_object(); - bool get_slave_enabled() { + inline bool get_slave_enabled() { return m_slave_enabled; } @@ -53,7 +53,7 @@ public: m_slave_enabled = enabled; } - bool is_delay_master(){ + inline bool is_delay_master(){ return m_delay_master; } @@ -88,24 +88,23 @@ public: * binlog position. */ int slave_reply(Master_info* mi); - int slave_start(Master_info *mi); - int slave_stop(Master_info *mi); - int request_transmit(Master_info*); + void slave_start(Master_info *mi); + void slave_stop(Master_info *mi); + void slave_reconnect(Master_info *mi); + int request_transmit(Master_info *mi); void kill_connection(MYSQL *mysql); - int reset_slave(Master_info *mi); private: /* True when init_object has been called */ bool m_init_done; - bool m_slave_enabled; /* semi-sycn is enabled on the slave */ + bool m_slave_enabled; /* semi-sync is enabled on the slave */ bool m_delay_master; unsigned int m_kill_conn_timeout; }; /* System and status variables for the slave component */ -extern my_bool rpl_semi_sync_slave_enabled; -extern my_bool rpl_semi_sync_slave_status; +extern my_bool global_rpl_semi_sync_slave_enabled; extern ulong rpl_semi_sync_slave_trace_level; extern Repl_semi_sync_slave repl_semisync_slave; @@ -113,4 +112,7 @@ extern char rpl_semi_sync_slave_delay_master; extern unsigned int rpl_semi_sync_slave_kill_conn_timeout; extern unsigned long long rpl_semi_sync_slave_send_ack; +extern int rpl_semi_sync_enabled(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *status_var, + enum_var_type scope); #endif /* SEMISYNC_SLAVE_H */ diff --git a/sql/slave.cc b/sql/slave.cc index e745749d64d..3318c92b317 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4659,6 +4659,7 @@ static int try_to_reconnect(THD *thd, MYSQL *mysql, Master_info *mi, sql_print_information("%s", messages[SLAVE_RECON_MSG_KILLED_AFTER]); return 1; } + repl_semisync_slave.slave_reconnect(mi); return 0; } @@ -4747,14 +4748,7 @@ pthread_handler_t handle_slave_io(void *arg) } thd->variables.wsrep_on= 0; - if (DBUG_EVALUATE_IF("failed_slave_start", 1, 0) - || repl_semisync_slave.slave_start(mi)) - { - mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL, - ER_THD(thd, ER_SLAVE_FATAL_ERROR), - "Failed to run 'thread_start' hook"); - goto err; - } + repl_semisync_slave.slave_start(mi); if (!(mi->mysql = mysql = mysql_init(NULL))) { @@ -4848,6 +4842,7 @@ connected: if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, reconnect_messages[SLAVE_RECON_ACT_REG])) goto err; + goto connected; } @@ -4911,6 +4906,15 @@ connected: we're in fact receiving nothing. */ THD_STAGE_INFO(thd, stage_waiting_for_master_to_send_event); + +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF("pause_before_io_read_event", + { + DBUG_ASSERT(!debug_sync_set_action( thd, STRING_WITH_LEN( + "now signal io_thread_at_read_event wait_for io_thread_continue_read_event"))); + DBUG_SET("-d,pause_before_io_read_event"); + };); +#endif event_len= read_event(mysql, mi, &suppress_warnings, &network_read_len); if (check_io_slave_killed(mi, NullS)) goto err; @@ -5010,17 +5014,36 @@ Stopping slave I/O thread due to out-of-memory error from master"); goto err; } - if (rpl_semi_sync_slave_status && (mi->semi_ack & SEMI_SYNC_NEED_ACK)) + if (repl_semisync_slave.get_slave_enabled() && + mi->semi_sync_reply_enabled && + (mi->semi_ack & SEMI_SYNC_NEED_ACK)) { - /* - We deliberately ignore the error in slave_reply, such error should - not cause the slave IO thread to stop, and the error messages are - already reported. - */ - DBUG_EXECUTE_IF("simulate_delay_semisync_slave_reply", my_sleep(800000);); - (void)repl_semisync_slave.slave_reply(mi); - } + DBUG_EXECUTE_IF("simulate_delay_semisync_slave_reply", + my_sleep(800000);); + if (repl_semisync_slave.slave_reply(mi)) + { + /* + Master is not responding (gone away?) or it has turned semi sync + off. Turning off semi-sync responses as there is no point in sending + data to the master if the master not receiving the messages. + This also stops the logs from getting filled with + "Semi-sync slave net_flush() reply failed" messages. + On reconnect semi sync will be turned on again, if the + master has semi-sync enabled. + We check mi->abort_slave to see if the io thread was + killed and in this case we do not need an error message as + we know what is going on. + */ + if (!mi->abort_slave) + sql_print_error("Master server does not read semi-sync messages " + "last_error: %s (%d). " + "Fallback to asynchronous replication", + mi->mysql->net.last_error, + mi->mysql->net.last_errno); + mi->semi_sync_reply_enabled= 0; + } + } if (mi->using_gtid == Master_info::USE_GTID_NO && /* If rpl_semi_sync_slave_delay_master is enabled, we will flush @@ -6879,7 +6902,7 @@ dbug_gtid_accept: */ mi->do_accept_own_server_id= (s_id == global_system_variables.server_id && - rpl_semi_sync_slave_enabled && opt_gtid_strict_mode && + repl_semisync_slave.get_slave_enabled() && opt_gtid_strict_mode && mi->using_gtid != Master_info::USE_GTID_NO && !mysql_bin_log.check_strict_gtid_sequence(event_gtid.domain_id, event_gtid.server_id, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a03635bc868..fdf84ef8a99 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1876,14 +1876,6 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, */ } -#define SECONDS_TO_WAIT_FOR_KILL 2 -#if !defined(_WIN32) && defined(HAVE_SELECT) -/* my_sleep() can wait for sub second times */ -#define WAIT_FOR_KILL_TRY_TIMES 20 -#else -#define WAIT_FOR_KILL_TRY_TIMES 2 -#endif - /** Awake a thread. diff --git a/sql/sql_class.h b/sql/sql_class.h index 6bbac5647be..d61ee1545b6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -652,6 +652,15 @@ enum killed_type KILL_TYPE_QUERY }; +#define SECONDS_TO_WAIT_FOR_KILL 2 +#define SECONDS_TO_WAIT_FOR_DUMP_THREAD_KILL 10 +#if !defined(_WIN32) && defined(HAVE_SELECT) +/* my_sleep() can wait for sub second times */ +#define WAIT_FOR_KILL_TRY_TIMES 20 +#else +#define WAIT_FOR_KILL_TRY_TIMES 2 +#endif + #include "sql_lex.h" /* Must be here */ class Delayed_insert; diff --git a/sql/sql_list.h b/sql/sql_list.h index a9ab5415d5a..909e6209c44 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -799,7 +799,9 @@ public: class base_ilist_iterator { base_ilist *list; - struct ilink **el,*current; + struct ilink **el; +protected: + struct ilink *current; public: base_ilist_iterator(base_ilist &list_par) :list(&list_par), el(&list_par.first),current(0) {} @@ -811,6 +813,13 @@ public: el= ¤t->next; return current; } + /* Unlink element returned by last next() call */ + inline void unlink(void) + { + struct ilink **tmp= current->prev; + current->unlink(); + el= tmp; + } }; @@ -840,6 +849,13 @@ template class I_List_iterator :public base_ilist_iterator public: I_List_iterator(I_List &a) : base_ilist_iterator(a) {} inline T* operator++(int) { return (T*) base_ilist_iterator::next(); } + /* Remove element returned by last next() call */ + inline void remove(void) + { + unlink(); + delete (T*) current; + current= 0; // Safety + } }; /** diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c09a59b3adc..c30c825ffb8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2126,7 +2126,6 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * { ulong pos; ushort flags; - uint32 slave_server_id; status_var_increment(thd->status_var.com_other); @@ -2137,10 +2136,26 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * /* TODO: The following has to be changed to an 8 byte integer */ pos = uint4korr(packet); flags = uint2korr(packet + 4); - thd->variables.server_id=0; /* avoid suicide */ - if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0 - kill_zombie_dump_threads(slave_server_id); - thd->variables.server_id = slave_server_id; + if ((thd->variables.server_id= uint4korr(packet+6))) + { + bool got_error; + + got_error= kill_zombie_dump_threads(thd, + thd->variables.server_id); + if (got_error || thd->killed) + { + if (!thd->killed) + my_printf_error(ER_MASTER_FATAL_ERROR_READING_BINLOG, + "Could not start dump thread for slave: %u as " + "it has already a running dump thread", + MYF(0), (uint) thd->variables.server_id); + else if (! thd->get_stmt_da()->is_set()) + thd->send_kill_message(); + error= TRUE; + thd->unregister_slave(); // todo: can be extraneous + break; + } + } const char *name= packet + 10; size_t nlen= strlen(name); @@ -2148,6 +2163,8 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * general_log_print(thd, command, "Log: '%s' Pos: %lu", name, pos); if (nlen < FN_REFLEN) mysql_binlog_send(thd, thd->strmake(name, nlen), (my_off_t)pos, flags); + if (thd->killed && ! thd->get_stmt_da()->is_set()) + thd->send_kill_message(); thd->unregister_slave(); // todo: can be extraneous /* fake COM_QUIT -- if we get here, the thread needs to terminate */ error = TRUE; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 70b4b9aedf7..1ac6db00a15 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2060,7 +2060,7 @@ send_event_to_slave(binlog_send_info *info, Log_event_type event_type, } if (need_sync && repl_semisync_master.flush_net(info->thd, - packet->c_ptr_safe())) + packet->c_ptr())) { info->error= ER_UNKNOWN_ERROR; return "Failed to run hook 'after_send_event'"; @@ -3011,8 +3011,13 @@ err: if (info->thd->killed == KILL_SLAVE_SAME_ID) { - info->errmsg= "A slave with the same server_uuid/server_id as this slave " - "has connected to the master"; + /* + Note that the text is limited to 64 characters in errmsg-utf8 in + ER_ABORTING_CONNECTION. + */ + info->errmsg= + "A slave with the same server_uuid/server_id is already " + "connected"; info->error= ER_SLAVE_SAME_ID; } @@ -3385,6 +3390,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) @retval 0 success @retval 1 error */ + int reset_slave(THD *thd, Master_info* mi) { MY_STAT stat_area; @@ -3472,8 +3478,6 @@ int reset_slave(THD *thd, Master_info* mi) else if (global_system_variables.log_warnings > 1) sql_print_information("Deleted Master_info file '%s'.", fname); - if (rpl_semi_sync_slave_enabled) - repl_semisync_slave.reset_slave(mi); err: mi->unlock_slave_threads(); if (unlikely(error)) @@ -3501,43 +3505,89 @@ err: struct kill_callback_arg { - kill_callback_arg(uint32 id): slave_server_id(id), thd(0) {} - uint32 slave_server_id; + kill_callback_arg(THD *thd_arg, uint32 id): + thd(thd_arg), slave_server_id(id), counter(0) {} THD *thd; + uint32 slave_server_id; + uint counter; }; -static my_bool kill_callback(THD *thd, kill_callback_arg *arg) + +/* + Collect all active dump threads +*/ + +static my_bool kill_callback_collect(THD *thd, kill_callback_arg *arg) { if (thd->get_command() == COM_BINLOG_DUMP && - thd->variables.server_id == arg->slave_server_id) + thd->variables.server_id == arg->slave_server_id && + thd != arg->thd) { - arg->thd= thd; + arg->counter++; mysql_mutex_lock(&thd->LOCK_thd_kill); // Lock from delete mysql_mutex_lock(&thd->LOCK_thd_data); - return 1; + thd->awake_no_mutex(KILL_SLAVE_SAME_ID); // Mark killed + /* + Remover the thread from ack_receiver to ensure it is not + sending acks to the master anymore. + */ + ack_receiver.remove_slave(thd); + + mysql_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_thd_kill); } return 0; } -void kill_zombie_dump_threads(uint32 slave_server_id) -{ - kill_callback_arg arg(slave_server_id); - server_threads.iterate(kill_callback, &arg); +/* + Check if there are any active dump threads +*/ - if (arg.thd) - { - /* - Here we do not call kill_one_thread() as - it will be slow because it will iterate through the list - again. We just to do kill the thread ourselves. - */ - arg.thd->awake_no_mutex(KILL_SLAVE_SAME_ID); - mysql_mutex_unlock(&arg.thd->LOCK_thd_kill); - mysql_mutex_unlock(&arg.thd->LOCK_thd_data); - } +static my_bool kill_callback_check(THD *thd, kill_callback_arg *arg) +{ + return (thd->get_command() == COM_BINLOG_DUMP && + thd->variables.server_id == arg->slave_server_id && + thd != arg->thd); } + +/** + Try to kill running dump threads on the master + + @result 0 ok + @result 1 old slave thread exists and does not want to die + + There should not be more than one dump thread with the same server id + this code has however in the past has several issues. To ensure that + things works in all cases (now and in the future), this code is collecting + all matching server id's and killing all of them. +*/ + +bool kill_zombie_dump_threads(THD *thd, uint32 slave_server_id) +{ + kill_callback_arg arg(thd, slave_server_id); + server_threads.iterate(kill_callback_collect, &arg); + + if (!arg.counter) + return 0; + + /* + Wait up to SECONDS_TO_WAIT_FOR_DUMP_THREAD_KILL for kill + of all dump thread, trying every 1/10 of second. + */ + for (uint i= 10 * SECONDS_TO_WAIT_FOR_DUMP_THREAD_KILL ; + --i > 0 && !thd->killed; + i++) + { + if (!server_threads.iterate(kill_callback_check, &arg)) + return 0; // All dump thread are killed + my_sleep(1000000L / 10); // Wait 1/10 of a second + } + return 1; +} + + /** Get value for a string parameter with error checking diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 95916e31abf..3be1e18ca0d 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -43,7 +43,7 @@ void adjust_linfo_offsets(my_off_t purge_offset); void show_binlogs_get_fields(THD *thd, List *field_list); bool show_binlogs(THD* thd); extern int init_master_info(Master_info* mi); -void kill_zombie_dump_threads(uint32 slave_server_id); +bool kill_zombie_dump_threads(THD *thd, uint32 slave_server_id); int check_binlog_magic(IO_CACHE* log, const char** errmsg); int compare_log_name(const char *log_1, const char *log_2); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index be8a66ff7f2..dea04bf3bc5 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3478,13 +3478,6 @@ static bool fix_rpl_semi_sync_master_wait_point(sys_var *self, THD *thd, return false; } -static bool fix_rpl_semi_sync_master_wait_no_slave(sys_var *self, THD *thd, - enum_var_type type) -{ - repl_semisync_master.check_and_switch(); - return false; -} - static Sys_var_on_access_global Sys_semisync_master_enabled( @@ -3511,12 +3504,11 @@ static Sys_var_on_access_global Sys_semisync_master_wait_no_slave( "rpl_semi_sync_master_wait_no_slave", - "Wait until timeout when no semi-synchronous replication slave " - "available (enabled by default).", + "Wait until timeout when no semi-synchronous replication slave is " + "available.", GLOBAL_VAR(rpl_semi_sync_master_wait_no_slave), CMD_LINE(OPT_ARG), DEFAULT(TRUE), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), - ON_UPDATE(fix_rpl_semi_sync_master_wait_no_slave)); + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0)); static Sys_var_on_access_global @@ -3543,13 +3535,6 @@ Sys_semisync_master_wait_point( NO_MUTEX_GUARD, NOT_IN_BINLOG,ON_CHECK(0), ON_UPDATE(fix_rpl_semi_sync_master_wait_point)); -static bool fix_rpl_semi_sync_slave_enabled(sys_var *self, THD *thd, - enum_var_type type) -{ - repl_semisync_slave.set_slave_enabled(rpl_semi_sync_slave_enabled != 0); - return false; -} - static bool fix_rpl_semi_sync_slave_trace_level(sys_var *self, THD *thd, enum_var_type type) { @@ -3577,10 +3562,9 @@ static Sys_var_on_access_global From 1ca813bf76b66e86af2bde918eb33ee98a4e522b Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 25 Dec 2023 15:30:03 +0200 Subject: [PATCH 077/121] Added socketpair.c as a replacement for 'pipe()' call for Windows. This was needed to get semisync to work on Windows. --- THIRDPARTY | 29 ++++++ sql/CMakeLists.txt | 1 + sql/semisync_master_ack_receiver.cc | 17 ++- sql/semisync_master_ack_receiver.h | 53 ++++++++-- sql/socketpair.c | 156 ++++++++++++++++++++++++++++ sql/socketpair.h | 21 ++++ 6 files changed, 263 insertions(+), 14 deletions(-) create mode 100644 sql/socketpair.c create mode 100644 sql/socketpair.h diff --git a/THIRDPARTY b/THIRDPARTY index 35bb238ed1e..b15d979ea4a 100644 --- a/THIRDPARTY +++ b/THIRDPARTY @@ -1690,3 +1690,32 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *************************************************************************** + +%%The following software may be included in this product: +socketpair.c + +Copyright 2007, 2010 by Nathan C. Myers +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + The name of the author must not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index f1c1c65310b..20283cdefc4 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -175,6 +175,7 @@ SET (SQL_SOURCE table_cache.cc encryption.cc temporary_tables.cc json_table.cc proxy_protocol.cc backup.cc xa.cc + socketpair.c socketpair.h ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h ${GEN_SOURCES} diff --git a/sql/semisync_master_ack_receiver.cc b/sql/semisync_master_ack_receiver.cc index 6453b7ef32a..9320c7fc3e6 100644 --- a/sql/semisync_master_ack_receiver.cc +++ b/sql/semisync_master_ack_receiver.cc @@ -25,7 +25,7 @@ extern PSI_cond_key key_COND_ack_receiver; extern PSI_thread_key key_thread_ack_receiver; #endif -int global_ack_signal_fd= -1; +my_socket global_ack_signal_fd= -1; /* Callback function of ack receive thread */ pthread_handler_t ack_receive_handler(void *arg) @@ -242,6 +242,13 @@ void Ack_receiver::run() Select_socket_listener listener(m_slaves); #endif //HAVE_POLL + if (listener.got_error()) + { + sql_print_error("Got error %M starting ack receiver thread", + listener.got_error()); + return; + } + sql_print_information("Starting ack receiver thread"); thd->system_thread= SYSTEM_THREAD_SEMISYNC_MASTER_BACKGROUND; thd->thread_stack= (char*) &thd; @@ -258,7 +265,7 @@ void Ack_receiver::run() while (1) { - int ret, slave_count; + int ret, slave_count= 0; Slave *slave; mysql_mutex_lock(&m_mutex); @@ -315,7 +322,9 @@ void Ack_receiver::run() Slave_ilist_iterator it(m_slaves); while ((slave= it++)) { - if (slave->active) // Set in init_slave_sockets() + if (slave->active && + ((slave->vio.read_pos < slave->vio.read_end) || + listener.is_socket_active(slave))) { ulong len; @@ -341,6 +350,7 @@ void Ack_receiver::run() Delete it from listener */ it.remove(); + m_slaves_changed= true; } } else if (net.last_errno == ER_NET_READ_ERROR) @@ -351,6 +361,7 @@ void Ack_receiver::run() net.last_errno, ER_DEFAULT(net.last_errno), slave->server_id()); it.remove(); + m_slaves_changed= true; } } } diff --git a/sql/semisync_master_ack_receiver.h b/sql/semisync_master_ack_receiver.h index d3d9de27b89..eacb4b200c0 100644 --- a/sql/semisync_master_ack_receiver.h +++ b/sql/semisync_master_ack_receiver.h @@ -20,6 +20,7 @@ #include "my_pthread.h" #include "sql_class.h" #include "semisync.h" +#include "socketpair.h" #include struct Slave :public ilink @@ -127,32 +128,54 @@ private: }; -extern int global_ack_signal_fd; +extern my_socket global_ack_signal_fd; class Ack_listener { public: - int local_read_signal; + my_socket local_read_signal; const Slave_ilist &m_slaves; + int error; Ack_listener(const Slave_ilist &slaves) - :m_slaves(slaves) + :local_read_signal(-1), m_slaves(slaves), error(0) { - int pipes[2]; - pipe(pipes); - global_ack_signal_fd= pipes[1]; + my_socket pipes[2]; +#ifdef _WIN32 + error= create_socketpair(pipes); +#else + if (!pipe(pipes)) + { + fcntl(pipes[0], F_SETFL, O_NONBLOCK); + fcntl(pipes[1], F_SETFL, O_NONBLOCK); + } + else + { + pipes[0]= pipes[1]= -1; + } +#endif /* _WIN32 */ local_read_signal= pipes[0]; - fcntl(pipes[0], F_SETFL, O_NONBLOCK); - fcntl(pipes[1], F_SETFL, O_NONBLOCK); + global_ack_signal_fd= pipes[1]; } virtual ~Ack_listener() { - close(global_ack_signal_fd); - close(local_read_signal); - global_ack_signal_fd= -1; +#ifdef _WIN32 + my_socket pipes[2]; + pipes[0]= local_read_signal; + pipes[1]= global_ack_signal_fd; + close_socketpair(pipes); +#else + if (global_ack_signal_fd >= 0) + close(global_ack_signal_fd); + if (local_read_signal >= 0) + close(local_read_signal); +#endif /* _WIN32 */ + global_ack_signal_fd= local_read_signal= -1; } + int got_error() { return error; } + virtual bool has_signal_data()= 0; /* Clear data sent by signal_listener() to abort read */ @@ -162,14 +185,22 @@ public: { char buff[100]; /* Clear the signal message */ +#ifndef _WIN32 read(local_read_signal, buff, sizeof(buff)); +#else + recv(local_read_signal, buff, sizeof(buff), 0); +#endif /* _WIN32 */ } } }; static inline void signal_listener() { +#ifndef _WIN32 my_write(global_ack_signal_fd, (uchar*) "a", 1, MYF(0)); +#else + send(global_ack_signal_fd, "a", 1, 0); +#endif /* _WIN32 */ } #ifdef HAVE_POLL diff --git a/sql/socketpair.c b/sql/socketpair.c new file mode 100644 index 00000000000..ef89fa0446b --- /dev/null +++ b/sql/socketpair.c @@ -0,0 +1,156 @@ +/* socketpair.c +Copyright 2007, 2010 by Nathan C. Myers +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + The name of the author must not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Changes: + * 2023-12-25 Addopted for MariaDB usage + * 2014-02-12: merge David Woodhouse, Ger Hobbelt improvements + * git.infradead.org/users/dwmw2/openconnect.git/commitdiff/bdeefa54 + * github.com/GerHobbelt/selectable-socketpair + * always init the socks[] to -1/INVALID_SOCKET on error, both on Win32/64 + * and UNIX/other platforms + * 2013-07-18: Change to BSD 3-clause license + * 2010-03-31: + * set addr to 127.0.0.1 because win32 getsockname does not always set it. + * 2010-02-25: + * set SO_REUSEADDR option to avoid leaking some windows resource. + * Windows System Error 10049, "Event ID 4226 TCP/IP has reached + * the security limit imposed on the number of concurrent TCP connect + * attempts." Bleah. + * 2007-04-25: + * preserve value of WSAGetLastError() on all error returns. + * 2007-04-22: (Thanks to Matthew Gregan ) + * s/EINVAL/WSAEINVAL/ fix trivial compile failure + * s/socket/WSASocket/ enable creation of sockets suitable as stdin/stdout + * of a child process. + * add argument make_overlapped + */ + +#include +#ifdef _WIN32 +#include /* socklen_t, et al (MSVC20xx) */ +#include +#include +#include "socketpair.h" + +#define safe_errno (errno != 0) ? errno : -1 + +/** + create_socketpair() + + @param socks[2] Will be filled by 2 SOCKET entries (similar to pipe()) + socks[0] for reading + socks[1] for writing + + @return: 0 ok + # System error code. -1 if unknown + */ + +int create_socketpair(SOCKET socks[2]) +{ + union + { + struct sockaddr_in inaddr; + struct sockaddr addr; + } a; + SOCKET listener= -1; + int reuse = 1; + int last_error; + socklen_t addrlen = sizeof(a.inaddr); + + socks[0]= socks[1]= -1; + + if ((listener= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) + return safe_errno; + + memset(&a, 0, sizeof(a)); + a.inaddr.sin_family = AF_INET; + a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + a.inaddr.sin_port = 0; + + for (;;) /* Avoid using goto */ + { + if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, + (char*) &reuse, (socklen_t) sizeof(reuse)) == -1) + break; + if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) + break; + + memset(&a, 0, sizeof(a)); + if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR) + break; + // win32 getsockname may only set the port number, p=0.0005. + // ( http://msdn.microsoft.com/library/ms738543.aspx ): + a.inaddr.sin_addr.s_addr= htonl(INADDR_LOOPBACK); + a.inaddr.sin_family= AF_INET; + + if (listen(listener, 1) == SOCKET_ERROR) + break; + + socks[1]= socket(AF_INET, SOCK_STREAM, 0); + if (socks[1] == -1) + break; + if (connect(socks[1], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) + break; + + socks[0]= accept(listener, NULL, NULL); + if (socks[0] == -1) + break; + + closesocket(listener); + + { + /* Make both sockets non blocking */ + ulong arg= 1; + ioctlsocket(socks[0], FIONBIO,(void*) &arg); + ioctlsocket(socks[1], FIONBIO,(void*) &arg); + } + return 0; + } + /* Error handling */ + last_error= WSAGetLastError(); + if (listener != -1) + closesocket(listener); + close_socketpair(socks); + WSASetLastError(last_error); + + return last_error; +} + +/* + Free socketpair +*/ + +void close_socketpair(SOCKET socks[2]) +{ + if (socks[0] != -1) + closesocket(socks[0]); + if (socks[1] != -1) + closesocket(socks[1]); + socks[0]= socks[1]= -1; +} + +#endif /*_WIN32 */ diff --git a/sql/socketpair.h b/sql/socketpair.h new file mode 100644 index 00000000000..d9f89c84ffa --- /dev/null +++ b/sql/socketpair.h @@ -0,0 +1,21 @@ +/* Copyright (c) 2023, MariaDB Plc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + 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 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 */ + +#ifdef _WIN32 +C_MODE_START + int create_socketpair(SOCKET socks[2]); + void close_socketpair(SOCKET socks[2]); +C_MODE_END +#endif /* _WIN32 */ From 2fcb5d651b98f9e480a251639ec2ed169b8f9355 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 12 Dec 2023 15:26:04 +0200 Subject: [PATCH 078/121] Fixed possible mutex-wrong-order with KILL USER The old code collected a list of THD's, locked the THD's from getting deleted by locking two mutex and then later in a separate loop sent a kill signal to each THD. The problem with this approach is that, as THD's can be reused, the second time the THD is killed, the mutex can be taken in different order, which signals failures in safe_mutex. Fixed by sending the kill signal directly and not collect the THD's in a list to be signaled later. This is the same approach we are using in kill_zombie_dump_threads(). Other things: - Reset safe_mutex_t->locked_mutex when freed (Safety fix) --- mysys/thr_mutex.c | 1 + sql/sql_parse.cc | 52 ++++++++++++++--------------------------------- 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index dd3a5ce132f..24000685aef 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -665,6 +665,7 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp) my_hash_free(mp->used_mutex); my_hash_free(mp->locked_mutex); my_free(mp->locked_mutex); + mp->locked_mutex= 0; mp->create_flags|= MYF_NO_DEADLOCK_DETECTION; } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c30c825ffb8..c17e24d9599 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -9371,11 +9371,13 @@ kill_one_thread(THD *thd, my_thread_id id, killed_state kill_signal, killed_type struct kill_threads_callback_arg { - kill_threads_callback_arg(THD *thd_arg, LEX_USER *user_arg): - thd(thd_arg), user(user_arg) {} + kill_threads_callback_arg(THD *thd_arg, LEX_USER *user_arg, + killed_state kill_signal_arg): + thd(thd_arg), user(user_arg), kill_signal(kill_signal_arg), counter(0) {} THD *thd; LEX_USER *user; - List threads_to_kill; + killed_state kill_signal; + uint counter; }; @@ -9398,11 +9400,12 @@ static my_bool kill_threads_callback(THD *thd, kill_threads_callback_arg *arg) { return MY_TEST(arg->thd->security_ctx->master_access & PROCESS_ACL); } - if (!arg->threads_to_kill.push_back(thd, arg->thd->mem_root)) - { - mysql_mutex_lock(&thd->LOCK_thd_kill); // Lock from delete - mysql_mutex_lock(&thd->LOCK_thd_data); - } + arg->counter++; + mysql_mutex_lock(&thd->LOCK_thd_kill); // Lock from delete + mysql_mutex_lock(&thd->LOCK_thd_data); + thd->awake_no_mutex(arg->kill_signal); + mysql_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_thd_kill); } } return 0; @@ -9412,42 +9415,17 @@ static my_bool kill_threads_callback(THD *thd, kill_threads_callback_arg *arg) static uint kill_threads_for_user(THD *thd, LEX_USER *user, killed_state kill_signal, ha_rows *rows) { - kill_threads_callback_arg arg(thd, user); + kill_threads_callback_arg arg(thd, user, kill_signal); DBUG_ENTER("kill_threads_for_user"); - - *rows= 0; - - if (unlikely(thd->is_fatal_error)) // If we run out of memory - DBUG_RETURN(ER_OUT_OF_RESOURCES); - DBUG_PRINT("enter", ("user: %s signal: %u", user->user.str, (uint) kill_signal)); + *rows= 0; + if (server_threads.iterate(kill_threads_callback, &arg)) DBUG_RETURN(ER_KILL_DENIED_ERROR); - if (!arg.threads_to_kill.is_empty()) - { - List_iterator_fast it2(arg.threads_to_kill); - THD *next_ptr; - THD *ptr= it2++; - do - { - ptr->awake_no_mutex(kill_signal); - /* - Careful here: The list nodes are allocated on the memroots of the - THDs to be awakened. - But those THDs may be terminated and deleted as soon as we release - LOCK_thd_kill, which will make the list nodes invalid. - Since the operation "it++" dereferences the "next" pointer of the - previous list node, we need to do this while holding LOCK_thd_kill. - */ - next_ptr= it2++; - mysql_mutex_unlock(&ptr->LOCK_thd_kill); - mysql_mutex_unlock(&ptr->LOCK_thd_data); - (*rows)++; - } while ((ptr= next_ptr)); - } + *rows= arg.counter; DBUG_RETURN(0); } From c49fd902632ad2c1547cfa63c1206ea26783ce3f Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 21 Dec 2023 18:25:39 +0200 Subject: [PATCH 079/121] Ensure keyread_tmp variable is assigned. In the case of calcuating cost for a ref access for which there exists a usable range, the variable keyread_tmp would always be 0. If there is also another index that could be used as a filter, the cost of that filter would be wrong. In many cases 'the worst_seeks optimzation' would disable the filter from getting used, which is why this bug has not been noticed before. The next commit, which allows one to disable worst_seeks, will have a test case for this bug. --- sql/sql_select.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f27126825ed..62c7f52748a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8219,6 +8219,9 @@ best_access_path(JOIN *join, trace_access_idx.add("used_range_estimates", true); tmp= adjust_quick_cost(table->opt_range[key].cost, table->opt_range[key].rows); + keyread_tmp= table->file->keyread_time(key, 1, + table->opt_range[key]. + rows); goto got_cost; } else From 6f65e08277a9e65c193367e18c5e7bf68f68e3d2 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 22 Dec 2023 13:53:57 +0200 Subject: [PATCH 080/121] MDEV-33118 optimizer_adjust_secondary_key_costs variable optimizer-adjust_secondary_key_costs is added to provide 2 small adjustments to the 10.x optimizer cost model. This can be used in the case where the optimizer wrongly uses a secondary key instead of a clustered primary key. The reason behind this change is that MariaDB 10.x does not take into account that for engines like InnoDB, that scanning a primary key can be up to 7x faster than scanning a secondary key + read the row data trough the primary key. The different values for optimizer_adjust_secondary_key_costs are: optimizer_adjust_secondary_key_costs=0 - No changes to current model optimizer_adjust_secondary_key_costs=1 - Ensure that the cost of of secondary indexes has a cost of at least 5x times the cost of a clustered primary key (if one exists). This disables part of the worst_seek optimization described below. optimizer_adjust_secondary_key_costs=2 - Disable "worst_seek optimization" and adjust filter cost slightly (add cost of 1 if filter is used). The idea behind 'worst_seek optimization' is that we limit the cost for all non clustered ref access to the least of: - best-rows-by-range (or all rows in no range found) / 10 - scan-time-table (roughly number of file blocks to scan table) * 3 In addition we also do not try to use rowid_filter if number of rows estimated for 'ref' access is less than the worst_seek limitation. The idea is that worst_seek is trying to take into account that if we do a lot of accesses through a key, this is likely to be cached. However it only does this for secondary keys, and not for clustered keys or index only reads. The effect of the worst_seek are: - In some cases 'ref' will have a much lower cost than range or using a clustered key. - Some possible rowid filters for secondary keys will be ignored. When implementing optimizer_adjust_secondary_key_costs=2, I noticed that there is a slightly different costs for how ref+filter and range+filter are calculated. This caused a lot of range and range+filter to change to ref+filter, which is not good as range+filter provides the optimizer a better estimate of how many accepted rows there will be in the result set. Adding a extra small cost (1 seek) when using filter mitigated the above problems in almost all cases. This patch should not be applied to MariaDB 11.0 as worst_seeks is removed in 11.0 and the cost calculation for clustered keys, secondary keys, index scan and filter is more exact. Test case changes for --optimizer-adjust_secondary_key_costs=1 (Fix secondary key costs to be 5x of primary key): - stat_tables_innodb: - Complex change (probably ok as number of rows are really small) - ref over 1 row changed to range over 10 rows with join buffer - ref over 5 rows changed to eq_ref - secondary ref over 1 row changed to ref of primary key over 4 rows - Change of key to use longer key with index pushdown (a little bit worse but not significant). - Change to use secondary (1 row) -> primary (4 rows) - rowid_filter_innodb: - index_merge (2 rows) & ref (1) -> all (23 rows) -> primary eq_ref. Test case changes for --optimizer-adjust_secondary_key_costs=2 (remove of worst_seeks & adjust filter cost): - stat_tables_innodb: - Join order change (probably ok as number of rows are really small) - ref (5 rows) & ref(1 row) changed to range (10 rows & join buffer) & eq_ref. - selectivity_innodb: - ref -> ref|filter (ok) - rowid_filter_innodb: - ref -> ref|filter (ok) - range|filter (64 rows) changed to ref|filter (128 rows). ok as ref|filter outputs wrong number of rows in explain. - range, range_mrr_icp: -ref (500 rows -> ALL (1000 rows) (ok) - select_pkeycache, select, select_jcl6: - ref|filter (2 rows) -> ref (2 rows) (ok) - selectivity: - ref -> ref_filter (ok) - range: - Change of 'filtered' but no stat or plan change (ok) - selectivity: - ref -> ref+filter (ok) - Change of filtered but no plan change (ok) - join_nested_jcl6: - range -> ref|filter (ok as only 2 rows) - subselect3, subselect3_jcl6: - ref_or_null (4 rows) -> ALL (10 rows) (ok) - Index_subquery (4 rows) -> ALL (10 rows) (ok) - partition_mrr_myisam, partition_mrr_aria and partition_mrr_innodb: - Uses ALL instead of REF for a key value that is the same for > 50% of rows. (good) order_by_innodb: - range (200 rows) -> ref (20 rows)+filesort (ok) - subselect_sj2_mat: - One test changed. One ALL removed and replaced with eq_ref. Likely to be better. - join_cache: - Changed ref over 60% of the rows to use hash join (ok) - opt_tvc: - Changed to use eq_ref instead of ref with plan change (probably ok) - opt_trace: - No worst/max seeks clipping (good). - Almost double range_scan_time and index_scan_time (ok). - rowid_filter: - ref -> ref|filtered (ok) - range|filter (77 rows) changed to ref|filter (151 rows). Proably ok as ref|filter outputs wrong number of rows in explain. Reviewer: Sergei Petrunia --- mysql-test/main/mysqld--help.result | 8 ++ mysql-test/main/secondary_key_costs.result | 82 +++++++++++++++++++ mysql-test/main/secondary_key_costs.test | 53 ++++++++++++ .../sys_vars/r/sysvars_server_embedded.result | 10 +++ .../r/sysvars_server_notembedded.result | 10 +++ sql/sql_class.h | 3 +- sql/sql_select.cc | 48 +++++++++-- sql/sys_vars.cc | 13 +++ 8 files changed, 219 insertions(+), 8 deletions(-) create mode 100644 mysql-test/main/secondary_key_costs.result create mode 100644 mysql-test/main/secondary_key_costs.test diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 219bad22528..d8a8fe449b6 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -712,6 +712,13 @@ The following specify which files/extra groups are read (specified before remain max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors (Automatically configured unless set explicitly) + --optimizer-adjust-secondary-key-costs=# + 0 = No changes. 1 = Update secondary key costs for ranges + to be at least 5x of clustered primary key costs. 2 = + Remove 'max_seek optimization' for secondary keys and + slight adjustment of filter cost. This option will be + deleted in MariaDB 11.0 as it is not needed with the new + 11.0 optimizer. --optimizer-max-sel-arg-weight=# The maximum weight of the SEL_ARG graph. Set to 0 for no limit @@ -1684,6 +1691,7 @@ old-alter-table DEFAULT old-mode UTF8_IS_UTF8MB3 old-passwords FALSE old-style-user-limits FALSE +optimizer-adjust-secondary-key-costs 0 optimizer-max-sel-arg-weight 32000 optimizer-max-sel-args 16000 optimizer-prune-level 1 diff --git a/mysql-test/main/secondary_key_costs.result b/mysql-test/main/secondary_key_costs.result new file mode 100644 index 00000000000..55c84705abf --- /dev/null +++ b/mysql-test/main/secondary_key_costs.result @@ -0,0 +1,82 @@ +create table t1 ( +pk int primary key auto_increment, +nm varchar(32), +fl1 tinyint default 0, +fl2 tinyint default 0, +index idx1(nm, fl1), +index idx2(fl2) +) engine=myisam; +create table name ( +pk int primary key auto_increment, +nm bigint +) engine=myisam; +create table flag2 ( +pk int primary key auto_increment, +fl2 tinyint +) engine=myisam; +insert into name(nm) select seq from seq_1_to_1000 order by rand(17); +insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19); +insert into t1(nm,fl2) +select nm, fl2 from name, flag2 where name.pk = flag2.pk; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +set optimizer_trace="enabled=on"; +set optimizer_switch='rowid_filter=on'; +set statement optimizer_adjust_secondary_key_costs=0 for +explain select * from t1 where nm like '500%' AND fl2 = 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where +set @trace=(select trace from information_schema.optimizer_trace); +select json_detailed(json_extract(@trace, '$**.considered_access_paths')); +json_detailed(json_extract(@trace, '$**.considered_access_paths')) +[ + [ + { + "access_type": "ref", + "index": "idx2", + "used_range_estimates": true, + "rowid_filter_skipped": "worst/max seeks clipping", + "rows": 492, + "cost": 492.3171406, + "chosen": true + }, + { + "access_type": "range", + "resulting_rows": 0.492, + "cost": 1.448699097, + "chosen": true + } + ] +] + +The following trace should have a different rowid_filter_key cost + +set statement optimizer_adjust_secondary_key_costs=2 for +explain select * from t1 where nm like '500%' AND fl2 = 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range idx1,idx2 idx1 35 NULL 1 Using index condition; Using where +set @trace=(select trace from information_schema.optimizer_trace); +select json_detailed(json_extract(@trace, '$**.considered_access_paths')); +json_detailed(json_extract(@trace, '$**.considered_access_paths')) +[ + [ + { + "access_type": "ref", + "index": "idx2", + "used_range_estimates": true, + "rowid_filter_key": "idx1", + "rows": 492, + "cost": 3.814364688, + "chosen": true + }, + { + "access_type": "range", + "resulting_rows": 0.492, + "cost": 1.448699097, + "chosen": true + } + ] +] +drop table t1, name, flag2; diff --git a/mysql-test/main/secondary_key_costs.test b/mysql-test/main/secondary_key_costs.test new file mode 100644 index 00000000000..d3db137653b --- /dev/null +++ b/mysql-test/main/secondary_key_costs.test @@ -0,0 +1,53 @@ +--source include/have_sequence.inc +--source include/not_embedded.inc + +# +# Show the costs for rowid filter +# + +create table t1 ( + pk int primary key auto_increment, + nm varchar(32), + fl1 tinyint default 0, + fl2 tinyint default 0, + index idx1(nm, fl1), + index idx2(fl2) +) engine=myisam; + +create table name ( + pk int primary key auto_increment, + nm bigint +) engine=myisam; + +create table flag2 ( + pk int primary key auto_increment, + fl2 tinyint +) engine=myisam; + +insert into name(nm) select seq from seq_1_to_1000 order by rand(17); +insert into flag2(fl2) select seq mod 2 from seq_1_to_1000 order by rand(19); + +insert into t1(nm,fl2) + select nm, fl2 from name, flag2 where name.pk = flag2.pk; + +analyze table t1 persistent for all; + +--disable_ps_protocol +set optimizer_trace="enabled=on"; +set optimizer_switch='rowid_filter=on'; +set statement optimizer_adjust_secondary_key_costs=0 for +explain select * from t1 where nm like '500%' AND fl2 = 0; +set @trace=(select trace from information_schema.optimizer_trace); +select json_detailed(json_extract(@trace, '$**.considered_access_paths')); + +--echo +--echo The following trace should have a different rowid_filter_key cost +--echo +set statement optimizer_adjust_secondary_key_costs=2 for +explain select * from t1 where nm like '500%' AND fl2 = 0; +set @trace=(select trace from information_schema.optimizer_trace); +select json_detailed(json_extract(@trace, '$**.considered_access_paths')); + +--enable_ps_protocol + +drop table t1, name, flag2; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 8e50d8e7268..aa88a8f74a8 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2272,6 +2272,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_ADJUST_SECONDARY_KEY_COSTS +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT 0 = No changes. 1 = Update secondary key costs for ranges to be at least 5x of clustered primary key costs. 2 = Remove 'max_seek optimization' for secondary keys and slight adjustment of filter cost. This option will be deleted in MariaDB 11.0 as it is not needed with the new 11.0 optimizer. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 2 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED 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 00c66ddf072..c07b7169608 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -2432,6 +2432,16 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_ADJUST_SECONDARY_KEY_COSTS +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT 0 = No changes. 1 = Update secondary key costs for ranges to be at least 5x of clustered primary key costs. 2 = Remove 'max_seek optimization' for secondary keys and slight adjustment of filter cost. This option will be deleted in MariaDB 11.0 as it is not needed with the new 11.0 optimizer. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 2 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED diff --git a/sql/sql_class.h b/sql/sql_class.h index d61ee1545b6..5175d440136 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -698,7 +698,6 @@ typedef struct system_variables ulonglong max_statement_time; ulonglong optimizer_switch; ulonglong optimizer_trace; - ulong optimizer_trace_max_mem_size; sql_mode_t sql_mode; ///< which non-standard SQL behaviour should be enabled sql_mode_t old_behavior; ///< which old SQL behaviour should be enabled ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING @@ -761,6 +760,8 @@ typedef struct system_variables ulong optimizer_use_condition_selectivity; ulong optimizer_max_sel_arg_weight; ulong optimizer_max_sel_args; + ulong optimizer_trace_max_mem_size; + ulong optimizer_adjust_secondary_key_costs; ulong use_stat_tables; double sample_percentage; ulong histogram_size; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 62c7f52748a..b1779ebc24d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5895,11 +5895,15 @@ make_join_statistics(JOIN *join, List &tables_list, This is can't be to high as otherwise we are likely to use table scan. */ - s->worst_seeks= MY_MIN((double) s->found_records / 10, - (double) s->read_time*3); - if (s->worst_seeks < 2.0) // Fix for small tables - s->worst_seeks=2.0; - + /* Largest integer that can be stored in double (no compiler warning) */ + s->worst_seeks= (double) (1ULL << 53); + if (thd->variables.optimizer_adjust_secondary_key_costs != 2) + { + s->worst_seeks= MY_MIN((double) s->found_records / 10, + (double) s->read_time*3); + if (s->worst_seeks < 2.0) // Fix for small tables + s->worst_seeks=2.0; + } /* Add to stat->const_keys those indexes for which all group fields or all select distinct fields participate in one index. @@ -7817,8 +7821,27 @@ double cost_for_index_read(const THD *thd, const TABLE *table, uint key, if (table->covering_keys.is_set(key)) cost= file->keyread_time(key, 1, records); else + { cost= ((file->keyread_time(key, 0, records) + file->read_time(key, 1, MY_MIN(records, worst_seeks)))); + if (thd->variables.optimizer_adjust_secondary_key_costs == 1 && + file->is_clustering_key(0)) + { + /* + According to benchmarks done in 11.0 to calculate the new cost + model secondary key ranges are about 7x slower than primary + key ranges for big tables. Here we are a bit conservative and + only calculate with 5x. The reason for having it only 5x and + not for example 7x is is that choosing plans with more rows + that are read (ignored by the WHERE clause) causes the 10.x + optimizer to believe that there are more rows in the result + set, which can cause problems in finding the best join order. + Note: A clustering primary key is always key 0. + */ + double clustering_key_cost= file->read_time(0, 1, records); + cost= MY_MAX(cost, clustering_key_cost * 5); + } + } DBUG_PRINT("statistics", ("cost: %.3f", cost)); DBUG_RETURN(cost); @@ -7992,6 +8015,14 @@ best_access_path(JOIN *join, double keyread_tmp= 0; ha_rows rec; bool best_uses_jbuf= FALSE; + /* + if optimizer_use_condition_selectivity adjust filter cost to be slightly + higher to ensure that ref|filter is not less than range over same + number of rows + */ + double filter_setup_cost= (thd->variables. + optimizer_adjust_secondary_key_costs == 2 ? + 1.0 : 0.0); MY_BITMAP *eq_join_set= &s->table->eq_join_set; KEYUSE *hj_start_key= 0; SplM_plan_info *spl_plan= 0; @@ -8548,6 +8579,7 @@ best_access_path(JOIN *join, type == JT_EQ_REF ? 0.5 * tmp : MY_MIN(tmp, keyread_tmp); double access_cost_factor= MY_MIN((tmp - key_access_cost) / rows, 1.0); + if (!(records < s->worst_seeks && records <= thd->variables.max_seeks_for_key)) { @@ -8564,7 +8596,9 @@ best_access_path(JOIN *join, } if (filter) { - tmp-= filter->get_adjusted_gain(rows) - filter->get_cmp_gain(rows); + tmp-= (filter->get_adjusted_gain(rows) - + filter->get_cmp_gain(rows) - + filter_setup_cost); DBUG_ASSERT(tmp >= 0); trace_access_idx.add("rowid_filter_key", table->key_info[filter->key_no].name); @@ -8810,7 +8844,7 @@ best_access_path(JOIN *join, access_cost_factor); if (filter) { - tmp-= filter->get_adjusted_gain(rows); + tmp-= filter->get_adjusted_gain(rows) - filter_setup_cost; DBUG_ASSERT(tmp >= 0); } diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index dea04bf3bc5..61911d877e5 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2817,6 +2817,19 @@ static Sys_var_ulong Sys_optimizer_trace_max_mem_size( SESSION_VAR(optimizer_trace_max_mem_size), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, ULONG_MAX), DEFAULT(1024 * 1024), BLOCK_SIZE(1)); +static Sys_var_ulong Sys_optimizer_adjust_secondary_key_costs( + "optimizer_adjust_secondary_key_costs", + "0 = No changes. " + "1 = Update secondary key costs for ranges to be at least 5x of clustered " + "primary key costs. " + "2 = Remove 'max_seek optimization' for secondary keys and slight " + "adjustment of filter cost. " + "This option will be deleted in MariaDB 11.0 as it is not needed with the " + "new 11.0 optimizer.", + SESSION_VAR(optimizer_adjust_secondary_key_costs), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 2), DEFAULT(0), BLOCK_SIZE(1)); + + static Sys_var_charptr_fscs Sys_pid_file( "pid_file", "Pid file used by safe_mysqld", READ_ONLY GLOBAL_VAR(pidfile_name_ptr), CMD_LINE(REQUIRED_ARG), From 3c63e2f89051457033d48920e6f7aebd082ddad3 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 27 Dec 2023 19:58:59 +0200 Subject: [PATCH 081/121] Temporary table name used by multip-update has 'null' as part of the name Problem was that TMP_TABLE_PARAM was not properly initialized --- sql/sql_update.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7fd5c864c06..980fa0fbddc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2431,7 +2431,8 @@ loop_end: group.direction= ORDER::ORDER_ASC; group.item= (Item**) temp_fields.head_ref(); - tmp_param->quick_group= 1; + tmp_param->init(); + tmp_param->tmp_name="update"; tmp_param->field_count= temp_fields.elements; tmp_param->func_count= temp_fields.elements - 1; calc_group_buffer(tmp_param, &group); From 740d3e7a7472d19fc8636d42bbcfbafa0a283f11 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 5 Jan 2024 15:29:07 +0200 Subject: [PATCH 082/121] Trivial fixes: - Removed not used variable 'file' from MYSQL_BIN_LOG::open() - Assigned not initialized variable in connect/tabext.cpp --- sql/log.cc | 5 ----- storage/connect/tabext.cpp | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 3ca387d5ab9..401ce408c5f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3694,7 +3694,6 @@ bool MYSQL_BIN_LOG::open(const char *log_name, bool null_created_arg, bool need_mutex) { - File file= -1; xid_count_per_binlog *new_xid_list_entry= NULL, *b; DBUG_ENTER("MYSQL_BIN_LOG::open"); @@ -4090,8 +4089,6 @@ err: sql_print_error(fatal_log_error, (name) ? name : log_name, tmp_errno); if (new_xid_list_entry) delete new_xid_list_entry; - if (file >= 0) - mysql_file_close(file, MYF(0)); close(LOG_CLOSE_INDEX); DBUG_RETURN(1); } @@ -5363,8 +5360,6 @@ int MYSQL_BIN_LOG::new_file_without_locking() /** Start writing to a new log file or reopen the old file. - @param need_lock Set to 1 if caller has not locked LOCK_log - @retval nonzero - error diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp index f558cb04f4d..e8b9da63c22 100644 --- a/storage/connect/tabext.cpp +++ b/storage/connect/tabext.cpp @@ -330,7 +330,7 @@ bool TDBEXT::MakeSrcdef(PGLOBAL g) char *catp = strstr(Srcdef, "%s"); if (catp) { - char *fil1 = 0, *fil2; + char *fil1 = 0, *fil2= 0; PCSZ ph = ((EXTDEF*)To_Def)->Phpos; if (!ph) From c777429cf90288c2fb6ac1ab1347826ed2125b7d Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 19 Jan 2024 12:01:28 +0200 Subject: [PATCH 083/121] MDEV-33279 Disable transparent huge pages after page buffers has been allocatedDisable transparent huge pages (THP) The reason for disabling transparent huge pages (THP) is that they do not work well with MariaDB (or other databases, see links in MDEV-33279). The effect of using THP are that MariaDB will use much more (10x) more memory and will no be able to release memory back to the system. Disabling THP is done after all storage engines are started, to allow buffer pools and keybuffers (big allocations) to be allocated as huge pages. --- sql/mysqld.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2766bc00e3a..b07b7a414af 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5451,6 +5451,15 @@ static int init_server_components() #else locked_in_memory= 0; #endif +#ifdef PR_SET_THP_DISABLE + /* + Engine page buffers are now allocated. + Disable transparent huge pages for all + future allocations as these causes memory + leaks. + */ + prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0); +#endif ft_init_stopwords(); From d2c431bccbbd6ee74297a0dd9da44b2fe20c24d5 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 20 Jan 2024 17:09:38 +0200 Subject: [PATCH 084/121] Disable main.gis from embedded Fails with: query 'select ST_AsWKT(GeometryCollection(Point(44, 6), @g))' failed: ER_ILLEGAL_VALUE_FOR_TYPE (1367): Illegal non geometric '@`g`' value found during parsing --- mysql-test/main/gis.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index f160d8f1a10..b51080d2e1b 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -1,5 +1,5 @@ -- source include/have_geometry.inc - +-- source include/not_embedded.inc # # Spatial objects From 286d6f239a6f149208c30797ded3ad56af13fc18 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 20 Jan 2024 17:41:33 +0200 Subject: [PATCH 085/121] Fixed main.strict test to work with icc compiler --- mysql-test/main/strict.result | 2 +- mysql-test/main/strict.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/strict.result b/mysql-test/main/strict.result index 3163059956c..d9d92402927 100644 --- a/mysql-test/main/strict.result +++ b/mysql-test/main/strict.result @@ -897,7 +897,7 @@ ERROR 22003: Out of range value for column 'col1' at row 1 INSERT INTO t1 (col2) VALUES ('-1.2E-3'); ERROR 22003: Out of range value for column 'col2' at row 1 UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0; -ERROR 22003: DOUBLE value is out of range in '"test"."t1"."col1" * 5000' +Got one of the listed errors UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0; ERROR 22012: Division by 0 UPDATE t1 SET col2= MOD(col2,0) WHERE col2 > 0; diff --git a/mysql-test/main/strict.test b/mysql-test/main/strict.test index 830f051a5f6..1819f399041 100644 --- a/mysql-test/main/strict.test +++ b/mysql-test/main/strict.test @@ -824,7 +824,7 @@ INSERT INTO t1 (col2) VALUES (-1.1E-3); INSERT INTO t1 (col1) VALUES ('+1.8E+309'); --error 1264 INSERT INTO t1 (col2) VALUES ('-1.2E-3'); ---error ER_DATA_OUT_OF_RANGE +--error ER_DATA_OUT_OF_RANGE, ER_WARN_DATA_OUT_OF_RANGE UPDATE t1 SET col1 =col1 * 5000 WHERE col1 > 0; --error 1365 UPDATE t1 SET col2 =col2 / 0 WHERE col2 > 0; From 6085fb199a8a7da68c2ecc3c86452974c7b77dad Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 21 Jan 2024 16:52:19 +0200 Subject: [PATCH 086/121] Fixed compiler error/warning in backup_copy.cc --- extra/mariabackup/backup_copy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index f25570f32bb..04154be0538 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -2308,7 +2308,7 @@ ds_ctxt_t::make_hardlink(const char *from_path, const char *to_path) } else { - strncpy(to_path_full, to_path, sizeof(to_path_full)); + strncpy(to_path_full, to_path, sizeof(to_path_full)-1); } #ifdef _WIN32 return CreateHardLink(to_path_full, from_path, NULL); From 26c86c39fcf366aa14f8f948889c23e7a5be3702 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 21 Jan 2024 19:10:37 +0200 Subject: [PATCH 087/121] Fixed some mtr tests that failed on windows Most things where wrong in the test suite. The one thing that was a bug was that table_map_id was in some places defined as ulong and in other places as ulonglong. On Linux 64 bit this is not a problem as ulong == ulonglong, but on windows this caused failures. Fixed by ensuring that all instances of table_map_id are ulonglong. --- extra/mariabackup/xtrabackup.cc | 2 +- libmysqld/libmysql.c | 6 +- mysql-test/suite/multi_source/mdev-9544.test | 1 + .../suite/rpl/r/rpl_row_big_table_id.result | 16 +- .../r/sysvars_server_notembedded,win.rdiff | 1465 +++++++++++++++++ mysql-test/suite/sys_vars/t/sysvars_star.test | 4 +- plugin/file_key_management/parser.cc | 2 +- sql/item_strfunc.cc | 2 +- sql/log.cc | 5 +- sql/log_event.cc | 7 +- sql/log_event.h | 24 +- sql/log_event_client.cc | 4 +- sql/log_event_old.cc | 29 +- sql/log_event_old.h | 12 +- sql/log_event_server.cc | 41 +- sql/sql_analyse.cc | 3 +- sql/sql_class.cc | 3 +- sql/table.cc | 18 +- sql/table.h | 10 +- storage/myisammrg/ha_myisammrg.h | 6 +- .../bugfix/t/mdev_32753_after_start.test | 1 + .../spider/include/clean_up_spider.inc | 1 + 22 files changed, 1576 insertions(+), 86 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 74ea06e35ee..0dc2dda4705 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -2190,7 +2190,7 @@ static bool innodb_init_param() /* Check that values don't overflow on 32-bit systems. */ if (sizeof(ulint) == 4) { - if (xtrabackup_use_memory > UINT_MAX32) { + if (xtrabackup_use_memory > (longlong) UINT_MAX32) { msg("mariabackup: use-memory can't be over 4GB" " on 32-bit systems"); } diff --git a/libmysqld/libmysql.c b/libmysqld/libmysql.c index 7f55b0c2726..07926763c61 100644 --- a/libmysqld/libmysql.c +++ b/libmysqld/libmysql.c @@ -3229,7 +3229,8 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, size_t { longlong data= my_strtoll10(value, &endptr, &err); *param->error= (IS_TRUNCATED(data, param->is_unsigned, - INT_MIN32, INT_MAX32, UINT_MAX32) || err > 0); + (longlong) INT_MIN32, (longlong) INT_MAX32, + (longlong) UINT_MAX32) || err > 0); longstore(buffer, (int32) data); break; } @@ -3346,7 +3347,8 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, break; case MYSQL_TYPE_LONG: *param->error= IS_TRUNCATED(value, param->is_unsigned, - INT_MIN32, INT_MAX32, UINT_MAX32); + (longlong) INT_MIN32, (longlong) INT_MAX32, + (longlong) UINT_MAX32); longstore(buffer, (int32) value); break; case MYSQL_TYPE_LONGLONG: diff --git a/mysql-test/suite/multi_source/mdev-9544.test b/mysql-test/suite/multi_source/mdev-9544.test index f532a63a585..7b1169e7522 100644 --- a/mysql-test/suite/multi_source/mdev-9544.test +++ b/mysql-test/suite/multi_source/mdev-9544.test @@ -1,6 +1,7 @@ --source include/not_embedded.inc --source include/have_innodb.inc --source include/have_debug.inc +--source include/not_windows.inc --connect (server_1,127.0.0.1,root,,,$SERVER_MYPORT_1) --connect (server_2,127.0.0.1,root,,,$SERVER_MYPORT_2) diff --git a/mysql-test/suite/rpl/r/rpl_row_big_table_id.result b/mysql-test/suite/rpl/r/rpl_row_big_table_id.result index 694a6132244..0c51e58f5a7 100644 --- a/mysql-test/suite/rpl/r/rpl_row_big_table_id.result +++ b/mysql-test/suite/rpl/r/rpl_row_big_table_id.result @@ -21,23 +21,23 @@ master-bin.000001 # Gtid 1 # GTID #-#-# master-bin.000001 # Query 1 # use `test`; ALTER TABLE t comment '' master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# master-bin.000001 # Annotate_rows 1 # INSERT INTO t SET a= 1 -master-bin.000001 # Table_map 1 # table_id: 4294967295 (test.t) -master-bin.000001 # Write_rows_v1 1 # table_id: 4294967295 flags: STMT_END_F -master-bin.000001 # Query 1 # COMMIT -master-bin.000001 # Gtid 1 # GTID #-#-# -master-bin.000001 # Query 1 # use `test`; ALTER TABLE t comment '' -master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows 1 # INSERT INTO t SET a= 2 master-bin.000001 # Table_map 1 # table_id: 4294967296 (test.t) master-bin.000001 # Write_rows_v1 1 # table_id: 4294967296 flags: STMT_END_F master-bin.000001 # Query 1 # COMMIT master-bin.000001 # Gtid 1 # GTID #-#-# master-bin.000001 # Query 1 # use `test`; ALTER TABLE t comment '' master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows 1 # INSERT INTO t SET a= 3 +master-bin.000001 # Annotate_rows 1 # INSERT INTO t SET a= 2 master-bin.000001 # Table_map 1 # table_id: 4294967297 (test.t) master-bin.000001 # Write_rows_v1 1 # table_id: 4294967297 flags: STMT_END_F master-bin.000001 # Query 1 # COMMIT +master-bin.000001 # Gtid 1 # GTID #-#-# +master-bin.000001 # Query 1 # use `test`; ALTER TABLE t comment '' +master-bin.000001 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000001 # Annotate_rows 1 # INSERT INTO t SET a= 3 +master-bin.000001 # Table_map 1 # table_id: 4294967298 (test.t) +master-bin.000001 # Write_rows_v1 1 # table_id: 4294967298 flags: STMT_END_F +master-bin.000001 # Query 1 # COMMIT connection slave; connection master; SET debug_dbug=@old_debug_dbug; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff new file mode 100644 index 00000000000..acee8a39b43 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,win.rdiff @@ -0,0 +1,1465 @@ +--- suite/sys_vars/r/sysvars_server_notembedded.result ++++ suite/sys_vars/r/sysvars_server_notembedded.reject +@@ -34,7 +34,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_BLOCK_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Block size to be used for Aria index pages. + NUMERIC_MIN_VALUE 4096 + NUMERIC_MAX_VALUE 32768 +@@ -44,7 +44,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_CHECKPOINT_INTERVAL + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Interval between tries to do an automatic checkpoints. In seconds; 0 means 'no automatic checkpoints' which makes sense only for testing. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -54,7 +54,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_CHECKPOINT_LOG_ACTIVITY + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of bytes that the transaction log has to grow between checkpoints before a new checkpoint is written to the log. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -74,7 +74,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME ARIA_FORCE_START_AFTER_RECOVERY_FAILURES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of consecutive log recovery failures after which logs will be automatically deleted to cure the problem; 0 (the default) disables the feature. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 255 +@@ -94,7 +94,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_GROUP_COMMIT_INTERVAL + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Interval between commits in microseconds (1/1000000 sec). 0 stands for no waiting for other threads to come and do a commit in "hard" mode and no sync()/commit at all in "soft" mode. Option has only an effect if aria_group_commit is used + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -114,7 +114,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_LOG_FILE_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Limit for transaction log size + NUMERIC_MIN_VALUE 8388608 + NUMERIC_MAX_VALUE 4294967295 +@@ -144,10 +144,10 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_PAGECACHE_AGE_THRESHOLD + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in the page cache. + NUMERIC_MIN_VALUE 100 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 100 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -164,7 +164,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_PAGECACHE_DIVISION_LIMIT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The minimum percentage of warm blocks in key cache + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 100 +@@ -174,7 +174,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME ARIA_PAGECACHE_FILE_HASH_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of hash buckets for open and changed files. If you have a lot of Aria files open you should increase this for faster flush of changes. A good value is probably 1/10 of number of possible open Aria files. + NUMERIC_MIN_VALUE 128 + NUMERIC_MAX_VALUE 16384 +@@ -204,7 +204,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME ARIA_REPAIR_THREADS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of threads to use when repairing Aria tables. The value of 1 disables parallel repair. + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 128 +@@ -274,7 +274,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME AUTO_INCREMENT_INCREMENT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Auto-increment columns are incremented by this + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 65535 +@@ -284,7 +284,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME AUTO_INCREMENT_OFFSET + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1 + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 65535 +@@ -294,7 +294,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME BACK_LOG + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 65535 +@@ -364,20 +364,20 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME BINLOG_COMMIT_WAIT_COUNT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If non-zero, binlog write will wait at most binlog_commit_wait_usec microseconds for at least this many commits to queue up for group commit to the binlog. This can reduce I/O on the binlog and provide increased opportunity for parallel apply on the slave, but too high a value will decrease commit throughput. + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME BINLOG_COMMIT_WAIT_USEC + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum time, in microseconds, to wait for more commits to queue up for binlog group commit. Only takes effect if the value of binlog_commit_wait_count is non-zero. + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -394,7 +394,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME BINLOG_EXPIRE_LOGS_SECONDS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If non-zero, binary logs will be purged after binlog_expire_logs_seconds seconds; It and expire_logs_days are linked, such that changes in one are converted into the other. Possible purges happen at startup and at binary log rotation. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 8553600 +@@ -654,7 +654,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME CONNECT_TIMEOUT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake' + NUMERIC_MIN_VALUE 2 + NUMERIC_MAX_VALUE 31536000 +@@ -704,7 +704,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_LONG + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Long search depth for the two-step deadlock detection + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 33 +@@ -714,7 +714,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME DEADLOCK_SEARCH_DEPTH_SHORT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Short search depth for the two-step deadlock detection + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 32 +@@ -724,7 +724,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME DEADLOCK_TIMEOUT_LONG + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds) + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -734,7 +734,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME DEADLOCK_TIMEOUT_SHORT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -794,7 +794,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME DEFAULT_WEEK_FORMAT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The default week format used by WEEK() functions + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 7 +@@ -804,7 +804,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME DELAYED_INSERT_LIMIT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -814,7 +814,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME DELAYED_INSERT_TIMEOUT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 31536000 +@@ -824,7 +824,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME DELAYED_QUEUE_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -854,7 +854,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME DIV_PRECISION_INCREMENT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 38 +@@ -974,7 +974,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME EXTRA_MAX_CONNECTIONS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of connections on extra-port + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 100000 +@@ -1004,7 +1004,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME FLUSH_TIME + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 31536000 +@@ -1034,7 +1034,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME FT_MAX_WORD_LEN + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable + NUMERIC_MIN_VALUE 10 + NUMERIC_MAX_VALUE 84 +@@ -1044,7 +1044,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME FT_MIN_WORD_LEN + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 84 +@@ -1054,7 +1054,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME FT_QUERY_EXPANSION_LIMIT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of best matches to use for query expansion + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1000 +@@ -1304,7 +1304,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME HISTOGRAM_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 255 +@@ -1334,7 +1334,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME HOST_CACHE_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT How many host names should be cached to avoid resolving. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 65536 +@@ -1357,7 +1357,7 @@ + VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of seconds the server waits for read-only idle transaction + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 31536000 ++NUMERIC_MAX_VALUE 2147483 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -1367,7 +1367,7 @@ + VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of seconds the server waits for idle transaction + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 31536000 ++NUMERIC_MAX_VALUE 2147483 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -1377,7 +1377,7 @@ + VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of seconds the server waits for write idle transaction + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 31536000 ++NUMERIC_MAX_VALUE 2147483 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -1444,7 +1444,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME INTERACTIVE_TIMEOUT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 31536000 +@@ -1494,7 +1494,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME JOIN_CACHE_LEVEL + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 8 +@@ -1672,19 +1672,9 @@ + ENUM_VALUE_LIST OFF,ON + READ_ONLY NO + COMMAND_LINE_ARGUMENT OPTIONAL +-VARIABLE_NAME LOCKED_IN_MEMORY +-VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BOOLEAN +-VARIABLE_COMMENT Whether mysqld was locked in memory with --memlock +-NUMERIC_MIN_VALUE NULL +-NUMERIC_MAX_VALUE NULL +-NUMERIC_BLOCK_SIZE NULL +-ENUM_VALUE_LIST OFF,ON +-READ_ONLY YES +-COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME LOCK_WAIT_TIMEOUT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 31536000 +@@ -1834,7 +1824,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME LOG_SLOW_MAX_WARNINGS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Max numbers of warnings printed to slow query log per statement + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1000 +@@ -1844,7 +1834,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME LOG_SLOW_RATE_LIMIT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -1874,7 +1864,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME LOG_WARNINGS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Log some non critical warnings to the error log.Value can be between 0 and 11. Higher values mean more verbosity + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -1934,7 +1924,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME MAX_ALLOWED_PACKET + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Max packet length to send to or receive from the server + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 1073741824 +@@ -1954,7 +1944,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_BINLOG_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. + NUMERIC_MIN_VALUE 4096 + NUMERIC_MAX_VALUE 1073741824 +@@ -1974,7 +1964,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_CONNECTIONS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of simultaneous clients allowed + NUMERIC_MIN_VALUE 10 + NUMERIC_MAX_VALUE 100000 +@@ -1984,7 +1974,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_CONNECT_ERRORS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -1994,7 +1984,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_DELAYED_THREADS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16384 +@@ -2014,7 +2004,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_ERROR_COUNT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Max number of errors/warnings to store for a statement + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 65535 +@@ -2034,7 +2024,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_INSERT_DELAYED_THREADS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16384 +@@ -2054,7 +2044,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_LENGTH_FOR_SORT_DATA + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Max number of bytes in sorted records + NUMERIC_MIN_VALUE 4 + NUMERIC_MAX_VALUE 8388608 +@@ -2084,7 +2074,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_RECURSIVE_ITERATIONS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of iterations when executing recursive queries + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -2114,7 +2104,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_SEEKS_FOR_KEY + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -2134,7 +2124,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_SORT_LENGTH + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) + NUMERIC_MIN_VALUE 64 + NUMERIC_MAX_VALUE 8388608 +@@ -2144,7 +2134,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_SP_RECURSION_DEPTH + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum stored procedure recursion depth + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 255 +@@ -2164,7 +2154,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_TMP_TABLES + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Unused, will be removed. + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -2184,7 +2174,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MAX_WRITE_LOCK_COUNT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT After this many write locks, allow some read locks to run in between + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -2194,7 +2184,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME METADATA_LOCKS_CACHE_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Unused + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 1048576 +@@ -2204,7 +2194,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME METADATA_LOCKS_HASH_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Unused + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 1024 +@@ -2214,7 +2204,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MIN_EXAMINED_ROW_LIMIT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -2224,7 +2214,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MRR_BUFFER_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Size of buffer to use when using MRR with range access + NUMERIC_MIN_VALUE 8192 + NUMERIC_MAX_VALUE 2147483647 +@@ -2234,7 +2224,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MYISAM_BLOCK_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Block size to be used for MyISAM index pages + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 16384 +@@ -2244,7 +2234,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME MYISAM_DATA_POINTER_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Default pointer size to be used for MyISAM tables + NUMERIC_MIN_VALUE 2 + NUMERIC_MAX_VALUE 7 +@@ -2284,10 +2274,10 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME MYISAM_REPAIR_THREADS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If larger than 1, when repairing a MyISAM table all indexes will be created in parallel, with one thread per index. The value of 1 disables parallel repair + NUMERIC_MIN_VALUE 1 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -2332,9 +2322,19 @@ + ENUM_VALUE_LIST OFF,ON + READ_ONLY NO + COMMAND_LINE_ARGUMENT OPTIONAL ++VARIABLE_NAME NAMED_PIPE ++VARIABLE_SCOPE GLOBAL ++VARIABLE_TYPE BOOLEAN ++VARIABLE_COMMENT Enable the named pipe (NT) ++NUMERIC_MIN_VALUE NULL ++NUMERIC_MAX_VALUE NULL ++NUMERIC_BLOCK_SIZE NULL ++ENUM_VALUE_LIST OFF,ON ++READ_ONLY YES ++COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME NET_BUFFER_LENGTH + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Buffer length for TCP/IP and socket communication + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 1048576 +@@ -2344,7 +2344,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME NET_READ_TIMEOUT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 31536000 +@@ -2354,7 +2354,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME NET_RETRY_COUNT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -2364,7 +2364,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME NET_WRITE_TIMEOUT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 31536000 +@@ -2424,7 +2424,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME OPEN_FILES_LIMIT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -2434,7 +2434,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_ADJUST_SECONDARY_KEY_COSTS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT 0 = No changes. 1 = Update secondary key costs for ranges to be at least 5x of clustered primary key costs. 2 = Remove 'max_seek optimization' for secondary keys and slight adjustment of filter cost. This option will be deleted in MariaDB 11.0 as it is not needed with the new 11.0 optimizer. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 2 +@@ -2444,7 +2444,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -2454,7 +2454,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -2464,7 +2464,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1 +@@ -2474,7 +2474,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 62 +@@ -2484,7 +2484,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Controls number of record samples to check condition selectivity + NUMERIC_MIN_VALUE 10 + NUMERIC_MAX_VALUE 4294967295 +@@ -2514,17 +2514,17 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum allowed size of an optimizer trace + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 5 +@@ -2544,7 +2544,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2554,7 +2554,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2564,7 +2564,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2574,7 +2574,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1024 +@@ -2584,7 +2584,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2594,7 +2594,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1024 +@@ -2604,7 +2604,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_LONG_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2614,7 +2614,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1024 +@@ -2624,7 +2624,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2634,7 +2634,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1024 +@@ -2644,7 +2644,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2654,7 +2654,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of condition instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2664,7 +2664,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2674,7 +2674,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1048576 +@@ -2684,7 +2684,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of file instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2694,7 +2694,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of opened instrumented files. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1048576 +@@ -2704,7 +2704,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2714,7 +2714,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_INDEX_STAT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of index statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2724,7 +2724,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MEMORY_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of memory pool instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1024 +@@ -2734,7 +2734,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_METADATA_LOCKS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of metadata locks. Use 0 to disable, -1 for automated scaling. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 104857600 +@@ -2744,7 +2744,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of mutex instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2754,7 +2754,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 104857600 +@@ -2764,7 +2764,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PREPARED_STATEMENTS_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented prepared statements. Use 0 to disable, -1 for automated scaling. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2774,7 +2774,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PROGRAM_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented programs. Use 0 to disable, -1 for automated scaling. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2784,7 +2784,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of rwlock instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2794,7 +2794,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 104857600 +@@ -2804,7 +2804,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of socket instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2814,7 +2814,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2824,7 +2824,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SQL_TEXT_LENGTH + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum length of displayed sql text. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 1048576 +@@ -2834,7 +2834,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of stage instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2844,7 +2844,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of statement instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2854,7 +2854,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_STACK + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_CURRENT. + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 256 +@@ -2864,7 +2864,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2874,7 +2874,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2884,7 +2884,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_LOCK_STAT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of lock statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2894,7 +2894,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of thread instruments. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 256 +@@ -2904,7 +2904,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2914,7 +2914,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2924,7 +2924,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1024 +@@ -2934,7 +2934,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2944,7 +2944,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT ++VARIABLE_TYPE INT + VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. + NUMERIC_MIN_VALUE -1 + NUMERIC_MAX_VALUE 1048576 +@@ -2994,7 +2994,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PRELOAD_BUFFER_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 1073741824 +@@ -3014,7 +3014,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME PROFILING_HISTORY_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 100 +@@ -3024,7 +3024,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME PROGRESS_REPORT_TIME + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -3084,7 +3084,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Allocation block size for query parsing and execution + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 4294967295 +@@ -3094,7 +3094,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME QUERY_CACHE_LIMIT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Don't cache results that are bigger than this + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -3104,7 +3104,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The minimum size for blocks allocated by the query cache + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -3117,7 +3117,7 @@ + VARIABLE_TYPE BIGINT UNSIGNED + VARIABLE_COMMENT The memory allocated to store results from old queries + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1024 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -3154,7 +3154,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME QUERY_PREALLOC_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Persistent buffer for query parsing and execution + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 4294967295 +@@ -3167,7 +3167,7 @@ + VARIABLE_TYPE BIGINT UNSIGNED + VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -3177,14 +3177,14 @@ + VARIABLE_TYPE BIGINT UNSIGNED + VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME RANGE_ALLOC_BLOCK_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Allocation block size for storing ranges during optimization + NUMERIC_MIN_VALUE 4096 + NUMERIC_MAX_VALUE 4294967295 +@@ -3197,14 +3197,14 @@ + VARIABLE_TYPE BIGINT UNSIGNED + VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME READ_BUFFER_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value + NUMERIC_MIN_VALUE 8192 + NUMERIC_MAX_VALUE 2147483647 +@@ -3224,7 +3224,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME READ_RND_BUFFER_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 2147483647 +@@ -3434,10 +3434,10 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME ROWID_MERGE_BUFF_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The size of the buffers used [NOT] IN evaluation via partial matching + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 9223372036854775807 ++NUMERIC_MAX_VALUE 2147483647 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -3454,20 +3454,20 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TIMEOUT + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The timeout value (in ms) for semi-synchronous replication in the master + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TRACE_LEVEL + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The tracing level for semi-sync replication. + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -3524,10 +3524,10 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The tracing level for semi-sync replication. + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -3564,7 +3564,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SERVER_ID + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners + NUMERIC_MIN_VALUE 1 + NUMERIC_MAX_VALUE 4294967295 +@@ -3694,7 +3694,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16383 +@@ -3724,7 +3724,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 1073741824 +@@ -3744,7 +3744,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 2147483647 +@@ -3764,7 +3764,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME SLAVE_PARALLEL_THREADS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16383 +@@ -3774,7 +3774,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_PARALLEL_WORKERS + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Alias for slave_parallel_threads + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16383 +@@ -3814,7 +3814,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME SLAVE_TRANSACTION_RETRIES + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock, elapsed lock wait timeout or listed in slave_transaction_retry_errors, before giving up and stopping + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -3834,7 +3834,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLAVE_TRANSACTION_RETRY_INTERVAL + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Interval of the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout or listed in slave_transaction_retry_errors + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 3600 +@@ -3854,7 +3854,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME SLOW_LAUNCH_TIME + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 31536000 +@@ -4124,7 +4124,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME STORED_PROGRAM_CACHE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 524288 +@@ -4224,7 +4224,7 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME TABLE_DEFINITION_CACHE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of cached table definitions + NUMERIC_MIN_VALUE 400 + NUMERIC_MAX_VALUE 2097152 +@@ -4234,7 +4234,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME TABLE_OPEN_CACHE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of cached open tables + NUMERIC_MIN_VALUE 10 + NUMERIC_MAX_VALUE 1048576 +@@ -4294,7 +4294,7 @@ + COMMAND_LINE_ARGUMENT OPTIONAL + VARIABLE_NAME THREAD_CACHE_SIZE + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16384 +@@ -4352,6 +4352,26 @@ + ENUM_VALUE_LIST NULL + READ_ONLY NO + COMMAND_LINE_ARGUMENT REQUIRED ++VARIABLE_NAME THREAD_POOL_MIN_THREADS ++VARIABLE_SCOPE GLOBAL ++VARIABLE_TYPE INT UNSIGNED ++VARIABLE_COMMENT Minimum number of threads in the thread pool. ++NUMERIC_MIN_VALUE 1 ++NUMERIC_MAX_VALUE 256 ++NUMERIC_BLOCK_SIZE 1 ++ENUM_VALUE_LIST NULL ++READ_ONLY NO ++COMMAND_LINE_ARGUMENT REQUIRED ++VARIABLE_NAME THREAD_POOL_MODE ++VARIABLE_SCOPE GLOBAL ++VARIABLE_TYPE ENUM ++VARIABLE_COMMENT Chose implementation of the threadpool ++NUMERIC_MIN_VALUE NULL ++NUMERIC_MAX_VALUE NULL ++NUMERIC_BLOCK_SIZE NULL ++ENUM_VALUE_LIST windows,generic ++READ_ONLY YES ++COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME THREAD_POOL_OVERSUBSCRIBE + VARIABLE_SCOPE GLOBAL + VARIABLE_TYPE INT UNSIGNED +@@ -4455,7 +4475,7 @@ + VARIABLE_NAME TMPDIR + VARIABLE_SCOPE GLOBAL + VARIABLE_TYPE VARCHAR +-VARIABLE_COMMENT Path for temporary files. Several paths may be specified, separated by a colon (:), in this case they are used in a round-robin fashion ++VARIABLE_COMMENT Path for temporary files. Several paths may be specified, separated by a semicolon (;), in this case they are used in a round-robin fashion + NUMERIC_MIN_VALUE NULL + NUMERIC_MAX_VALUE NULL + NUMERIC_BLOCK_SIZE NULL +@@ -4494,7 +4514,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME TRANSACTION_ALLOC_BLOCK_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 134217728 +@@ -4504,7 +4524,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME TRANSACTION_PREALLOC_SIZE + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log + NUMERIC_MIN_VALUE 1024 + NUMERIC_MAX_VALUE 134217728 +@@ -4644,10 +4664,10 @@ + COMMAND_LINE_ARGUMENT NULL + VARIABLE_NAME WAIT_TIMEOUT + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it + NUMERIC_MIN_VALUE 1 +-NUMERIC_MAX_VALUE 31536000 ++NUMERIC_MAX_VALUE 2147483 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -4671,7 +4691,7 @@ + VARIABLE_NAME LOG_TC_SIZE + GLOBAL_VALUE_ORIGIN AUTO + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Size of transaction coordinator log. + ENUM_VALUE_LIST NULL + READ_ONLY YES diff --git a/mysql-test/suite/sys_vars/t/sysvars_star.test b/mysql-test/suite/sys_vars/t/sysvars_star.test index 8d0aefdc4c7..f1d1c137109 100644 --- a/mysql-test/suite/sys_vars/t/sysvars_star.test +++ b/mysql-test/suite/sys_vars/t/sysvars_star.test @@ -15,7 +15,7 @@ set global low_priority_updates=1; install soname 'sql_errlog'; vertical_results; -replace_regex /\/.*\//var\//; +replace_regex /(C:)?\/.*\//var\//; select * from information_schema.system_variables where variable_name in ( 'completion_type', #session!=global, origin=compile-time @@ -32,7 +32,7 @@ create user foo@localhost; connect foo,localhost,foo; select global_value_path from information_schema.system_variables where variable_name='plugin_maturity'; connection default; -replace_regex /\/.*\//var\//; +replace_regex /(C:)?\/.*\//var\//; select global_value_path from information_schema.system_variables where variable_name='plugin_maturity'; disconnect foo; drop user foo@localhost; diff --git a/plugin/file_key_management/parser.cc b/plugin/file_key_management/parser.cc index 57e0139a57d..a7b39f0ad16 100644 --- a/plugin/file_key_management/parser.cc +++ b/plugin/file_key_management/parser.cc @@ -260,7 +260,7 @@ int Parser::parse_line(char **line_ptr, keyentry *key) while (isdigit(*p)) { id = id * 10 + *p - '0'; - if (id > UINT_MAX32) + if (id > (longlong) UINT_MAX32) { report_error("Invalid key id", p - *line_ptr); return -1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3ce6f433999..ae855525060 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3224,7 +3224,7 @@ String *Item_func_binlog_gtid_pos::val_str(String *str) if (args[0]->null_value || args[1]->null_value) goto err; - if (pos < 0 || pos > UINT_MAX32) + if (pos < 0 || pos > (longlong) UINT_MAX32) goto err; if (gtid_state_from_binlog_pos(name->c_ptr_safe(), (uint32)pos, str)) diff --git a/sql/log.cc b/sql/log.cc index 401ce408c5f..a6342a15ddb 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6129,12 +6129,13 @@ bool THD::binlog_write_table_map(TABLE *table, bool with_annotate) int error= 1; bool is_transactional= table->file->row_logging_has_trans; DBUG_ENTER("THD::binlog_write_table_map"); - DBUG_PRINT("enter", ("table: %p (%s: #%lu)", + DBUG_PRINT("enter", ("table: %p (%s: #%llu)", table, table->s->table_name.str, table->s->table_map_id)); /* Pre-conditions */ - DBUG_ASSERT(table->s->table_map_id != ULONG_MAX); + DBUG_ASSERT((table->s->table_map_id & MAX_TABLE_MAP_ID) != UINT32_MAX && + (table->s->table_map_id & MAX_TABLE_MAP_ID) != 0); /* Ensure that all events in a GTID group are in the same cache */ if (variables.option_bits & OPTION_GTID_BEGIN) diff --git a/sql/log_event.cc b/sql/log_event.cc index c5d58c04054..2acb77a2dc5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3311,7 +3311,7 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len, } else { - m_table_id= (ulong) uint6korr(post_start); + m_table_id= (ulonglong) uint6korr(post_start); post_start+= RW_FLAGS_OFFSET; } @@ -3668,11 +3668,12 @@ Table_map_log_event::Table_map_log_event(const uchar *buf, uint event_len, else { DBUG_ASSERT(post_header_len == TABLE_MAP_HEADER_LEN); - m_table_id= (ulong) uint6korr(post_start); + m_table_id= (ulonglong) uint6korr(post_start); post_start+= TM_FLAGS_OFFSET; } - DBUG_ASSERT(m_table_id != ~0ULL); + DBUG_ASSERT((m_table_id & MAX_TABLE_MAP_ID) != UINT32_MAX && + (m_table_id & MAX_TABLE_MAP_ID) != 0); m_flags= uint2korr(post_start); diff --git a/sql/log_event.h b/sql/log_event.h index a85dcf9d782..8be46ed30cb 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -158,6 +158,12 @@ class String; #define NUM_LOAD_DELIM_STRS 5 +/* + The following is the max table_map_id. This is limited by that we + are using 6 bytes for it in replication +*/ +#define MAX_TABLE_MAP_ID ((1ULL << (6*8)) -1) + /***************************************************************************** MySQL Binary Log @@ -4796,7 +4802,8 @@ public: flag_set get_flags(flag_set flag) const { return m_flags & flag; } #ifdef MYSQL_SERVER - Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, bool is_transactional); + Table_map_log_event(THD *thd, TABLE *tbl, ulonglong tid, + bool is_transactional); #endif #ifdef HAVE_REPLICATION Table_map_log_event(const uchar *buf, uint event_len, @@ -5122,7 +5129,7 @@ protected: this class, not create instances of this class. */ #ifdef MYSQL_SERVER - Rows_log_event(THD*, TABLE*, ulong table_id, + Rows_log_event(THD*, TABLE*, ulonglong table_id, MY_BITMAP const *cols, bool is_transactional, Log_event_type event_type); #endif @@ -5356,7 +5363,7 @@ public: }; #if defined(MYSQL_SERVER) - Write_rows_log_event(THD*, TABLE*, ulong table_id, + Write_rows_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); #endif #ifdef HAVE_REPLICATION @@ -5397,7 +5404,7 @@ class Write_rows_compressed_log_event : public Write_rows_log_event { public: #if defined(MYSQL_SERVER) - Write_rows_compressed_log_event(THD*, TABLE*, ulong table_id, + Write_rows_compressed_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); virtual bool write(); #endif @@ -5433,7 +5440,7 @@ public: }; #ifdef MYSQL_SERVER - Update_rows_log_event(THD*, TABLE*, ulong table_id, + Update_rows_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); void init(MY_BITMAP const *cols); @@ -5485,7 +5492,7 @@ class Update_rows_compressed_log_event : public Update_rows_log_event { public: #if defined(MYSQL_SERVER) - Update_rows_compressed_log_event(THD*, TABLE*, ulong table_id, + Update_rows_compressed_log_event(THD*, TABLE*, ulonglong table_id, bool is_transactional); virtual bool write(); #endif @@ -5529,7 +5536,7 @@ public: }; #ifdef MYSQL_SERVER - Delete_rows_log_event(THD*, TABLE*, ulong, bool is_transactional); + Delete_rows_log_event(THD*, TABLE*, ulonglong, bool is_transactional); #endif #ifdef HAVE_REPLICATION Delete_rows_log_event(const uchar *buf, uint event_len, @@ -5570,7 +5577,8 @@ class Delete_rows_compressed_log_event : public Delete_rows_log_event { public: #if defined(MYSQL_SERVER) - Delete_rows_compressed_log_event(THD*, TABLE*, ulong, bool is_transactional); + Delete_rows_compressed_log_event(THD*, TABLE*, ulonglong, + bool is_transactional); virtual bool write(); #endif #ifdef HAVE_REPLICATION diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index cbb593d0888..3b7df6e0f66 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -1502,8 +1502,8 @@ bool Rows_log_event::print_verbose(IO_CACHE *file, if (!(map= print_event_info->m_table_map.get_table(m_table_id)) || !(td= map->create_table_def())) { - return (my_b_printf(file, "### Row event for unknown table #%lu", - (ulong) m_table_id)); + return (my_b_printf(file, "### Row event for unknown table #%llu", + (ulonglong) m_table_id)); } /* If the write rows event contained no values for the AI */ diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 4e6b9e3f1c8..b7325225b0a 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -47,12 +47,12 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, rpl_group_info *rgi) const Relay_log_info *rli= rgi->rli; /* - If m_table_id == ~0UL, then we have a dummy event that does not + If m_table_id == UINT32_MAX, then we have a dummy event that does not contain any data. In that case, we just remove all tables in the tables_to_lock list, close the thread tables, and return with success. */ - if (ev->m_table_id == ~0UL) + if (ev->m_table_id == UINT32_MAX) { /* This one is supposed to be set: just an extra check so that @@ -1123,13 +1123,14 @@ int Update_rows_log_event_old::do_exec_row(TABLE *table) **************************************************************************/ #ifndef MYSQL_CLIENT -Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, +Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, + ulonglong table_id, MY_BITMAP const *cols, bool is_transactional) : Log_event(thd_arg, 0, is_transactional), m_row_count(0), m_table(tbl_arg), - m_table_id(tid), + m_table_id(table_id), m_width(tbl_arg ? tbl_arg->s->fields : 1), m_rows_buf(0), m_rows_cur(0), m_rows_end(0), m_flags(0) #ifdef HAVE_REPLICATION @@ -1142,12 +1143,12 @@ Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, /* We allow a special form of dummy event when the table, and cols - are null and the table id is ~0UL. This is a temporary + are null and the table id is UINT32_MAX. This is a temporary solution, to be able to terminate a started statement in the binary log: the extraneous events will be removed in the future. */ - DBUG_ASSERT((tbl_arg && tbl_arg->s && tid != ~0UL) || - (!tbl_arg && !cols && tid == ~0UL)); + DBUG_ASSERT((tbl_arg && tbl_arg->s && table_id != UINT32_MAX) || + (!tbl_arg && !cols && table_id == UINT32_MAX)); if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS) set_flags(NO_FOREIGN_KEY_CHECKS_F); @@ -1209,7 +1210,7 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, } else { - m_table_id= (ulong) uint6korr(post_start); + m_table_id= (ulonglong) uint6korr(post_start); post_start+= RW_FLAGS_OFFSET; } @@ -1364,12 +1365,12 @@ int Old_rows_log_event::do_apply_event(rpl_group_info *rgi) Relay_log_info const *rli= rgi->rli; /* - If m_table_id == ~0UL, then we have a dummy event that does not + If m_table_id == UINT32_MAX, then we have a dummy event that does not contain any data. In that case, we just remove all tables in the tables_to_lock list, close the thread tables, and return with success. */ - if (m_table_id == ~0UL) + if (m_table_id == UINT32_MAX) { /* This one is supposed to be set: just an extra check so that @@ -1786,7 +1787,7 @@ bool Old_rows_log_event::write_data_header() // This method should not be reached. assert(0); - DBUG_ASSERT(m_table_id != ~0UL); + DBUG_ASSERT(m_table_id != UINT32_MAX); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { int4store(buf + 0, m_table_id); @@ -2400,7 +2401,7 @@ int Old_rows_log_event::find_row(rpl_group_info *rgi) #if !defined(MYSQL_CLIENT) Write_rows_log_event_old::Write_rows_log_event_old(THD *thd_arg, TABLE *tbl_arg, - ulong tid_arg, + ulonglong tid_arg, MY_BITMAP const *cols, bool is_transactional) : Old_rows_log_event(thd_arg, tbl_arg, tid_arg, cols, is_transactional) @@ -2512,7 +2513,7 @@ bool Write_rows_log_event_old::print(FILE *file, #ifndef MYSQL_CLIENT Delete_rows_log_event_old::Delete_rows_log_event_old(THD *thd_arg, TABLE *tbl_arg, - ulong tid, + ulonglong tid, MY_BITMAP const *cols, bool is_transactional) : Old_rows_log_event(thd_arg, tbl_arg, tid, cols, is_transactional), @@ -2620,7 +2621,7 @@ bool Delete_rows_log_event_old::print(FILE *file, #if !defined(MYSQL_CLIENT) Update_rows_log_event_old::Update_rows_log_event_old(THD *thd_arg, TABLE *tbl_arg, - ulong tid, + ulonglong tid, MY_BITMAP const *cols, bool is_transactional) : Old_rows_log_event(thd_arg, tbl_arg, tid, cols, is_transactional), diff --git a/sql/log_event_old.h b/sql/log_event_old.h index e5aaacec209..1afe9aba60c 100644 --- a/sql/log_event_old.h +++ b/sql/log_event_old.h @@ -131,7 +131,7 @@ public: MY_BITMAP const *get_cols() const { return &m_cols; } size_t get_width() const { return m_width; } - ulong get_table_id() const { return m_table_id; } + ulonglong get_table_id() const { return m_table_id; } #ifndef MYSQL_CLIENT virtual bool write_data_header(); @@ -158,7 +158,7 @@ protected: this class, not create instances of this class. */ #ifndef MYSQL_CLIENT - Old_rows_log_event(THD*, TABLE*, ulong table_id, + Old_rows_log_event(THD*, TABLE*, ulonglong table_id, MY_BITMAP const *cols, bool is_transactional); #endif Old_rows_log_event(const uchar *row_data, uint event_len, @@ -176,7 +176,7 @@ protected: #ifndef MYSQL_CLIENT TABLE *m_table; /* The table the rows belong to */ #endif - ulong m_table_id; /* Table ID */ + ulonglong m_table_id; /* Table ID */ MY_BITMAP m_cols; /* Bitmap denoting columns available */ ulong m_width; /* The width of the columns bitmap */ @@ -359,7 +359,7 @@ class Write_rows_log_event_old : public Old_rows_log_event /********** BEGIN CUT & PASTE FROM Write_rows_log_event **********/ public: #if !defined(MYSQL_CLIENT) - Write_rows_log_event_old(THD*, TABLE*, ulong table_id, + Write_rows_log_event_old(THD*, TABLE*, ulonglong table_id, MY_BITMAP const *cols, bool is_transactional); #endif #ifdef HAVE_REPLICATION @@ -430,7 +430,7 @@ class Update_rows_log_event_old : public Old_rows_log_event /********** BEGIN CUT & PASTE FROM Update_rows_log_event **********/ public: #ifndef MYSQL_CLIENT - Update_rows_log_event_old(THD*, TABLE*, ulong table_id, + Update_rows_log_event_old(THD*, TABLE*, ulonglong table_id, MY_BITMAP const *cols, bool is_transactional); #endif @@ -507,7 +507,7 @@ class Delete_rows_log_event_old : public Old_rows_log_event /********** BEGIN CUT & PASTE FROM Update_rows_log_event **********/ public: #ifndef MYSQL_CLIENT - Delete_rows_log_event_old(THD*, TABLE*, ulong, + Delete_rows_log_event_old(THD*, TABLE*, ulonglong, MY_BITMAP const *cols, bool is_transactional); #endif #ifdef HAVE_REPLICATION diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 976a657b635..3e7fcc9df85 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5254,13 +5254,14 @@ bool sql_ex_info::write_data(Log_event_writer *writer) Rows_log_event member functions **************************************************************************/ -Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, +Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, + ulonglong table_id, MY_BITMAP const *cols, bool is_transactional, Log_event_type event_type) : Log_event(thd_arg, 0, is_transactional), m_row_count(0), m_table(tbl_arg), - m_table_id(tid), + m_table_id(table_id), m_width(tbl_arg ? tbl_arg->s->fields : 1), m_rows_buf(0), m_rows_cur(0), m_rows_end(0), m_flags(0), m_type(event_type), m_extra_row_data(0) @@ -5272,12 +5273,13 @@ Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, { /* We allow a special form of dummy event when the table, and cols - are null and the table id is ~0UL. This is a temporary + are null and the table id is UINT32_MAX. This is a temporary solution, to be able to terminate a started statement in the binary log: the extraneous events will be removed in the future. */ - DBUG_ASSERT((tbl_arg && tbl_arg->s && tid != ~0UL) || - (!tbl_arg && !cols && tid == ~0UL)); + DBUG_ASSERT((tbl_arg && tbl_arg->s && + (table_id & MAX_TABLE_MAP_ID) != UINT32_MAX) || + (!tbl_arg && !cols && (table_id & MAX_TABLE_MAP_ID) == UINT32_MAX)); if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS) set_flags(NO_FOREIGN_KEY_CHECKS_F); @@ -5425,12 +5427,12 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) LEX *lex= thd->lex; uint8 new_trg_event_map= get_trg_event_map(); /* - If m_table_id == ~0ULL, then we have a dummy event that does not + If m_table_id == UINT32_MAX, then we have a dummy event that does not contain any data. In that case, we just remove all tables in the tables_to_lock list, close the thread tables, and return with success. */ - if (m_table_id == ~0ULL) + if (m_table_id == UINT32_MAX) { /* This one is supposed to be set: just an extra check so that @@ -6069,7 +6071,7 @@ Rows_log_event::do_update_pos(rpl_group_info *rgi) bool Rows_log_event::write_data_header() { uchar buf[ROWS_HEADER_LEN_V2]; // No need to init the buffer - DBUG_ASSERT(m_table_id != ~0ULL); + DBUG_ASSERT(m_table_id != UINT32_MAX); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { int4store(buf + 0, m_table_id); @@ -6277,7 +6279,7 @@ int Table_map_log_event::save_field_metadata() Mats says tbl->s lives longer than this event so it's ok to copy pointers (tbl->s->db etc) and not pointer content. */ -Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, +Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulonglong tid, bool is_transactional) : Log_event(thd, 0, is_transactional), m_table(tbl), @@ -6300,7 +6302,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, uchar cbuf[MAX_INT_WIDTH]; uchar *cbuf_end; DBUG_ENTER("Table_map_log_event::Table_map_log_event(TABLE)"); - DBUG_ASSERT(m_table_id != ~0ULL); + DBUG_ASSERT(m_table_id != UINT32_MAX); /* In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in table.cc / alloc_table_share(): @@ -6627,7 +6629,7 @@ int Table_map_log_event::do_update_pos(rpl_group_info *rgi) bool Table_map_log_event::write_data_header() { - DBUG_ASSERT(m_table_id != ~0ULL); + DBUG_ASSERT(m_table_id != UINT32_MAX); uchar buf[TABLE_MAP_HEADER_LEN]; DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { @@ -7082,7 +7084,7 @@ void Table_map_log_event::pack_info(Protocol *protocol) Constructor used to build an event for writing to the binary log. */ Write_rows_log_event::Write_rows_log_event(THD *thd_arg, TABLE *tbl_arg, - ulong tid_arg, + ulonglong tid_arg, bool is_transactional) :Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->rpl_write_set, is_transactional, WRITE_ROWS_EVENT_V1) @@ -7092,7 +7094,7 @@ Write_rows_log_event::Write_rows_log_event(THD *thd_arg, TABLE *tbl_arg, Write_rows_compressed_log_event::Write_rows_compressed_log_event( THD *thd_arg, TABLE *tbl_arg, - ulong tid_arg, + ulonglong tid_arg, bool is_transactional) : Write_rows_log_event(thd_arg, tbl_arg, tid_arg, is_transactional) { @@ -8216,7 +8218,8 @@ end: */ Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg, - ulong tid, bool is_transactional) + ulonglong tid, + bool is_transactional) : Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional, DELETE_ROWS_EVENT_V1) { @@ -8224,7 +8227,7 @@ Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg, Delete_rows_compressed_log_event::Delete_rows_compressed_log_event( THD *thd_arg, TABLE *tbl_arg, - ulong tid_arg, + ulonglong tid_arg, bool is_transactional) : Delete_rows_log_event(thd_arg, tbl_arg, tid_arg, is_transactional) { @@ -8365,7 +8368,7 @@ uint8 Delete_rows_log_event::get_trg_event_map() Constructor used to build an event for writing to the binary log. */ Update_rows_log_event::Update_rows_log_event(THD *thd_arg, TABLE *tbl_arg, - ulong tid, + ulonglong tid, bool is_transactional) : Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional, UPDATE_ROWS_EVENT_V1) @@ -8373,9 +8376,9 @@ Update_rows_log_event::Update_rows_log_event(THD *thd_arg, TABLE *tbl_arg, init(tbl_arg->rpl_write_set); } -Update_rows_compressed_log_event::Update_rows_compressed_log_event(THD *thd_arg, TABLE *tbl_arg, - ulong tid, - bool is_transactional) +Update_rows_compressed_log_event:: +Update_rows_compressed_log_event(THD *thd_arg, TABLE *tbl_arg, + ulonglong tid, bool is_transactional) : Update_rows_log_event(thd_arg, tbl_arg, tid, is_transactional) { m_type = UPDATE_ROWS_COMPRESSED_EVENT_V1; diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 4c853689504..93b0dbb3ac7 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -953,7 +953,8 @@ void field_longlong::get_opt_type(String *answer, UINT_MAX24 : INT_MAX24)) snprintf(buff, sizeof(buff), "MEDIUMINT(%d)", (int) max_length); else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ? - UINT_MAX32 : INT_MAX32)) + (longlong) UINT_MAX32 : + (longlong) INT_MAX32)) snprintf(buff, sizeof(buff), "INT(%d)", (int) max_length); else snprintf(buff, sizeof(buff), "BIGINT(%d)", (int) max_length); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index fdf84ef8a99..da98be9bf2f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -7005,7 +7005,8 @@ THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, { DBUG_ENTER("binlog_prepare_pending_rows_event"); /* Pre-conditions */ - DBUG_ASSERT(table->s->table_map_id != ~0UL); + DBUG_ASSERT((table->s->table_map_id & MAX_TABLE_MAP_ID) != UINT32_MAX && + (table->s->table_map_id & MAX_TABLE_MAP_ID) != 0); /* Fetch the type code for the RowsEventT template parameter */ int const general_type_code= RowsEventT::TYPE_CODE; diff --git a/sql/table.cc b/sql/table.cc index 836495992c3..0d4404008ea 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -48,6 +48,7 @@ #ifdef WITH_WSREP #include "wsrep_schema.h" #endif +#include "log_event.h" // MAX_TABLE_MAP_ID /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -107,7 +108,7 @@ LEX_CSTRING MYSQL_PROC_NAME= {STRING_WITH_LEN("proc")}; */ static LEX_CSTRING parse_vcol_keyword= { STRING_WITH_LEN("PARSE_VCOL_EXPR ") }; -static std::atomic last_table_id; +static std::atomic last_table_id; /* Functions defined in this file */ @@ -383,17 +384,20 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, DBUG_EXECUTE_IF("simulate_big_table_id", if (last_table_id < UINT_MAX32) - last_table_id= UINT_MAX32 - 1;); + last_table_id= UINT_MAX32-1;); /* - There is one reserved number that cannot be used. Remember to - change this when 6-byte global table id's are introduced. + Replication is using 6 bytes as table_map_id. Ensure that + the 6 lowest bytes are not 0. + We also have to ensure that we do not use the special value + UINT_MAX32 as this is used to mark a dummy event row event. See + comments in Rows_log_event::Rows_log_event(). */ do { share->table_map_id= last_table_id.fetch_add(1, std::memory_order_relaxed); - } while (unlikely(share->table_map_id == ~0UL || - share->table_map_id == 0)); + } while (unlikely((share->table_map_id & MAX_TABLE_MAP_ID) == 0) || + unlikely((share->table_map_id & MAX_TABLE_MAP_ID) == UINT_MAX32)); } DBUG_RETURN(share); } @@ -456,7 +460,7 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key, table_map_id is also used for MERGE tables to suppress repeated compatibility checks. */ - share->table_map_id= (ulong) thd->query_id; + share->table_map_id= (ulonglong) thd->query_id; DBUG_VOID_RETURN; } diff --git a/sql/table.h b/sql/table.h index fb2b1167833..e061d1eb669 100644 --- a/sql/table.h +++ b/sql/table.h @@ -851,7 +851,7 @@ struct TABLE_SHARE /* 1 if frm version cannot be updated as part of upgrade */ bool keep_original_mysql_version; - ulong table_map_id; /* for row-based replication */ + ulonglong table_map_id; /* for row-based replication */ /* Things that are incompatible between the stored version and the @@ -1006,7 +1006,7 @@ struct TABLE_SHARE return (table_category == TABLE_CATEGORY_LOG); } - inline ulong get_table_def_version() + inline ulonglong get_table_def_version() { return table_map_id; } @@ -1085,7 +1085,7 @@ struct TABLE_SHARE @sa TABLE_LIST::is_the_same_definition() */ - ulong get_table_ref_version() const + ulonglong get_table_ref_version() const { return (tmp_table == SYSTEM_TMP_TABLE) ? 0 : table_map_id; } @@ -2774,7 +2774,7 @@ struct TABLE_LIST { set_table_ref_id(s->get_table_ref_type(), s->get_table_ref_version()); } inline void set_table_ref_id(enum_table_ref_type table_ref_type_arg, - ulong table_ref_version_arg) + ulonglong table_ref_version_arg) { m_table_ref_type= table_ref_type_arg; m_table_ref_version= table_ref_version_arg; @@ -2929,7 +2929,7 @@ private: /** See comments for set_table_ref_id() */ enum enum_table_ref_type m_table_ref_type; /** See comments for set_table_ref_id() */ - ulong m_table_ref_version; + ulonglong m_table_ref_version; }; class Item; diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h index 6da327ec84b..9964add9201 100644 --- a/storage/myisammrg/ha_myisammrg.h +++ b/storage/myisammrg/ha_myisammrg.h @@ -34,7 +34,7 @@ class Mrg_child_def: public Sql_alloc { /* Remembered MERGE child def version. See top comment in ha_myisammrg.cc */ enum_table_ref_type m_child_table_ref_type; - ulong m_child_def_version; + ulonglong m_child_def_version; public: LEX_STRING db; LEX_STRING name; @@ -44,12 +44,12 @@ public: { return m_child_table_ref_type; } - inline ulong get_child_def_version() + inline ulonglong get_child_def_version() { return m_child_def_version; } inline void set_child_def_version(enum_table_ref_type child_table_ref_type, - ulong version) + ulonglong version) { m_child_table_ref_type= child_table_ref_type; m_child_def_version= version; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test index 281d2adce64..de2ab789a28 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32753_after_start.test @@ -4,6 +4,7 @@ # This test tests spider init after startup under global ORACLE mode install soname 'ha_spider'; +--replace_regex /\.dll/.so/ select * from mysql.plugin; create table t (c int) Engine=SPIDER; drop table t; diff --git a/storage/spider/mysql-test/spider/include/clean_up_spider.inc b/storage/spider/mysql-test/spider/include/clean_up_spider.inc index 249606ec774..1c977bfb66f 100644 --- a/storage/spider/mysql-test/spider/include/clean_up_spider.inc +++ b/storage/spider/mysql-test/spider/include/clean_up_spider.inc @@ -3,6 +3,7 @@ DROP FUNCTION spider_copy_tables; DROP FUNCTION spider_ping_table; DROP FUNCTION spider_bg_direct_sql; DROP FUNCTION spider_direct_sql; +--replace_regex /\.dll/.so/ UNINSTALL SONAME IF EXISTS 'ha_spider'; DROP TABLE IF EXISTS mysql.spider_xa; DROP TABLE IF EXISTS mysql.spider_xa_member; From 8c5db7a1872c5644a14bbaddadee277d0b354c23 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 12 Jan 2024 17:34:19 +0100 Subject: [PATCH 088/121] MDEV-29587 Allowing insert into a view with columns that are not part the table We can check only fields which take part in inserts. --- mysql-test/main/view.result | 46 ++++++++++++++++ mysql-test/main/view.test | 53 +++++++++++++++++++ .../suite/funcs_1/r/innodb_views.result | 2 +- .../suite/funcs_1/r/memory_views.result | 2 +- .../suite/funcs_1/r/myisam_views-big.result | 2 +- .../suite/funcs_1/views/views_master.inc | 1 - sql/sql_insert.cc | 29 +++++++--- 7 files changed, 125 insertions(+), 10 deletions(-) diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index a962776a4dc..9cab1b5f7f8 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -7029,3 +7029,49 @@ DROP TABLE t1, t2; # # End of 10.6 tests # +# +# MDEV-29587: Allowing insert into a view with columns that +# are not part the table +# +# view with 2 the same fields +CREATE TABLE table1 (x INT); +CREATE VIEW view1 AS SELECT x, x as x1 FROM table1; +INSERT INTO view1(x) VALUES (1); +INSERT INTO view1(x1) VALUES (1); +INSERT INTO view1(x1,x) VALUES (1,1); +ERROR HY000: The target table view1 of the INSERT is not insertable-into +DROP VIEW view1; +DROP TABLE table1; +# view with a field and expression over the field +CREATE TABLE table1 (x INT); +CREATE VIEW view1 AS SELECT x, x + 1 as x1 FROM table1; +INSERT INTO view1(x) VALUES (1); +INSERT INTO view1(x1) VALUES (1); +ERROR HY000: The target table view1 of the INSERT is not insertable-into +INSERT INTO view1(x1,x) VALUES (1,1); +ERROR HY000: The target table view1 of the INSERT is not insertable-into +DROP VIEW view1; +DROP TABLE table1; +# view with a field and collation expression over the field +CREATE TABLE table1 (x char(20)); +CREATE VIEW view1 AS SELECT x, x collate latin1_german1_ci as x1 FROM table1; +INSERT INTO view1(x) VALUES ("ua"); +# we can insert in the field with collation +INSERT INTO view1(x1) VALUES ("ua"); +INSERT INTO view1(x1,x) VALUES ("ua","ua"); +ERROR HY000: The target table view1 of the INSERT is not insertable-into +DROP VIEW view1; +DROP TABLE table1; +# view with a field and expression over other field +CREATE TABLE table1 (x INT, y INT); +CREATE VIEW view1 AS SELECT x, y + 1 as x1 FROM table1; +INSERT INTO view1(x) VALUES (1); +INSERT INTO view1(x1) VALUES (1); +ERROR HY000: The target table view1 of the INSERT is not insertable-into +INSERT INTO view1(x1,x) VALUES (1,1); +ERROR HY000: The target table view1 of the INSERT is not insertable-into +DROP VIEW view1; +DROP TABLE table1; +# +# End of 10.11 test +# diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test index a4fe17a86f7..4c2d71d4906 100644 --- a/mysql-test/main/view.test +++ b/mysql-test/main/view.test @@ -6792,3 +6792,56 @@ DROP TABLE t1, t2; --echo # --echo # End of 10.6 tests --echo # + + +--echo # +--echo # MDEV-29587: Allowing insert into a view with columns that +--echo # are not part the table +--echo # + +--echo # view with 2 the same fields +CREATE TABLE table1 (x INT); +CREATE VIEW view1 AS SELECT x, x as x1 FROM table1; +INSERT INTO view1(x) VALUES (1); +INSERT INTO view1(x1) VALUES (1); +--error ER_NON_INSERTABLE_TABLE +INSERT INTO view1(x1,x) VALUES (1,1); +DROP VIEW view1; +DROP TABLE table1; + +--echo # view with a field and expression over the field +CREATE TABLE table1 (x INT); +CREATE VIEW view1 AS SELECT x, x + 1 as x1 FROM table1; +INSERT INTO view1(x) VALUES (1); +--error ER_NON_INSERTABLE_TABLE +INSERT INTO view1(x1) VALUES (1); +--error ER_NON_INSERTABLE_TABLE +INSERT INTO view1(x1,x) VALUES (1,1); +DROP VIEW view1; +DROP TABLE table1; + +--echo # view with a field and collation expression over the field +CREATE TABLE table1 (x char(20)); +CREATE VIEW view1 AS SELECT x, x collate latin1_german1_ci as x1 FROM table1; +INSERT INTO view1(x) VALUES ("ua"); +--echo # we can insert in the field with collation +INSERT INTO view1(x1) VALUES ("ua"); +--error ER_NON_INSERTABLE_TABLE +INSERT INTO view1(x1,x) VALUES ("ua","ua"); +DROP VIEW view1; +DROP TABLE table1; + +--echo # view with a field and expression over other field +CREATE TABLE table1 (x INT, y INT); +CREATE VIEW view1 AS SELECT x, y + 1 as x1 FROM table1; +INSERT INTO view1(x) VALUES (1); +--error ER_NON_INSERTABLE_TABLE +INSERT INTO view1(x1) VALUES (1); +--error ER_NON_INSERTABLE_TABLE +INSERT INTO view1(x1,x) VALUES (1,1); +DROP VIEW view1; +DROP TABLE table1; + +--echo # +--echo # End of 10.11 test +--echo # diff --git a/mysql-test/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result index 90d72b451b9..5bd48cf9706 100644 --- a/mysql-test/suite/funcs_1/r/innodb_views.result +++ b/mysql-test/suite/funcs_1/r/innodb_views.result @@ -22145,9 +22145,9 @@ DELETE FROM t1; DROP VIEW v1; CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1; INSERT INTO v1 SET f1 = 1; -ERROR HY000: The target table v1 of the INSERT is not insertable-into SELECT * from t1; f1 f2 f3 f4 +1 NULL NULL NULL DELETE FROM t1; INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO'; ERROR HY000: The target table v1 of the INSERT is not insertable-into diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result index 417c0e85188..8ce1e1c7cba 100644 --- a/mysql-test/suite/funcs_1/r/memory_views.result +++ b/mysql-test/suite/funcs_1/r/memory_views.result @@ -22147,9 +22147,9 @@ DELETE FROM t1; DROP VIEW v1; CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1; INSERT INTO v1 SET f1 = 1; -ERROR HY000: The target table v1 of the INSERT is not insertable-into SELECT * from t1; f1 f2 f3 f4 +1 NULL NULL NULL DELETE FROM t1; INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO'; ERROR HY000: The target table v1 of the INSERT is not insertable-into diff --git a/mysql-test/suite/funcs_1/r/myisam_views-big.result b/mysql-test/suite/funcs_1/r/myisam_views-big.result index efd5ee1c568..984ae74fc8b 100644 --- a/mysql-test/suite/funcs_1/r/myisam_views-big.result +++ b/mysql-test/suite/funcs_1/r/myisam_views-big.result @@ -23849,9 +23849,9 @@ DELETE FROM t1; DROP VIEW v1; CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1; INSERT INTO v1 SET f1 = 1; -ERROR HY000: The target table v1 of the INSERT is not insertable-into SELECT * from t1; f1 f2 f3 f4 +1 NULL NULL NULL DELETE FROM t1; INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO'; ERROR HY000: The target table v1 of the INSERT is not insertable-into diff --git a/mysql-test/suite/funcs_1/views/views_master.inc b/mysql-test/suite/funcs_1/views/views_master.inc index 526e9e3426e..a9203529f21 100644 --- a/mysql-test/suite/funcs_1/views/views_master.inc +++ b/mysql-test/suite/funcs_1/views/views_master.inc @@ -3479,7 +3479,6 @@ CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1; # Maybe the SQL standard allows the following INSERT. # But it would be a very sophisticated DBMS. ---error ER_NON_INSERTABLE_TABLE INSERT INTO v1 SET f1 = 1; SELECT * from t1; DELETE FROM t1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7c72d979e75..345f174def2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -96,7 +96,8 @@ static void end_delayed_insert(THD *thd); pthread_handler_t handle_delayed_insert(void *arg); static void unlink_blobs(TABLE *table); #endif -static bool check_view_insertability(THD *thd, TABLE_LIST *view); +static bool check_view_insertability(THD *thd, TABLE_LIST *view, + List &fields); static int binlog_show_create_table_(THD *thd, TABLE *table, Table_specification_st *create_info); @@ -311,7 +312,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (check_key_in_view(thd, table_list) || (table_list->view && - check_view_insertability(thd, table_list))) + check_view_insertability(thd, table_list, fields))) { my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias.str, "INSERT"); DBUG_RETURN(-1); @@ -1426,6 +1427,7 @@ abort: check_view_insertability() thd - thread handler view - reference on VIEW + fields - fields used in insert IMPLEMENTATION A view is insertable if the folloings are true: @@ -1441,7 +1443,8 @@ abort: TRUE - can't be used for insert */ -static bool check_view_insertability(THD * thd, TABLE_LIST *view) +static bool check_view_insertability(THD *thd, TABLE_LIST *view, + List &fields) { uint num= view->view->first_select_lex()->item_list.elements; TABLE *table= view->table; @@ -1452,6 +1455,8 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size); MY_BITMAP used_fields; enum_column_usage saved_column_usage= thd->column_usage; + List_iterator_fast it(fields); + Item *ex; DBUG_ENTER("check_key_in_view"); if (!used_fields_buff) @@ -1480,6 +1485,17 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) /* simple SELECT list entry (field without expression) */ if (!(field= trans->item->field_for_view_update())) { + // Do not check fields which we are not inserting into + while((ex= it++)) + { + // The field used in the INSERT + if (ex->real_item()->field_for_view_update() == + trans->item->field_for_view_update()) + break; + } + it.rewind(); + if (!ex) + continue; thd->column_usage= saved_column_usage; DBUG_RETURN(TRUE); } @@ -1494,11 +1510,12 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) } thd->column_usage= saved_column_usage; /* unique test */ - for (trans= trans_start; trans != trans_end; trans++) + while((ex= it++)) { /* Thanks to test above, we know that all columns are of type Item_field */ - Item_field *field= (Item_field *)trans->item; - /* check fields belong to table in which we are inserting */ + DBUG_ASSERT(ex->real_item()->field_for_view_update()->type() == + Item::FIELD_ITEM); + Item_field *field= (Item_field *)ex->real_item()->field_for_view_update(); if (field->field->table == table && bitmap_fast_test_and_set(&used_fields, field->field->field_index)) DBUG_RETURN(TRUE); From 27459b413deb1e21c2e9686e36ab44788a132b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 23 Jan 2024 16:24:27 +0200 Subject: [PATCH 089/121] MDEV-14448: Ctrl-C should not exit client Undo any Windows behaviour changes. --- client/mysql.cc | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index befa0e9b113..fe086f29dac 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -89,7 +89,6 @@ extern "C" { #undef bcmp // Fix problem with new readline #if defined(__WIN__) #include -#include #else # ifdef __APPLE__ # include @@ -1079,29 +1078,6 @@ static sig_handler window_resize(int sig); static void end_in_sig_handler(int sig); static bool kill_query(const char *reason); -#ifdef _WIN32 -static BOOL WINAPI ctrl_handler_windows(DWORD fdwCtrlType) -{ - switch (fdwCtrlType) - { - // Handle the CTRL-C signal. - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - handle_sigint(SIGINT); - return TRUE; // this means that the signal is handled - case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - kill_query("Terminate"); - end_in_sig_handler(SIGINT + 1); - aborted= 1; - } - // This means to pass the signal to the next handler. This allows - // my_cgets and the internal ReadConsole call to exit and gracefully - // abort the program. - return FALSE; -} -#endif const char DELIMITER_NAME[]= "delimiter"; const uint DELIMITER_NAME_LEN= sizeof(DELIMITER_NAME) - 1; inline bool is_delimiter_command(char *name, ulong len) @@ -1234,12 +1210,11 @@ int main(int argc,char *argv[]) if (!status.batch) ignore_errors=1; // Don't abort monitor -#ifndef _WIN32 - signal(SIGINT, handle_sigint); // Catch SIGINT to clean up + if (opt_sigint_ignore) + signal(SIGINT, SIG_IGN); + else + signal(SIGINT, handle_sigint); // Catch SIGINT to clean up signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up -#else - SetConsoleCtrlHandler(ctrl_handler_windows, TRUE); -#endif #if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL) /* Readline will call this if it installs a handler */ @@ -1471,9 +1446,6 @@ bool kill_query(const char *reason) */ sig_handler handle_sigint(int sig) { - if (opt_sigint_ignore) - return; - /* On Unix only, if no query is being executed just clear the prompt, don't exit. On Windows we exit. From 2bc940f7c940d792ef71058ed0c44660820bed8c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 20 Jan 2024 11:01:46 +0100 Subject: [PATCH 090/121] disable perfschema in mtr bootstrap should fix numerous failures of main.bootstrap tets --- mysql-test/mysql-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 789d97278fc..f75f0fe64df 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3076,6 +3076,7 @@ sub mysql_install_db { mtr_add_arg($args, "--core-file"); mtr_add_arg($args, "--console"); mtr_add_arg($args, "--character-set-server=latin1"); + mtr_add_arg($args, "--disable-performance-schema"); if ( $opt_debug ) { From db9fad1562b37b8d362bb48a35ac8d0bd9d00b4c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2024 23:20:07 +0100 Subject: [PATCH 091/121] cleanup: main.log_tables test --- mysql-test/main/log_tables.result | 97 ++++++++++------ mysql-test/main/log_tables.test | 183 +++++++++++------------------- 2 files changed, 129 insertions(+), 151 deletions(-) diff --git a/mysql-test/main/log_tables.result b/mysql-test/main/log_tables.result index 553b4929bb5..e77de1b13ee 100644 --- a/mysql-test/main/log_tables.result +++ b/mysql-test/main/log_tables.result @@ -1,14 +1,9 @@ SET SQL_MODE=""; -SET @old_general_log_state = @@global.general_log; SET @old_log_output= @@global.log_output; SET @old_slow_query_log= @@global.slow_query_log; SET @old_general_log= @@global.general_log; SET @old_long_query_time= @@session.long_query_time; use mysql; -SET @saved_long_query_time = @@long_query_time; -SET @saved_log_output = @@log_output; -SET @saved_general_log = @@GLOBAL.general_log; -SET @saved_slow_query_log = @@GLOBAL.slow_query_log; truncate table general_log; select * from general_log; event_time user_host thread_id server_id command_type argument @@ -120,6 +115,9 @@ show open tables; Database Table In_use Name_locked SET GLOBAL GENERAL_LOG=ON; SET GLOBAL SLOW_QUERY_LOG=ON; +# +# Bug#23924 general_log truncates queries with character set introducers. +# truncate table mysql.general_log; set names binary; select _koi8r'' as test; @@ -131,6 +129,9 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query set names binary TIMESTAMP USER_HOST THREAD_ID 1 Query select _koi8r'\xD4\xC5\xD3\xD4' as test TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log set names utf8; +# +# Bug #16905 Log tables: unicode statements are logged incorrectly +# truncate table mysql.general_log; set names utf8; create table bug16905 (s char(15) character set utf8 default 'пусто'); @@ -142,6 +143,9 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query create table bug16905 (s char(15) characte TIMESTAMP USER_HOST THREAD_ID 1 Query insert into bug16905 values ('новое') TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log drop table bug16905; +# +# Bug #17600: Invalid data logged into mysql.slow_log +# truncate table mysql.slow_log; set session long_query_time=1; select sleep(2); @@ -150,7 +154,11 @@ sleep(2) select * from mysql.slow_log; start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text thread_id rows_affected TIMESTAMP USER_HOST QUERY_TIME 00:00:00.000000 1 0 mysql 0 0 1 select sleep(2) THREAD_ID 0 -set @@session.long_query_time = @saved_long_query_time; +set @@session.long_query_time = @old_long_query_time; +# +# Bug #18559 log tables cannot change engine, and gets deadlocked when +# dropping w/ log on +# alter table mysql.general_log engine=myisam; ERROR HY000: You cannot 'ALTER' a log table if logging is enabled alter table mysql.slow_log engine=myisam; @@ -232,7 +240,7 @@ TIMESTAMP USER_HOST THREAD_ID 1 Query truncate table mysql.slow_log TIMESTAMP USER_HOST THREAD_ID 1 Query set session long_query_time=1 TIMESTAMP USER_HOST THREAD_ID 1 Query select sleep(2) TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.slow_log -TIMESTAMP USER_HOST THREAD_ID 1 Query set @@session.long_query_time = @saved_long_query_time +TIMESTAMP USER_HOST THREAD_ID 1 Query set @@session.long_query_time = @old_long_query_time TIMESTAMP USER_HOST THREAD_ID 1 Query alter table mysql.general_log engine=myisam TIMESTAMP USER_HOST THREAD_ID 1 Query alter table mysql.slow_log engine=myisam TIMESTAMP USER_HOST THREAD_ID 1 Query drop table mysql.general_log @@ -300,17 +308,20 @@ ON UPDATE CURRENT_TIMESTAMP, set global general_log='ON'; set global slow_query_log='ON'; use test; +# +# Bug #20139 Infinite loop after "FLUSH" and "LOCK tabX, general_log" +# flush tables with read lock; unlock tables; use mysql; lock tables general_log read local, help_category read local; ERROR HY000: You can't use locks with log tables unlock tables; +# +# Bug #17544 Cannot do atomic log rotate and +# Bug #21785 Server crashes after rename of the log table +# SET SESSION long_query_time = 1000; -drop table if exists mysql.renamed_general_log; -drop table if exists mysql.renamed_slow_log; -drop table if exists mysql.general_log_new; -drop table if exists mysql.slow_log_new; use mysql; RENAME TABLE general_log TO renamed_general_log; ERROR HY000: Cannot rename 'general_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'general_log' @@ -356,13 +367,16 @@ set global slow_query_log='ON'; ERROR 42S02: Table 'mysql.slow_log' doesn't exist RENAME TABLE general_log2 TO general_log; RENAME TABLE slow_log2 TO slow_log; -SET SESSION long_query_time = @saved_long_query_time; +SET SESSION long_query_time = @old_long_query_time; set global general_log='ON'; set global slow_query_log='ON'; flush logs; flush logs; drop table renamed_general_log, renamed_slow_log; use test; +# +# Bug #21966 Strange warnings on repair of the log tables +# use mysql; repair table general_log; Table Op Msg_type Msg_text @@ -380,6 +394,10 @@ slow_log slow_log_new drop table slow_log_new, general_log_new; use test; +# +# Bug#69953 / MDEV-4851 +# Log tables should be modifable on LOG_OUTPUT != TABLE +# SET GLOBAL LOG_OUTPUT = 'FILE'; SET GLOBAL slow_query_log = 1; SET GLOBAL general_log = 1; @@ -388,6 +406,10 @@ ALTER TABLE mysql.general_log ADD COLUMN comment_text TEXT NOT NULL; SET GLOBAL LOG_OUTPUT = 'NONE'; ALTER TABLE mysql.slow_log DROP COLUMN comment_text; ALTER TABLE mysql.general_log DROP COLUMN comment_text; +# +# Bug#27857 (Log tables supplies the wrong value for generating +# AUTO_INCREMENT numbers) +# SET GLOBAL LOG_OUTPUT = 'TABLE'; SET GLOBAL general_log = 0; FLUSH LOGS; @@ -451,16 +473,15 @@ START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own sl START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) THREAD_ID 0 3 START_TIME USER_HOST QUERY_TIME 00:00:00.000000 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) THREAD_ID 0 4 SET GLOBAL slow_query_log = 0; -SET SESSION long_query_time =@saved_long_query_time; +SET SESSION long_query_time =@old_long_query_time; FLUSH LOGS; ALTER TABLE mysql.slow_log DROP COLUMN seq; ALTER TABLE mysql.slow_log ENGINE = CSV; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; -drop procedure if exists proc25422_truncate_slow; -drop procedure if exists proc25422_truncate_general; -drop procedure if exists proc25422_alter_slow; -drop procedure if exists proc25422_alter_general; +# +# Bug#25422 (Hang with log tables) +# use test// create procedure proc25422_truncate_slow (loops int) begin @@ -485,26 +506,26 @@ end// create procedure proc25422_alter_slow (loops int) begin declare v1 int default 0; +declare old_log_state int default @@global.slow_query_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do -set @old_log_state = @@global.slow_query_log; set global slow_query_log = 'OFF'; alter table mysql.slow_log engine = CSV; -set global slow_query_log = @old_log_state; +set global slow_query_log = old_log_state; set v1 = v1 + 1; end while; end// create procedure proc25422_alter_general (loops int) begin declare v1 int default 0; +declare old_log_state int default @@global.general_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do -set @old_log_state = @@global.general_log; set global general_log = 'OFF'; alter table mysql.general_log engine = CSV; -set global general_log = @old_log_state; +set global general_log = old_log_state; set v1 = v1 + 1; end while; end// @@ -563,17 +584,19 @@ drop procedure proc25422_truncate_slow; drop procedure proc25422_truncate_general; drop procedure proc25422_alter_slow; drop procedure proc25422_alter_general; +# +# Bug#23044 (Warnings on flush of a log table) +# FLUSH TABLE mysql.general_log; show warnings; Level Code Message FLUSH TABLE mysql.slow_log; show warnings; Level Code Message -DROP TABLE IF EXISTS `db_17876.slow_log_data`; -DROP TABLE IF EXISTS `db_17876.general_log_data`; -DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; -DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; -DROP DATABASE IF EXISTS `db_17876`; +# +# Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the +# thread) +# CREATE DATABASE db_17876; CREATE TABLE `db_17876.slow_log_data` ( `start_time` timestamp(6) default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, @@ -686,6 +709,9 @@ DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; +# +# Bug#21557 entries in the general query log truncated at 1000 characters. +# select CONNECTION_ID() into @thread_id; truncate table mysql.general_log; set global general_log = on; @@ -902,9 +928,9 @@ Execute select '000 001 002 003 004 005 006 007 008 009010 011 012 013 014 015 0 Query set global general_log = off deallocate prepare long_query; set global general_log = @old_general_log; -DROP TABLE IF EXISTS log_count; -DROP TABLE IF EXISTS slow_log_copy; -DROP TABLE IF EXISTS general_log_copy; +# +# Bug#34306: Can't make copy of log tables when server binary log is enabled +# CREATE TABLE log_count (count BIGINT(21)); SET GLOBAL general_log = ON; SET GLOBAL slow_query_log = ON; @@ -926,9 +952,12 @@ CREATE TABLE general_log_copy SELECT * FROM mysql.general_log; INSERT INTO general_log_copy SELECT * FROM mysql.general_log; INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log)); DROP TABLE general_log_copy; -SET GLOBAL general_log = @saved_general_log; -SET GLOBAL slow_query_log = @saved_slow_query_log; +SET GLOBAL general_log = @old_general_log; +SET GLOBAL slow_query_log = @old_slow_query_log; DROP TABLE log_count; +# +# Bug #31700: thd->examined_row_count not incremented for 'const' type queries +# SET SESSION long_query_time = 0; SET GLOBAL slow_query_log = ON; FLUSH LOGS; @@ -954,9 +983,10 @@ TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - KEY', f1,f2,f3,SLEEP(1.1) FROM t1 TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - PK', f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f1=2 DROP TABLE t1; TRUNCATE TABLE mysql.slow_log; +# +# Bug #47924 main.log_tables times out sporadically +# use mysql; -drop table if exists renamed_general_log; -drop table if exists renamed_slow_log; RENAME TABLE general_log TO renamed_general_log; ERROR HY000: Cannot rename 'general_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'general_log' RENAME TABLE slow_log TO renamed_slow_log; @@ -964,7 +994,6 @@ ERROR HY000: Cannot rename 'slow_log'. When logging enabled, rename to/from log use test; flush tables with read lock; unlock tables; -SET @@session.long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; SET @@global.general_log= @old_general_log; diff --git a/mysql-test/main/log_tables.test b/mysql-test/main/log_tables.test index 9d964b8090b..b54b154cf05 100644 --- a/mysql-test/main/log_tables.test +++ b/mysql-test/main/log_tables.test @@ -1,13 +1,9 @@ # this test needs multithreaded mysqltest -- source include/not_embedded.inc -# -# Basic log tables test -# -# check that CSV engine was compiled in + --source include/have_csv.inc SET SQL_MODE=""; -SET @old_general_log_state = @@global.general_log; SET @old_log_output= @@global.log_output; SET @old_slow_query_log= @@global.slow_query_log; SET @old_general_log= @@global.general_log; @@ -16,16 +12,9 @@ SET @old_long_query_time= @@session.long_query_time; --disable_ps_protocol use mysql; -# Capture initial settings of system variables -# so that we can revert to old state after manipulation for testing -# NOTE: PLEASE USE THESE VALUES TO 'RESET' SYSTEM VARIABLES -# Capturing old values within the tests results in loss of values -# due to people not paying attention to previous tests' changes, captures -# or improper cleanup -SET @saved_long_query_time = @@long_query_time; -SET @saved_log_output = @@log_output; -SET @saved_general_log = @@GLOBAL.general_log; -SET @saved_slow_query_log = @@GLOBAL.slow_query_log; +# +# Basic log tables test +# # # Check that log tables work and we can do basic selects. This also @@ -147,9 +136,9 @@ show open tables; SET GLOBAL GENERAL_LOG=ON; SET GLOBAL SLOW_QUERY_LOG=ON; -# -# Bug#23924 general_log truncates queries with character set introducers. -# +--echo # +--echo # Bug#23924 general_log truncates queries with character set introducers. +--echo # truncate table mysql.general_log; set names binary; select _koi8r'' as test; @@ -157,9 +146,9 @@ select _koi8r' select * from mysql.general_log; set names utf8; -# -# Bug #16905 Log tables: unicode statements are logged incorrectly -# +--echo # +--echo # Bug #16905 Log tables: unicode statements are logged incorrectly +--echo # truncate table mysql.general_log; set names utf8; @@ -169,21 +158,21 @@ insert into bug16905 values ('новое'); select * from mysql.general_log; drop table bug16905; -# -# Bug #17600: Invalid data logged into mysql.slow_log -# +--echo # +--echo # Bug #17600: Invalid data logged into mysql.slow_log +--echo # truncate table mysql.slow_log; set session long_query_time=1; select sleep(2); --replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME 12 THREAD_ID select * from mysql.slow_log; -set @@session.long_query_time = @saved_long_query_time; +set @@session.long_query_time = @old_long_query_time; -# -# Bug #18559 log tables cannot change engine, and gets deadlocked when -# dropping w/ log on -# +--echo # +--echo # Bug #18559 log tables cannot change engine, and gets deadlocked when +--echo # dropping w/ log on +--echo # # check that appropriate error messages are given when one attempts to alter # or drop a log tables, while corresponding logs are enabled @@ -322,9 +311,9 @@ set global general_log='ON'; set global slow_query_log='ON'; use test; -# -# Bug #20139 Infinite loop after "FLUSH" and "LOCK tabX, general_log" -# +--echo # +--echo # Bug #20139 Infinite loop after "FLUSH" and "LOCK tabX, general_log" +--echo # flush tables with read lock; unlock tables; @@ -333,18 +322,12 @@ use mysql; lock tables general_log read local, help_category read local; unlock tables; -# -# Bug #17544 Cannot do atomic log rotate and -# Bug #21785 Server crashes after rename of the log table -# +--echo # +--echo # Bug #17544 Cannot do atomic log rotate and +--echo # Bug #21785 Server crashes after rename of the log table +--echo # SET SESSION long_query_time = 1000; ---disable_warnings -drop table if exists mysql.renamed_general_log; -drop table if exists mysql.renamed_slow_log; -drop table if exists mysql.general_log_new; -drop table if exists mysql.slow_log_new; ---enable_warnings use mysql; # Should result in error @@ -399,7 +382,7 @@ set global slow_query_log='ON'; RENAME TABLE general_log2 TO general_log; RENAME TABLE slow_log2 TO slow_log; -SET SESSION long_query_time = @saved_long_query_time; +SET SESSION long_query_time = @old_long_query_time; # this should work set global general_log='ON'; @@ -427,13 +410,6 @@ use test; # TODO: improve filtering of expected errors in master.err in # mysql-test-run.pl (based on the test name ?), and uncomment this test. -# --disable_warnings -# drop table if exists mysql.bad_general_log; -# drop table if exists mysql.bad_slow_log; -# drop table if exists mysql.general_log_hide; -# drop table if exists mysql.slow_log_hide; -# --enable_warnings -# # create table mysql.bad_general_log (a int) engine= CSV; # create table mysql.bad_slow_log (a int) engine= CSV; # @@ -459,9 +435,9 @@ use test; # drop table mysql.bad_general_log; # drop table mysql.bad_slow_log; -# -# Bug #21966 Strange warnings on repair of the log tables -# +--echo # +--echo # Bug #21966 Strange warnings on repair of the log tables +--echo # use mysql; # check that no warning occurs on repair of the log tables @@ -474,11 +450,10 @@ show tables like "%log%"; drop table slow_log_new, general_log_new; use test; -# -# Bug#69953 / MDEV-4851 -# Log tables should be modifable on LOG_OUTPUT != TABLE -# -# +--echo # +--echo # Bug#69953 / MDEV-4851 +--echo # Log tables should be modifable on LOG_OUTPUT != TABLE +--echo # SET GLOBAL LOG_OUTPUT = 'FILE'; SET GLOBAL slow_query_log = 1; @@ -492,10 +467,10 @@ ALTER TABLE mysql.slow_log DROP COLUMN comment_text; ALTER TABLE mysql.general_log DROP COLUMN comment_text; -# -# Bug#27857 (Log tables supplies the wrong value for generating -# AUTO_INCREMENT numbers) -# +--echo # +--echo # Bug#27857 (Log tables supplies the wrong value for generating +--echo # AUTO_INCREMENT numbers) +--echo # SET GLOBAL LOG_OUTPUT = 'TABLE'; @@ -554,7 +529,7 @@ SELECT "My own slow query", sleep(2); SELECT * FROM mysql.slow_log WHERE seq >= 2 LIMIT 3; SET GLOBAL slow_query_log = 0; -SET SESSION long_query_time =@saved_long_query_time; +SET SESSION long_query_time =@old_long_query_time; FLUSH LOGS; ALTER TABLE mysql.slow_log DROP COLUMN seq; @@ -563,16 +538,9 @@ ALTER TABLE mysql.slow_log ENGINE = CSV; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; -# -# Bug#25422 (Hang with log tables) -# - ---disable_warnings -drop procedure if exists proc25422_truncate_slow; -drop procedure if exists proc25422_truncate_general; -drop procedure if exists proc25422_alter_slow; -drop procedure if exists proc25422_alter_general; ---enable_warnings +--echo # +--echo # Bug#25422 (Hang with log tables) +--echo # delimiter //; @@ -602,14 +570,14 @@ end// create procedure proc25422_alter_slow (loops int) begin declare v1 int default 0; + declare old_log_state int default @@global.slow_query_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do - set @old_log_state = @@global.slow_query_log; set global slow_query_log = 'OFF'; alter table mysql.slow_log engine = CSV; - set global slow_query_log = @old_log_state; + set global slow_query_log = old_log_state; set v1 = v1 + 1; end while; end// @@ -617,14 +585,14 @@ end// create procedure proc25422_alter_general (loops int) begin declare v1 int default 0; + declare old_log_state int default @@global.general_log; declare ER_BAD_LOG_STATEMENT condition for 1575; declare continue handler for ER_BAD_LOG_STATEMENT begin end; while v1 < loops do - set @old_log_state = @@global.general_log; set global general_log = 'OFF'; alter table mysql.general_log engine = CSV; - set global general_log = @old_log_state; + set global general_log = old_log_state; set v1 = v1 + 1; end while; end// @@ -713,9 +681,9 @@ drop procedure proc25422_alter_general; --enable_ps_protocol -# -# Bug#23044 (Warnings on flush of a log table) -# +--echo # +--echo # Bug#23044 (Warnings on flush of a log table) +--echo # FLUSH TABLE mysql.general_log; show warnings; @@ -723,18 +691,10 @@ show warnings; FLUSH TABLE mysql.slow_log; show warnings; -# -# Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the -# thread) -# - ---disable_warnings -DROP TABLE IF EXISTS `db_17876.slow_log_data`; -DROP TABLE IF EXISTS `db_17876.general_log_data`; -DROP PROCEDURE IF EXISTS `db_17876.archiveSlowLog`; -DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; -DROP DATABASE IF EXISTS `db_17876`; ---enable_warnings +--echo # +--echo # Bug#17876 (Truncating mysql.slow_log in a SP after using cursor locks the +--echo # thread) +--echo # CREATE DATABASE db_17876; @@ -872,9 +832,9 @@ DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log; SET GLOBAL slow_query_log = @old_slow_query_log; -# -# Bug#21557 entries in the general query log truncated at 1000 characters. -# +--echo # +--echo # Bug#21557 entries in the general query log truncated at 1000 characters. +--echo # select CONNECTION_ID() into @thread_id; --disable_ps_protocol @@ -992,15 +952,9 @@ select command_type, argument from mysql.general_log where thread_id = @thread_i deallocate prepare long_query; set global general_log = @old_general_log; -# -# Bug#34306: Can't make copy of log tables when server binary log is enabled -# - ---disable_warnings -DROP TABLE IF EXISTS log_count; -DROP TABLE IF EXISTS slow_log_copy; -DROP TABLE IF EXISTS general_log_copy; ---enable_warnings +--echo # +--echo # Bug#34306: Can't make copy of log tables when server binary log is enabled +--echo # CREATE TABLE log_count (count BIGINT(21)); @@ -1030,14 +984,14 @@ INSERT INTO general_log_copy SELECT * FROM mysql.general_log; INSERT INTO log_count (count) VALUES ((SELECT count(*) FROM mysql.general_log)); DROP TABLE general_log_copy; -SET GLOBAL general_log = @saved_general_log; -SET GLOBAL slow_query_log = @saved_slow_query_log; +SET GLOBAL general_log = @old_general_log; +SET GLOBAL slow_query_log = @old_slow_query_log; DROP TABLE log_count; -# -# Bug #31700: thd->examined_row_count not incremented for 'const' type queries -# +--echo # +--echo # Bug #31700: thd->examined_row_count not incremented for 'const' type queries +--echo # SET SESSION long_query_time = 0; SET GLOBAL slow_query_log = ON; @@ -1064,16 +1018,12 @@ DROP TABLE t1; TRUNCATE TABLE mysql.slow_log; -# -# Bug #47924 main.log_tables times out sporadically -# +--echo # +--echo # Bug #47924 main.log_tables times out sporadically +--echo # use mysql; # Should result in error ---disable_warnings -drop table if exists renamed_general_log; -drop table if exists renamed_slow_log; ---enable_warnings --error ER_CANT_RENAME_LOG_TABLE RENAME TABLE general_log TO renamed_general_log; --error ER_CANT_RENAME_LOG_TABLE @@ -1083,7 +1033,6 @@ use test; flush tables with read lock; unlock tables; -SET @@session.long_query_time= @old_long_query_time; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; From dcb814c44ec28e8cf011047407cc7304e93e466a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 21 Jan 2024 23:28:54 +0100 Subject: [PATCH 092/121] MDEV-11628 mysql.slow_log reports incorrect start time use thd->start_time for the "start_time" column of the slow_log table. "current_time" here refers to the current_time() function return value not to the actual *current* time. also fixes MDEV-33267 User with minimal permissions can intentionally corrupt mysql.slow_log table --- mysql-test/main/log_tables.result | 28 ++++++++++++++++++++++++++++ mysql-test/main/log_tables.test | 18 ++++++++++++++++++ sql/log.cc | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/log_tables.result b/mysql-test/main/log_tables.result index e77de1b13ee..5c628458e7a 100644 --- a/mysql-test/main/log_tables.result +++ b/mysql-test/main/log_tables.result @@ -994,6 +994,34 @@ ERROR HY000: Cannot rename 'slow_log'. When logging enabled, rename to/from log use test; flush tables with read lock; unlock tables; +# +# MDEV-33267 User with minimal permissions can intentionally corrupt mysql.slow_log table +# +truncate mysql.slow_log; +set global log_output= 'TABLE'; +create user u@localhost; +set slow_query_log=on, long_query_time=0.1; +select 'before evil-doing', sleep(0.2); +before evil-doing sleep(0.2) +before evil-doing 0 +connect con1,localhost,u,,; +set @@timestamp= 2147483647; +set slow_query_log=on, long_query_time=0.1; +select 'evil-doing', sleep(1.1); +evil-doing sleep(1.1) +evil-doing 0 +disconnect con1; +connection default; +select 'after evil-doing', sleep(0.2); +after evil-doing sleep(0.2) +after evil-doing 0 +select distinct sql_text from mysql.slow_log where sql_text like '%evil%'; +sql_text +select 'before evil-doing', sleep(0.2) +select 'evil-doing', sleep(1.1) +select 'after evil-doing', sleep(0.2) +set global log_output=default; +drop user u@localhost; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; SET @@global.general_log= @old_general_log; diff --git a/mysql-test/main/log_tables.test b/mysql-test/main/log_tables.test index b54b154cf05..1169f2b094c 100644 --- a/mysql-test/main/log_tables.test +++ b/mysql-test/main/log_tables.test @@ -1033,6 +1033,24 @@ use test; flush tables with read lock; unlock tables; +--echo # +--echo # MDEV-33267 User with minimal permissions can intentionally corrupt mysql.slow_log table +--echo # +truncate mysql.slow_log; +set global log_output= 'TABLE'; +create user u@localhost; +set slow_query_log=on, long_query_time=0.1; +select 'before evil-doing', sleep(0.2); +--connect (con1,localhost,u,,) +set @@timestamp= 2147483647; +set slow_query_log=on, long_query_time=0.1; +select 'evil-doing', sleep(1.1); +--disconnect con1 +--connection default +select 'after evil-doing', sleep(0.2); +select distinct sql_text from mysql.slow_log where sql_text like '%evil%'; +set global log_output=default; +drop user u@localhost; SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; diff --git a/sql/log.cc b/sql/log.cc index 75199000b85..32c8ad46321 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1334,7 +1334,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, size_t query_length, query_utime= (current_utime - thd->start_utime); lock_utime= (thd->utime_after_lock - thd->start_utime); my_hrtime_t current_time= { hrtime_from_time(thd->start_time) + - thd->start_time_sec_part + query_utime }; + thd->start_time_sec_part }; if (!query || thd->get_command() == COM_STMT_PREPARE) { From 8bb464899f1658522cc9740fdb73120d7190dca0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 22 Jan 2024 18:01:37 +0100 Subject: [PATCH 093/121] cleanup: unused and undefined methods --- sql/field.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/field.h b/sql/field.h index 836de2d1bd6..4a95a6e0556 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4060,9 +4060,6 @@ public: bool compatible_field_size(uint field_metadata, const Relay_log_info *rli, uint16 mflags, int *order_var) const override; uint row_pack_length() const override { return field_length; } - int pack_cmp(const uchar *a,const uchar *b,uint key_length, - bool insert_or_update); - int pack_cmp(const uchar *b,uint key_length,bool insert_or_update); uint packed_col_length(const uchar *to, uint length) override; uint max_packed_col_length(uint max_length) override; uint size_of() const override { return sizeof *this; } From 14d00fdb15b47c7f06768f39d5d8473ed47bdd18 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 22 Jan 2024 18:17:05 +0100 Subject: [PATCH 094/121] cleanup: MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES no need to use it when both arguments have the same length --- sql/field.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/field.cc b/sql/field.cc index 53dc5f2e15a..9e1e0931ef1 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7562,7 +7562,7 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) const a_ptr, field_length, b_ptr, field_length, Field_string::char_length(), - MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES); + 0); } From a7ee3bc58bc23ad7ac5ced54dc745d0e65bee524 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 22 Jan 2024 18:02:11 +0100 Subject: [PATCH 095/121] MDEV-29954 Unique hash key on column prefix is computed incorrectly use the original, not the truncated, field in the long unique prefix, that is, in the hash(left(field, length)) expression. because MyISAM CHECK/REPAIR in compute_vcols() moves table->field but not prefix fields from keyparts. Also, implement Field_string::cmp_prefix() for prefix comparison of CHAR columns to work. --- mysql-test/main/long_unique_bugs.result | 9 +++++++++ mysql-test/main/long_unique_bugs.test | 8 ++++++++ sql/field.cc | 13 +++++++++++++ sql/field.h | 2 ++ sql/key.cc | 2 +- sql/table.cc | 5 ++--- 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index e5c14afd9c4..30ba3d0af9a 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -651,5 +651,14 @@ f1 f2 f3 f4 f5 f6 f7 4 00004 0001009089999 netstes psit e drop table t1; # +# MDEV-29954 Unique hash key on column prefix is computed incorrectly +# +create table t1 (c char(10),unique key a using hash (c(1))); +insert into t1 values (0); +check table t1 extended; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 5fed7c72d9a..12367b1deb8 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -634,6 +634,14 @@ replace t1 (f2, f3, f4, f5, f6, f7) values ('00004', '0001009089999', '', 'netst select * from t1; drop table t1; +--echo # +--echo # MDEV-29954 Unique hash key on column prefix is computed incorrectly +--echo # +create table t1 (c char(10),unique key a using hash (c(1))); +insert into t1 values (0); +check table t1 extended; +drop table t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/field.cc b/sql/field.cc index 9e1e0931ef1..fc828dcc86c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7566,6 +7566,19 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr) const } +int Field_string::cmp_prefix(const uchar *a_ptr, const uchar *b_ptr, + size_t prefix_char_len) const +{ + size_t field_len= table->field[field_index]->field_length; + + return field_charset()->coll->strnncollsp_nchars(field_charset(), + a_ptr, field_len, + b_ptr, field_len, + prefix_char_len, + 0); +} + + void Field_string::sort_string(uchar *to,uint length) { #ifdef DBUG_ASSERT_EXISTS diff --git a/sql/field.h b/sql/field.h index 4a95a6e0556..aeb2ae0d20a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4038,6 +4038,8 @@ public: String *val_str(String *, String *) override; my_decimal *val_decimal(my_decimal *) override; int cmp(const uchar *,const uchar *) const override; + int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_char_len) const + override; void sort_string(uchar *buff,uint length) override; void update_data_type_statistics(Data_type_statistics *st) const override { diff --git a/sql/key.cc b/sql/key.cc index d801bcc982b..2fa7d7066a4 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -605,7 +605,7 @@ int key_rec_cmp(void *key_p, uchar *first_rec, uchar *second_rec) } /* No null values in the fields - We use the virtual method cmp_max with a max length parameter. + We use the virtual method cmp_prefix with a max length parameter. For most field types this translates into a cmp without max length. The exceptions are the BLOB and VARCHAR field types that take the max length into account. diff --git a/sql/table.cc b/sql/table.cc index a5e33052d3f..f3d186f4d9d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1272,12 +1272,11 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, if (keypart->key_part_flag & HA_PART_KEY_SEG) { int length= keypart->length/keypart->field->charset()->mbmaxlen; + Field *kpf= table->field[keypart->field->field_index]; list_item= new (mem_root) Item_func_left(thd, - new (mem_root) Item_field(thd, keypart->field), + new (mem_root) Item_field(thd, kpf), new (mem_root) Item_int(thd, length)); list_item->fix_fields(thd, NULL); - keypart->field->vcol_info= - table->field[keypart->field->field_index]->vcol_info; } else list_item= new (mem_root) Item_field(thd, keypart->field); From 011d666ada0514875717a15171b93b139a701219 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Tue, 23 Jan 2024 20:53:52 +0530 Subject: [PATCH 096/121] reorder the log columns for MDEV-27087 --- .../plugins/r/sql_error_log_withdbinfo.result | 8 +++---- .../plugins/t/sql_error_log_withdbinfo.test | 2 +- plugin/sql_errlog/sql_errlog.c | 22 +++++++++---------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result b/mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result index 649d91269b6..4d869da5fd8 100644 --- a/mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result +++ b/mysql-test/suite/plugins/r/sql_error_log_withdbinfo.result @@ -28,10 +28,10 @@ CREATE DATABASE `NULL`; USE `NULL`; DROP DATABASE db; ERROR HY000: Can't drop database 'db'; database doesn't exist -THREAD_ID `test` TIME HOSTNAME ERROR 1238: Variable 'sql_error_log_with_db_and_thread_info' is a read only variable : SET sql_error_log_with_db_and_thread_info=OFF -THREAD_ID `test` TIME HOSTNAME ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db -THREAD_ID NULL TIME HOSTNAME ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db -THREAD_ID `NULL` TIME HOSTNAME ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db +TIME THREAD_ID HOSTNAME `test` ERROR 1238: Variable 'sql_error_log_with_db_and_thread_info' is a read only variable : SET sql_error_log_with_db_and_thread_info=OFF +TIME THREAD_ID HOSTNAME `test` ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db +TIME THREAD_ID HOSTNAME NULL ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db +TIME THREAD_ID HOSTNAME `NULL` ERROR 1008: Can't drop database 'db'; database doesn't exist : DROP DATABASE db DROP DATABASE `NULL`; # Reset CREATE DATABASE test; diff --git a/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test b/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test index bddcc14e275..c28fe793805 100644 --- a/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test +++ b/mysql-test/suite/plugins/t/sql_error_log_withdbinfo.test @@ -40,7 +40,7 @@ DROP DATABASE db; --let SEARCH_FILE= $MYSQLD_DATADIR/sql_errors.log --let LINES_TO_READ=4 ---replace_regex /[1-9]* `NULL` [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID `NULL` TIME HOSTNAME / /[1-9]* `test` [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID `test` TIME HOSTNAME / /[1-9]* NULL [1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [^E]*/THREAD_ID NULL TIME HOSTNAME / +--replace_regex /[1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]* .* @ .* `test` /TIME THREAD_ID HOSTNAME `test` //[1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]* .* @ .* NULL /TIME THREAD_ID HOSTNAME NULL //[1-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]* .* @ .* `NULL` /TIME THREAD_ID HOSTNAME `NULL` / --source include/read_head.inc DROP DATABASE `NULL`; diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c index a3f36fc966e..d668ed8779b 100644 --- a/plugin/sql_errlog/sql_errlog.c +++ b/plugin/sql_errlog/sql_errlog.c @@ -107,21 +107,19 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), { if (event->database.str) { - logger_printf(logfile, "%llu %`s %04d-%02d-%02d %2d:%02d:%02d " - "%s ERROR %d: %s : %s \n", - event->general_thread_id, event->database.str, t.tm_year + 1900, - t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, - t.tm_sec, event->general_user, event->general_error_code, - event->general_command, event->general_query); + logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d %llu " + "%s %`s ERROR %d: %s : %s \n", + t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, + t.tm_sec, event->general_thread_id, event->general_user, event->database.str, + event->general_error_code, event->general_command, event->general_query); } else { - logger_printf(logfile, "%llu %s %04d-%02d-%02d %2d:%02d:%02d " - "%s ERROR %d: %s : %s \n", - event->general_thread_id, "NULL", t.tm_year + 1900, - t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, - t.tm_sec, event->general_user, event->general_error_code, - event->general_command, event->general_query); + logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d %llu " + "%s %s ERROR %d: %s : %s \n", + t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, + t.tm_sec, event->general_thread_id, event->general_user, "NULL", + event->general_error_code, event->general_command, event->general_query); } } else From 7c2f0822223a342d1ec4d8ec12c64291d7379492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Tue, 23 Jan 2024 18:38:22 +0200 Subject: [PATCH 097/121] Improve READLINE_V5 detection More in depth check to cover all used readline functions. --- cmake/readline.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/readline.cmake b/cmake/readline.cmake index 9c35d8c7d22..55a2867d2a3 100644 --- a/cmake/readline.cmake +++ b/cmake/readline.cmake @@ -114,6 +114,9 @@ MACRO (MYSQL_FIND_SYSTEM_READLINE) { rl_completion_func_t *func1= (rl_completion_func_t*)0; rl_compentry_func_t *func2= (rl_compentry_func_t*)0; + rl_on_new_line(); + rl_replace_line(\"\", 0); + rl_redisplay(); }" NEW_READLINE_INTERFACE) From 3699a7e1a90e17cfc016518fc4922b94d2dbe6be Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 11 Jan 2024 15:01:00 +1100 Subject: [PATCH 098/121] macos: Fix CMAKE_OSX_ARCHITECTURES when not set When CMAKE_OSX_ARCHITECTURES isn't set we end up with "Packaging as: mariadb-10.4.33-osx10.19-x86_64" on arm64 builders. Instead of implying 64bit is x86, use CMAKE_SYSTEM_PROCESSOR to form the filename. --- cmake/package_name.cmake | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index ce13a446fe6..ab0c1d44de8 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -99,11 +99,7 @@ IF(NOT VERSION) SET(DEFAULT_MACHINE "${CMAKE_OSX_ARCHITECTURES}") ENDIF() ELSE() - IF(64BIT) - SET(DEFAULT_MACHINE "x86_64") - ELSE() - SET(DEFAULT_MACHINE "i386") - ENDIF() + SET(DEFAULT_MACHINE ${CMAKE_SYSTEM_PROCESSOR}) ENDIF() IF(DEFAULT_MACHINE MATCHES "i386") From 9d88c5b8b40cce897b0a718584289f8ca331381e Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 23 Jan 2024 23:56:40 +0400 Subject: [PATCH 099/121] MDEV-31616 Problems with a stored function EMPTY() on upgrade to 10.6. The IDENT_sys doesn't include keywords, so the function with the keyword name can be created, but cannot be called. Moving keywords to new rules keyword_func_sp_var_and_label and keyword_func_sp_var_not_label so the functions with these names are allowed. --- mysql-test/main/parser.result | 16 +- mysql-test/main/sp.result | 73 ++++ mysql-test/main/sp.test | 38 ++ .../suite/compat/oracle/r/parser.result | 16 +- mysql-test/suite/funcs_1/r/storedproc.result | 150 ++++++-- mysql-test/suite/funcs_1/t/storedproc.test | 211 ++++++++++- .../suite/perfschema/r/digest_view.result | 50 +-- .../start_server_low_digest_sql_length.result | 4 +- sql/item_create.cc | 346 ++++++++++++++++++ sql/lex.h | 5 - sql/sql_yacc.yy | 243 ++++-------- 11 files changed, 897 insertions(+), 255 deletions(-) diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result index 89732e20b40..bf9b8e4b137 100644 --- a/mysql-test/main/parser.result +++ b/mysql-test/main/parser.result @@ -1507,7 +1507,7 @@ BEGIN NOT ATOMIC DECLARE history INT; SET history=10; SELECT history; END SELECT history FROM t1 SELECT history 'alias' FROM t1 SELECT history() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.history does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT history.history() Error 1630 FUNCTION history.history does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT history DATE FROM t1 @@ -1530,7 +1530,7 @@ BEGIN NOT ATOMIC DECLARE next INT; SET next=10; SELECT next; END SELECT next FROM t1 SELECT next 'alias' FROM t1 SELECT next() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.next does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT next.next() Error 1630 FUNCTION next.next does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT next DATE FROM t1 @@ -1577,7 +1577,7 @@ BEGIN NOT ATOMIC DECLARE previous INT; SET previous=10; SELECT previous; END SELECT previous FROM t1 SELECT previous 'alias' FROM t1 SELECT previous() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.previous does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT previous.previous() Error 1630 FUNCTION previous.previous does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT previous DATE FROM t1 @@ -1601,7 +1601,7 @@ BEGIN NOT ATOMIC DECLARE system INT; SET system=10; SELECT system; END SELECT system FROM t1 SELECT system 'alias' FROM t1 SELECT system() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.system does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system.system() Error 1630 FUNCTION system.system does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system DATE FROM t1 @@ -1624,7 +1624,7 @@ BEGIN NOT ATOMIC DECLARE system_time INT; SET system_time=10; SELECT system_time SELECT system_time FROM t1 SELECT system_time 'alias' FROM t1 SELECT system_time() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.system_time does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system_time.system_time() Error 1630 FUNCTION system_time.system_time does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system_time DATE FROM t1 @@ -1695,7 +1695,7 @@ BEGIN NOT ATOMIC DECLARE transaction INT; SET transaction=10; SELECT transaction SELECT transaction FROM t1 SELECT transaction 'alias' FROM t1 SELECT transaction() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.transaction does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT transaction.transaction() Error 1630 FUNCTION transaction.transaction does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT transaction DATE FROM t1 @@ -1741,7 +1741,7 @@ BEGIN NOT ATOMIC DECLARE versioning INT; SET versioning=10; SELECT versioning; E SELECT versioning FROM t1 SELECT versioning 'alias' FROM t1 SELECT versioning() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.versioning does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT versioning.versioning() Error 1630 FUNCTION versioning.versioning does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT versioning DATE FROM t1 @@ -1764,7 +1764,7 @@ BEGIN NOT ATOMIC DECLARE without INT; SET without=10; SELECT without; END SELECT without FROM t1 SELECT without 'alias' FROM t1 SELECT without() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.without does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT without.without() Error 1630 FUNCTION without.without does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT without DATE FROM t1 diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 4e93973782f..f33fbc84f30 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -9008,4 +9008,77 @@ BEGIN NOT ATOMIC DECLARE r ROW TYPE OF t1 DEFAULT (SELECT * FROM t1); SELECT r.a r.a 1 SET SESSION log_slow_verbosity= @tmp; +# +# MDEV-31616 Problems with a stored function EMPTY() on upgrade to 10.6. +# +CREATE OR REPLACE FUNCTION empty(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +Warnings: +Note 1585 This function 'empty' has the same name as a native function +SELECT empty('1'); +empty('1') +0 +Warnings: +Note 1585 This function 'empty' has the same name as a native function +DROP FUNCTION empty; +CREATE OR REPLACE FUNCTION json_table(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +Warnings: +Note 1585 This function 'json_table' has the same name as a native function +SELECT json_table('1'); +json_table('1') +0 +Warnings: +Note 1585 This function 'json_table' has the same name as a native function +DROP FUNCTION json_table; +CREATE OR REPLACE FUNCTION nested(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +Warnings: +Note 1585 This function 'nested' has the same name as a native function +SELECT nested('1'); +nested('1') +0 +Warnings: +Note 1585 This function 'nested' has the same name as a native function +DROP FUNCTION nested; +CREATE OR REPLACE FUNCTION ordinality(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +Warnings: +Note 1585 This function 'ordinality' has the same name as a native function +SELECT ordinality('1'); +ordinality('1') +0 +Warnings: +Note 1585 This function 'ordinality' has the same name as a native function +DROP FUNCTION ordinality; +CREATE OR REPLACE FUNCTION path(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +Warnings: +Note 1585 This function 'path' has the same name as a native function +SELECT path('1'); +path('1') +0 +Warnings: +Note 1585 This function 'path' has the same name as a native function +DROP FUNCTION path; +CREATE OR REPLACE FUNCTION fast(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +Warnings: +Note 1585 This function 'fast' has the same name as a native function +SELECT fast('1'); +fast('1') +0 +Warnings: +Note 1585 This function 'fast' has the same name as a native function +DROP FUNCTION fast; +CREATE OR REPLACE FUNCTION relay(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +Warnings: +Note 1585 This function 'relay' has the same name as a native function +SELECT relay('1'); +relay('1') +0 +Warnings: +Note 1585 This function 'relay' has the same name as a native function +DROP FUNCTION relay; +CREATE OR REPLACE FUNCTION database() RETURNS int RETURN 333; +Warnings: +Note 1585 This function 'database' has the same name as a native function +SELECT database(); +database() +test +DROP FUNCTION database; DROP TABLE t1; diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index cc244a20014..5a794e46cd2 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10618,6 +10618,44 @@ BEGIN NOT ATOMIC DECLARE r ROW TYPE OF t1 DEFAULT (SELECT * FROM t1); SELECT r.a --delimiter ; SET SESSION log_slow_verbosity= @tmp; + +--echo # +--echo # MDEV-31616 Problems with a stored function EMPTY() on upgrade to 10.6. +--echo # +CREATE OR REPLACE FUNCTION empty(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +SELECT empty('1'); +DROP FUNCTION empty; + +CREATE OR REPLACE FUNCTION json_table(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +SELECT json_table('1'); +DROP FUNCTION json_table; + +CREATE OR REPLACE FUNCTION nested(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +SELECT nested('1'); +DROP FUNCTION nested; + +CREATE OR REPLACE FUNCTION ordinality(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +SELECT ordinality('1'); +DROP FUNCTION ordinality; + +CREATE OR REPLACE FUNCTION path(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +SELECT path('1'); +DROP FUNCTION path; + + +CREATE OR REPLACE FUNCTION fast(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +SELECT fast('1'); +DROP FUNCTION fast; + +CREATE OR REPLACE FUNCTION relay(a VARCHAR(128)) RETURNS int RETURN LENGTH(a)=0; +SELECT relay('1'); +DROP FUNCTION relay; + +CREATE OR REPLACE FUNCTION database() RETURNS int RETURN 333; +SELECT database(); +DROP FUNCTION database; + + # Cleanup DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/r/parser.result b/mysql-test/suite/compat/oracle/r/parser.result index 32ea444ea25..0944b7f39bd 100644 --- a/mysql-test/suite/compat/oracle/r/parser.result +++ b/mysql-test/suite/compat/oracle/r/parser.result @@ -84,7 +84,7 @@ DECLARE history INT; BEGIN history:=10; SELECT history; END SELECT history FROM t1 SELECT history 'alias' FROM t1 SELECT history() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.history does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT history.history() Error 1630 FUNCTION history.history does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT history DATE FROM t1 @@ -106,7 +106,7 @@ DECLARE next INT; BEGIN next:=10; SELECT next; END SELECT next FROM t1 SELECT next 'alias' FROM t1 SELECT next() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.next does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT next.next() Error 1630 FUNCTION next.next does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT next DATE FROM t1 @@ -151,7 +151,7 @@ DECLARE previous INT; BEGIN previous:=10; SELECT previous; END SELECT previous FROM t1 SELECT previous 'alias' FROM t1 SELECT previous() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.previous does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT previous.previous() Error 1630 FUNCTION previous.previous does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT previous DATE FROM t1 @@ -174,7 +174,7 @@ DECLARE system INT; BEGIN system:=10; SELECT system; END SELECT system FROM t1 SELECT system 'alias' FROM t1 SELECT system() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.system does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system.system() Error 1630 FUNCTION system.system does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system DATE FROM t1 @@ -196,7 +196,7 @@ DECLARE system_time INT; BEGIN system_time:=10; SELECT system_time; END SELECT system_time FROM t1 SELECT system_time 'alias' FROM t1 SELECT system_time() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.system_time does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system_time.system_time() Error 1630 FUNCTION system_time.system_time does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT system_time DATE FROM t1 @@ -264,7 +264,7 @@ DECLARE transaction INT; BEGIN transaction:=10; SELECT transaction; END SELECT transaction FROM t1 SELECT transaction 'alias' FROM t1 SELECT transaction() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.transaction does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT transaction.transaction() Error 1630 FUNCTION transaction.transaction does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT transaction DATE FROM t1 @@ -308,7 +308,7 @@ DECLARE versioning INT; BEGIN versioning:=10; SELECT versioning; END SELECT versioning FROM t1 SELECT versioning 'alias' FROM t1 SELECT versioning() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.versioning does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT versioning.versioning() Error 1630 FUNCTION versioning.versioning does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT versioning DATE FROM t1 @@ -330,7 +330,7 @@ DECLARE without INT; BEGIN without:=10; SELECT without; END SELECT without FROM t1 SELECT without 'alias' FROM t1 SELECT without() -Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1 +Error 1630 FUNCTION test.without does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT without.without() Error 1630 FUNCTION without.without does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual SELECT without DATE FROM t1 diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result index c9f92d51210..3d33181c121 100644 --- a/mysql-test/suite/funcs_1/r/storedproc.result +++ b/mysql-test/suite/funcs_1/r/storedproc.result @@ -2088,9 +2088,11 @@ SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'cursor() SELECT * from t1 where f2=f1' at line 1 CREATE PROCEDURE database() -SELECT * from t1 where f2=f1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'database() -SELECT * from t1 where f2=f1' at line 1 +SELECT 1; +CALL database(); +1 +1 +DROP PROCEDURE database; CREATE PROCEDURE databases() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'databases() @@ -2350,6 +2352,12 @@ CREATE PROCEDURE join() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'join() SELECT * from t1 where f2=f1' at line 1 +CREATE PROCEDURE json_table() +SELECT 1; +CALL json_table(); +1 +1 +DROP PROCEDURE json_table; CREATE PROCEDURE key() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key() @@ -2470,6 +2478,12 @@ CREATE PROCEDURE natural() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'natural() SELECT * from t1 where f2=f1' at line 1 +CREATE PROCEDURE nested() +SELECT 1; +CALL nested(); +1 +1 +DROP PROCEDURE nested; CREATE PROCEDURE not() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'not() @@ -2509,6 +2523,12 @@ CREATE PROCEDURE order() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'order() SELECT * from t1 where f2=f1' at line 1 +CREATE PROCEDURE ordinality() +SELECT 1; +CALL ordinality; +1 +1 +DROP PROCEDURE ordinality; CREATE PROCEDURE out() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'out() @@ -2521,6 +2541,12 @@ CREATE PROCEDURE outfile() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'outfile() SELECT * from t1 where f2=f1' at line 1 +CREATE PROCEDURE path() +SELECT 1; +CALL path(); +1 +1 +DROP PROCEDURE path; CREATE PROCEDURE precision() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'precision() @@ -2602,9 +2628,11 @@ SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'rlike() SELECT * from t1 where f2=f1' at line 1 CREATE PROCEDURE schema() -SELECT * from t1 where f2=f1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'schema() -SELECT * from t1 where f2=f1' at line 1 +SELECT 1; +CALL schema(); +1 +1 +DROP PROCEDURE schema; CREATE PROCEDURE schemas() SELECT * from t1 where f2=f1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'schemas() @@ -4204,9 +4232,6 @@ CREATE PROCEDURE sp1() database:BEGIN SELECT @x; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'database:BEGIN -SELECT @x; -END' at line 2 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() databases:BEGIN @@ -4737,6 +4762,11 @@ SELECT @x; END' at line 2 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() +json_table:BEGIN +SELECT @x; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() key:BEGIN SELECT @x; END// @@ -4977,6 +5007,11 @@ SELECT @x; END' at line 2 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() +nested:BEGIN +SELECT @x; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() not:BEGIN SELECT @x; END// @@ -5057,6 +5092,11 @@ SELECT @x; END' at line 2 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() +ordinality:BEGIN +SELECT @x; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() out:BEGIN SELECT @x; END// @@ -5081,6 +5121,11 @@ SELECT @x; END' at line 2 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() +path:BEGIN +SELECT @x; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() precision:BEGIN SELECT @x; END// @@ -5253,9 +5298,6 @@ CREATE PROCEDURE sp1() schema:BEGIN SELECT @x; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'schema:BEGIN -SELECT @x; -END' at line 2 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() schemas:BEGIN @@ -7811,8 +7853,6 @@ CREATE PROCEDURE sp1() BEGIN declare database char; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'database char; -END' at line 3 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() BEGIN @@ -8278,6 +8318,11 @@ END' at line 3 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() BEGIN +declare json_table char; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() +BEGIN declare key char; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key char; @@ -8488,6 +8533,11 @@ END' at line 3 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() BEGIN +declare nested char; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() +BEGIN declare not char; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'not char; @@ -8556,6 +8606,11 @@ END' at line 3 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() BEGIN +declare ordinality char; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() +BEGIN declare out char; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'out char; @@ -8577,6 +8632,11 @@ END' at line 3 DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1() BEGIN +declare path char; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1() +BEGIN declare precision char; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'precision char; @@ -8745,11 +8805,7 @@ CREATE PROCEDURE sp1() BEGIN declare schema char; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'schema char; -END' at line 3 DROP PROCEDURE IF EXISTS sp1; -Warnings: -Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1() BEGIN declare schemas char; @@ -9704,11 +9760,7 @@ BEGIN declare database condition for sqlstate '02000'; declare exit handler for database set @var2 = 1; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'database condition for sqlstate '02000'; -declare exit handler for database se...' at line 3 DROP PROCEDURE IF EXISTS sp1; -Warnings: -Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN declare databases condition for sqlstate '02000'; @@ -10372,6 +10424,12 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare json_table condition for sqlstate '02000'; +declare exit handler for json_table set @var2 = 1; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1( ) +BEGIN declare key condition for sqlstate '02000'; declare exit handler for key set @var2 = 1; END// @@ -10672,6 +10730,12 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare nested condition for sqlstate '02000'; +declare exit handler for nested set @var2 = 1; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1( ) +BEGIN declare not condition for sqlstate '02000'; declare exit handler for not set @var2 = 1; END// @@ -10768,6 +10832,12 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare ordinality condition for sqlstate '02000'; +declare exit handler for ordinality set @var2 = 1; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1( ) +BEGIN declare out condition for sqlstate '02000'; declare exit handler for out set @var2 = 1; END// @@ -10798,6 +10868,12 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare path condition for sqlstate '02000'; +declare exit handler for path set @var2 = 1; +END// +DROP PROCEDURE sp1; +CREATE PROCEDURE sp1( ) +BEGIN declare precision condition for sqlstate '02000'; declare exit handler for precision set @var2 = 1; END// @@ -11021,11 +11097,7 @@ BEGIN declare schema condition for sqlstate '02000'; declare exit handler for schema set @var2 = 1; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'schema condition for sqlstate '02000'; -declare exit handler for schema set @v...' at line 3 DROP PROCEDURE IF EXISTS sp1; -Warnings: -Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN declare schemas condition for sqlstate '02000'; @@ -11974,8 +12046,7 @@ CREATE PROCEDURE sp1( ) BEGIN declare database handler for sqlstate '02000' set @var2 = 1; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'database handler for sqlstate '02000' set @var2 = 1; -END' at line 3 +ERROR HY000: Unknown data type: 'handler' DROP PROCEDURE IF EXISTS sp1; Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist @@ -12571,6 +12642,11 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare json_table handler for sqlstate '02000' set @var2 = 1; +END// +ERROR HY000: Unknown data type: 'handler' +CREATE PROCEDURE sp1( ) +BEGIN declare key handler for sqlstate '02000' set @var2 = 1; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key handler for sqlstate '02000' set @var2 = 1; @@ -12841,6 +12917,11 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare nested handler for sqlstate '02000' set @var2 = 1; +END// +ERROR HY000: Unknown data type: 'handler' +CREATE PROCEDURE sp1( ) +BEGIN declare not handler for sqlstate '02000' set @var2 = 1; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'not handler for sqlstate '02000' set @var2 = 1; @@ -12930,6 +13011,11 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare ordinality handler for sqlstate '02000' set @var2 = 1; +END// +ERROR HY000: Unknown data type: 'handler' +CREATE PROCEDURE sp1( ) +BEGIN declare out handler for sqlstate '02000' set @var2 = 1; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'out handler for sqlstate '02000' set @var2 = 1; @@ -12957,6 +13043,11 @@ Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist CREATE PROCEDURE sp1( ) BEGIN +declare path handler for sqlstate '02000' set @var2 = 1; +END// +ERROR HY000: Unknown data type: 'handler' +CREATE PROCEDURE sp1( ) +BEGIN declare precision handler for sqlstate '02000' set @var2 = 1; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'precision handler for sqlstate '02000' set @var2 = 1; @@ -13164,8 +13255,7 @@ CREATE PROCEDURE sp1( ) BEGIN declare schema handler for sqlstate '02000' set @var2 = 1; END// -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'schema handler for sqlstate '02000' set @var2 = 1; -END' at line 3 +ERROR HY000: Unknown data type: 'handler' DROP PROCEDURE IF EXISTS sp1; Warnings: Note 1305 PROCEDURE db_storedproc.sp1 does not exist diff --git a/mysql-test/suite/funcs_1/t/storedproc.test b/mysql-test/suite/funcs_1/t/storedproc.test index 8712919e430..e9c00742f01 100644 --- a/mysql-test/suite/funcs_1/t/storedproc.test +++ b/mysql-test/suite/funcs_1/t/storedproc.test @@ -1102,9 +1102,11 @@ CREATE PROCEDURE current_user() CREATE PROCEDURE cursor() SELECT * from t1 where f2=f1; ---error ER_PARSE_ERROR CREATE PROCEDURE database() - SELECT * from t1 where f2=f1; + SELECT 1; + +CALL database(); +DROP PROCEDURE database; --error ER_PARSE_ERROR CREATE PROCEDURE databases() @@ -1367,6 +1369,12 @@ CREATE PROCEDURE iterate() CREATE PROCEDURE join() SELECT * from t1 where f2=f1; +CREATE PROCEDURE json_table() + SELECT 1; + +CALL json_table(); +DROP PROCEDURE json_table; + --error ER_PARSE_ERROR CREATE PROCEDURE key() SELECT * from t1 where f2=f1; @@ -1487,6 +1495,13 @@ CREATE PROCEDURE modifies() CREATE PROCEDURE natural() SELECT * from t1 where f2=f1; +CREATE PROCEDURE nested() + SELECT 1; + +CALL nested(); + +DROP PROCEDURE nested; + --error ER_PARSE_ERROR CREATE PROCEDURE not() SELECT * from t1 where f2=f1; @@ -1527,6 +1542,13 @@ CREATE PROCEDURE or() CREATE PROCEDURE order() SELECT * from t1 where f2=f1; +CREATE PROCEDURE ordinality() + SELECT 1; + +CALL ordinality; + +DROP PROCEDURE ordinality; + --error ER_PARSE_ERROR CREATE PROCEDURE out() SELECT * from t1 where f2=f1; @@ -1539,6 +1561,13 @@ CREATE PROCEDURE outer() CREATE PROCEDURE outfile() SELECT * from t1 where f2=f1; +CREATE PROCEDURE path() + SELECT 1; + +CALL path(); + +DROP PROCEDURE path; + --error ER_PARSE_ERROR CREATE PROCEDURE precision() SELECT * from t1 where f2=f1; @@ -1619,9 +1648,11 @@ CREATE PROCEDURE right() CREATE PROCEDURE rlike() SELECT * from t1 where f2=f1; ---error ER_PARSE_ERROR CREATE PROCEDURE schema() - SELECT * from t1 where f2=f1; + SELECT 1; + +CALL schema(); +DROP PROCEDURE schema; --error ER_PARSE_ERROR CREATE PROCEDURE schemas() @@ -3481,7 +3512,7 @@ DROP PROCEDURE IF EXISTS sp1; --enable_warnings delimiter //; ---error ER_PARSE_ERROR + CREATE PROCEDURE sp1() database:BEGIN SELECT @x; @@ -4284,6 +4315,15 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; +CREATE PROCEDURE sp1() + json_table:BEGIN + SELECT @x; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -4644,6 +4684,16 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; + +CREATE PROCEDURE sp1() + nested:BEGIN + SELECT @x; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -4765,6 +4815,16 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; + +CREATE PROCEDURE sp1() + ordinality:BEGIN + SELECT @x; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -4801,6 +4861,16 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; + +CREATE PROCEDURE sp1() + path:BEGIN + SELECT @x; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -5066,7 +5136,7 @@ DROP PROCEDURE IF EXISTS sp1; --enable_warnings delimiter //; ---error ER_PARSE_ERROR + CREATE PROCEDURE sp1() schema:BEGIN SELECT @x; @@ -8938,7 +9008,7 @@ DROP PROCEDURE IF EXISTS sp1; --enable_warnings delimiter //; ---error ER_PARSE_ERROR + CREATE PROCEDURE sp1() BEGIN declare database char; @@ -9736,11 +9806,20 @@ BEGIN declare join char; END// delimiter ;// - --disable_warnings DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; + +CREATE PROCEDURE sp1() +BEGIN + declare json_table char; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -10101,6 +10180,16 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; + +CREATE PROCEDURE sp1() +BEGIN + declare nested char; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -10220,6 +10309,16 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; + +CREATE PROCEDURE sp1() +BEGIN + declare ordinality char; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -10256,6 +10355,16 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; --enable_warnings +delimiter //; + +CREATE PROCEDURE sp1() +BEGIN + declare path char; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1() @@ -10506,7 +10615,7 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; delimiter //; ---error ER_PARSE_ERROR + CREATE PROCEDURE sp1() BEGIN declare schema char; @@ -11624,7 +11733,7 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; delimiter //; ---error ER_PARSE_ERROR + CREATE PROCEDURE sp1( ) BEGIN declare database condition for sqlstate '02000'; @@ -12360,6 +12469,17 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; + +CREATE PROCEDURE sp1( ) +BEGIN + declare json_table condition for sqlstate '02000'; + declare exit handler for json_table set @var2 = 1; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -12690,6 +12810,17 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; + +CREATE PROCEDURE sp1( ) +BEGIN + declare nested condition for sqlstate '02000'; + declare exit handler for nested set @var2 = 1; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -12799,6 +12930,17 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; + +CREATE PROCEDURE sp1( ) +BEGIN + declare ordinality condition for sqlstate '02000'; + declare exit handler for ordinality set @var2 = 1; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -12832,6 +12974,17 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; + +CREATE PROCEDURE sp1( ) +BEGIN + declare path condition for sqlstate '02000'; + declare exit handler for path set @var2 = 1; +END// +delimiter ;// + +DROP PROCEDURE sp1; + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -13075,7 +13228,7 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; delimiter //; ---error ER_PARSE_ERROR + CREATE PROCEDURE sp1( ) BEGIN declare schema condition for sqlstate '02000'; @@ -14181,7 +14334,7 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; delimiter //; ---error ER_PARSE_ERROR + CREATE PROCEDURE sp1( ) BEGIN declare database handler for sqlstate '02000' set @var2 = 1; @@ -14850,6 +15003,14 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; +--error ER_UNKNOWN_DATA_TYPE +CREATE PROCEDURE sp1( ) +BEGIN + declare json_table handler for sqlstate '02000' set @var2 = 1; +END// +delimiter ;// + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -15150,6 +15311,14 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; +--error ER_UNKNOWN_DATA_TYPE +CREATE PROCEDURE sp1( ) +BEGIN + declare nested handler for sqlstate '02000' set @var2 = 1; +END// +delimiter ;// + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -15250,6 +15419,14 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; +--error ER_UNKNOWN_DATA_TYPE +CREATE PROCEDURE sp1( ) +BEGIN + declare ordinality handler for sqlstate '02000' set @var2 = 1; +END// +delimiter ;// + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -15280,6 +15457,14 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; +delimiter //; +--error ER_UNKNOWN_DATA_TYPE +CREATE PROCEDURE sp1( ) +BEGIN + declare path handler for sqlstate '02000' set @var2 = 1; +END// +delimiter ;// + delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp1( ) @@ -15511,7 +15696,7 @@ delimiter ;// DROP PROCEDURE IF EXISTS sp1; delimiter //; ---error ER_PARSE_ERROR +--error ER_UNKNOWN_DATA_TYPE CREATE PROCEDURE sp1( ) BEGIN declare schema handler for sqlstate '02000' set @var2 = 1; diff --git a/mysql-test/suite/perfschema/r/digest_view.result b/mysql-test/suite/perfschema/r/digest_view.result index f3b5d9edcaa..cbaf9469829 100644 --- a/mysql-test/suite/perfschema/r/digest_view.result +++ b/mysql-test/suite/perfschema/r/digest_view.result @@ -191,17 +191,17 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY DIGEST_TEXT; SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR -test 6792f631a33c9aa30f74fc4a1ac00d0d EXPLAIN SELECT * FROM `test` . `v1` 1 -test 1a904f6e400d36fc3277347dc3dd7e3b EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1 -test 84b4a595b190b7b2be65930719a5f217 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1 -test c2fbbef6771c0d94bc0bda68b083c2ee EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1 -test 89124df2148819b870c1d648f748b1ad EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1 -test 02270358998b539b9b11f709b372eda9 SELECT * FROM `test` . `v1` 1 -test e42e0a8f9dd70f815fd3b1323ae4d07d SELECT * FROM `test` . `v1` WHERE `a` = ? 1 -test f549d4607e65f96ae2bc4dc4f70965dd SELECT * FROM `test` . `v1` WHERE `b` > ? 1 -test d0ca89f87d46b19d6823e9c3d8fcc4f3 SELECT `a` , `b` FROM `test` . `v1` 1 -test 3599e7d908d651cd2b3410656f0a9a85 SELECT `b` , `a` FROM `test` . `v1` 1 -test 579dc8800f4005f131faf0202bfd383f TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 +test 370e7bef18915f6611ac6d260774b983 EXPLAIN SELECT * FROM `test` . `v1` 1 +test 234d37a98244d9c8e7ddc95d8d615b67 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1 +test 3dbb0324b7aa42191a45415438f0664b EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1 +test c4a754140ab2b645514868c727428aa0 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1 +test 534e1e8b3fdd54ac7950a9c0c049d67b EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1 +test 6b928d386834bf77fb56d6917a66b3b3 SELECT * FROM `test` . `v1` 1 +test 914e5e0b02604c846266f1941ca5c99c SELECT * FROM `test` . `v1` WHERE `a` = ? 1 +test e037e9baeb863981ceed07178b82d85c SELECT * FROM `test` . `v1` WHERE `b` > ? 1 +test 1e4dbc9041d1c2c6ef0aee7bb10a9712 SELECT `a` , `b` FROM `test` . `v1` 1 +test ce9abb5b3de1de61ca0c7bed9bd8e268 SELECT `b` , `a` FROM `test` . `v1` 1 +test 8117308957580606865e284265d48615 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 DROP TABLE test.v1; CREATE VIEW test.v1 AS SELECT * FROM test.t1; EXPLAIN SELECT * from test.v1; @@ -248,19 +248,19 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY DIGEST_TEXT; SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR -test 1d9b60541940c07a0731da3a7e4b3710 CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1 -test c3a18ebfa01b069ce0cbcf1d3c3a28fd DROP TABLE `test` . `v1` 1 -test 6792f631a33c9aa30f74fc4a1ac00d0d EXPLAIN SELECT * FROM `test` . `v1` 2 -test 1a904f6e400d36fc3277347dc3dd7e3b EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2 -test 84b4a595b190b7b2be65930719a5f217 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2 -test c2fbbef6771c0d94bc0bda68b083c2ee EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2 -test 89124df2148819b870c1d648f748b1ad EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2 -test 02270358998b539b9b11f709b372eda9 SELECT * FROM `test` . `v1` 2 -test e42e0a8f9dd70f815fd3b1323ae4d07d SELECT * FROM `test` . `v1` WHERE `a` = ? 2 -test f549d4607e65f96ae2bc4dc4f70965dd SELECT * FROM `test` . `v1` WHERE `b` > ? 2 -test 279f05780dfbf44c1b9c444c4a3d7f81 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1 -test d0ca89f87d46b19d6823e9c3d8fcc4f3 SELECT `a` , `b` FROM `test` . `v1` 2 -test 3599e7d908d651cd2b3410656f0a9a85 SELECT `b` , `a` FROM `test` . `v1` 2 -test 579dc8800f4005f131faf0202bfd383f TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 +test aacd39adbd408fe1250208d032ce0bed CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1 +test b7905ad078429428effa41db5d58c43e DROP TABLE `test` . `v1` 1 +test 370e7bef18915f6611ac6d260774b983 EXPLAIN SELECT * FROM `test` . `v1` 2 +test 234d37a98244d9c8e7ddc95d8d615b67 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2 +test 3dbb0324b7aa42191a45415438f0664b EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2 +test c4a754140ab2b645514868c727428aa0 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2 +test 534e1e8b3fdd54ac7950a9c0c049d67b EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2 +test 6b928d386834bf77fb56d6917a66b3b3 SELECT * FROM `test` . `v1` 2 +test 914e5e0b02604c846266f1941ca5c99c SELECT * FROM `test` . `v1` WHERE `a` = ? 2 +test e037e9baeb863981ceed07178b82d85c SELECT * FROM `test` . `v1` WHERE `b` > ? 2 +test ac0e7e062fb2eecae26f4e432cde3dd3 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1 +test 1e4dbc9041d1c2c6ef0aee7bb10a9712 SELECT `a` , `b` FROM `test` . `v1` 2 +test ce9abb5b3de1de61ca0c7bed9bd8e268 SELECT `b` , `a` FROM `test` . `v1` 2 +test 8117308957580606865e284265d48615 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 DROP VIEW test.v1; DROP TABLE test.t1; diff --git a/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result b/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result index 3cca1764ec4..c2f2547ed49 100644 --- a/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result +++ b/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result @@ -8,5 +8,5 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 #################################### SELECT event_name, digest, digest_text, sql_text FROM events_statements_history_long; event_name digest digest_text sql_text -statement/sql/select bb82f2829bcdfd9ac1e53f7b27829d36 SELECT ? + ? + SELECT ... -statement/sql/truncate 86a7d96b41a68b8dfb6c94888bd3bb76 TRUNCATE TABLE truncat... +statement/sql/select 3ff8cd05d2991a9ac9b182801987d61e SELECT ? + ? + SELECT ... +statement/sql/truncate eddd22a5c210f96a5160acbb5d7563b3 TRUNCATE TABLE truncat... diff --git a/sql/item_create.cc b/sql/item_create.cc index 794e65a31a6..f15b343b127 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -127,6 +127,19 @@ protected: }; +class Create_func_addmonths : public Create_func_arg2 +{ +public: + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); + + static Create_func_addmonths s_singleton; + +protected: + Create_func_addmonths() = default; + virtual ~Create_func_addmonths() = default; +}; + + class Create_func_aes_encrypt : public Create_func_arg2 { public: @@ -258,6 +271,19 @@ protected: }; +class Create_func_collation : public Create_func_arg1 +{ +public: + virtual Item *create_1_arg(THD *thd, Item *arg1); + + static Create_func_collation s_singleton; + +protected: + Create_func_collation() = default; + virtual ~Create_func_collation() = default; +}; + + class Create_func_chr : public Create_func_arg1 { public: @@ -345,6 +371,20 @@ protected: }; +class Create_func_coalesce : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); + + static Create_func_coalesce s_singleton; + +protected: + Create_func_coalesce() = default; + virtual ~Create_func_coalesce() = default; +}; + + class Create_func_compress : public Create_func_arg1 { public: @@ -472,6 +512,19 @@ protected: }; +class Create_func_database : public Create_func_arg0 +{ +public: + virtual Item *create_builder(THD *thd); + + static Create_func_database s_singleton; + +protected: + Create_func_database() = default; + virtual ~Create_func_database() = default; +}; + + class Create_func_nvl2 : public Create_func_arg3 { public: @@ -563,6 +616,22 @@ protected: }; +class Create_func_date_format : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); + + static Create_func_date_format s_singleton; + +protected: + Create_func_date_format() = default; + virtual ~Create_func_date_format() = default; +}; + + + + class Create_func_dayname : public Create_func_arg1 { public: @@ -1382,6 +1451,31 @@ protected: virtual ~Create_func_octet_length() = default; }; +class Create_func_old_password : public Create_func_arg1 +{ +public: + virtual Item *create_1_arg(THD *thd, Item *arg1); + + static Create_func_old_password s_singleton; + +protected: + Create_func_old_password() = default; + virtual ~Create_func_old_password() = default; +}; + + +class Create_func_password : public Create_func_arg1 +{ +public: + virtual Item *create_1_arg(THD *thd, Item *arg1); + + static Create_func_password s_singleton; + +protected: + Create_func_password() = default; + virtual ~Create_func_password() = default; +}; + #ifndef DBUG_OFF class Create_func_like_range_min : public Create_func_arg2 @@ -1630,6 +1724,32 @@ protected: }; +class Create_func_microsecond : public Create_func_arg1 +{ +public: + virtual Item *create_1_arg(THD *thd, Item *arg1); + + static Create_func_microsecond s_singleton; + +protected: + Create_func_microsecond() = default; + virtual ~Create_func_microsecond() = default; +}; + + +class Create_func_mod : public Create_func_arg2 +{ +public: + virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2); + + static Create_func_mod s_singleton; + +protected: + Create_func_mod() = default; + virtual ~Create_func_mod() = default; +}; + + class Create_func_monthname : public Create_func_arg1 { public: @@ -1747,6 +1867,19 @@ protected: }; +class Create_func_quarter : public Create_func_arg1 +{ +public: + virtual Item *create_1_arg(THD *thd, Item *arg1); + + static Create_func_quarter s_singleton; + +protected: + Create_func_quarter() = default; + virtual ~Create_func_quarter() = default; +}; + + class Create_func_quote : public Create_func_arg1 { public: @@ -1888,6 +2021,19 @@ protected: }; +class Create_func_row_count : public Create_func_arg0 +{ +public: + virtual Item *create_builder(THD *thd); + + static Create_func_row_count s_singleton; + +protected: + Create_func_row_count() = default; + virtual ~Create_func_row_count() = default; +}; + + class Create_func_rpad : public Create_native_func { public: @@ -2349,6 +2495,20 @@ protected: }; +class Create_func_week : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); + + static Create_func_week s_singleton; + +protected: + Create_func_week() = default; + virtual ~Create_func_week() = default; +}; + + class Create_func_weekday : public Create_func_arg1 { public: @@ -2828,6 +2988,16 @@ Create_func_addtime::create_2_arg(THD *thd, Item *arg1, Item *arg2) } +Create_func_addmonths Create_func_addmonths::s_singleton; + +Item* +Create_func_addmonths::create_2_arg(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) + Item_date_add_interval(thd, arg1, arg2, INTERVAL_MONTH, false); +} + + Create_func_aes_encrypt Create_func_aes_encrypt::s_singleton; Item* @@ -2957,6 +3127,15 @@ Create_func_ceiling::create_1_arg(THD *thd, Item *arg1) } +Create_func_collation Create_func_collation::s_singleton; + +Item* +Create_func_collation::create_1_arg(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_collation(thd, arg1); +} + + Create_func_chr Create_func_chr::s_singleton; Item* @@ -3017,6 +3196,26 @@ Create_func_dyncol_json::create_1_arg(THD *thd, Item *arg1) return new (thd->mem_root) Item_func_dyncol_json(thd, arg1); } +Create_func_coalesce Create_func_coalesce::s_singleton; + +Item* +Create_func_coalesce::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (unlikely(arg_count < 1)) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + return NULL; + } + + return new (thd->mem_root) Item_func_coalesce(thd, *item_list); +} + Create_func_concat Create_func_concat::s_singleton; Item* @@ -3111,6 +3310,16 @@ Create_func_connection_id::create_builder(THD *thd) } +Create_func_database Create_func_database::s_singleton; + +Item* +Create_func_database::create_builder(THD *thd) +{ + thd->lex->safe_to_cache_query= 0; + return new (thd->mem_root) Item_func_database(thd); +} + + Create_func_nvl2 Create_func_nvl2::s_singleton; Item* @@ -3175,6 +3384,37 @@ Create_func_datediff::create_2_arg(THD *thd, Item *arg1, Item *arg2) return new (thd->mem_root) Item_func_minus(thd, i1, i2); } +Create_func_date_format Create_func_date_format::s_singleton; + +Item* +Create_func_date_format::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + return new (thd->mem_root) Item_func_date_format(thd, param_1, param_2); + } + case 3: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + return new (thd->mem_root) Item_func_date_format(thd, + param_1, param_2, param_3); + } + } + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + return NULL; +} + Create_func_dayname Create_func_dayname::s_singleton; @@ -4289,6 +4529,23 @@ Create_func_length::create_1_arg(THD *thd, Item *arg1) return new (thd->mem_root) Item_func_octet_length(thd, arg1); } +Create_func_old_password Create_func_old_password::s_singleton; + +Item* +Create_func_old_password::create_1_arg(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_password(thd, arg1, + Item_func_password::OLD); +} + +Create_func_password Create_func_password::s_singleton; + +Item* +Create_func_password::create_1_arg(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_password(thd, arg1); +} + Create_func_octet_length Create_func_octet_length::s_singleton; Item* @@ -4657,6 +4914,24 @@ Create_func_md5::create_1_arg(THD *thd, Item *arg1) } +Create_func_microsecond Create_func_microsecond::s_singleton; + +Item* +Create_func_microsecond::create_1_arg(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_microsecond(thd, arg1); +} + + +Create_func_mod Create_func_mod::s_singleton; + +Item* +Create_func_mod::create_2_arg(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_mod(thd, arg1, arg2); +} + + Create_func_monthname Create_func_monthname::s_singleton; Item* @@ -4759,6 +5034,15 @@ Create_func_pow::create_2_arg(THD *thd, Item *arg1, Item *arg2) } +Create_func_quarter Create_func_quarter::s_singleton; + +Item* +Create_func_quarter::create_1_arg(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_quarter(thd, arg1); +} + + Create_func_quote Create_func_quote::s_singleton; Item* @@ -4934,6 +5218,17 @@ Create_func_round::create_native(THD *thd, const LEX_CSTRING *name, } +Create_func_row_count Create_func_row_count::s_singleton; + +Item* +Create_func_row_count::create_builder(THD *thd) +{ + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); + thd->lex->safe_to_cache_query= 0; + return new (thd->mem_root) Item_func_row_count(thd); +} + + Create_func_rpad Create_func_rpad::s_singleton; Create_func_rpad_oracle Create_func_rpad_oracle::s_singleton; @@ -5391,6 +5686,43 @@ Create_func_version::create_builder(THD *thd) } +Create_func_week Create_func_week::s_singleton; + +Item* +Create_func_week::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) +{ + Item* func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_week(thd, param_1); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_week(thd, param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + break; + } + } + + return func; +} + + Create_func_weekday Create_func_weekday::s_singleton; Item* @@ -5541,6 +5873,7 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("ABS") }, BUILDER(Create_func_abs)}, { { STRING_WITH_LEN("ACOS") }, BUILDER(Create_func_acos)}, { { STRING_WITH_LEN("ADDTIME") }, BUILDER(Create_func_addtime)}, + { { STRING_WITH_LEN("ADD_MONTHS") }, BUILDER(Create_func_addmonths)}, { { STRING_WITH_LEN("AES_DECRYPT") }, BUILDER(Create_func_aes_decrypt)}, { { STRING_WITH_LEN("AES_ENCRYPT") }, BUILDER(Create_func_aes_encrypt)}, { { STRING_WITH_LEN("ASIN") }, BUILDER(Create_func_asin)}, @@ -5556,7 +5889,9 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("CHARACTER_LENGTH") }, BUILDER(Create_func_char_length)}, { { STRING_WITH_LEN("CHAR_LENGTH") }, BUILDER(Create_func_char_length)}, { { STRING_WITH_LEN("CHR") }, BUILDER(Create_func_chr)}, + { { STRING_WITH_LEN("COALESCE") }, BUILDER(Create_func_coalesce)}, { { STRING_WITH_LEN("COERCIBILITY") }, BUILDER(Create_func_coercibility)}, + { { STRING_WITH_LEN("COLLATION") }, BUILDER(Create_func_collation)}, { { STRING_WITH_LEN("COLUMN_CHECK") }, BUILDER(Create_func_dyncol_check)}, { { STRING_WITH_LEN("COLUMN_EXISTS") }, BUILDER(Create_func_dyncol_exists)}, { { STRING_WITH_LEN("COLUMN_LIST") }, BUILDER(Create_func_dyncol_list)}, @@ -5571,7 +5906,9 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("COS") }, BUILDER(Create_func_cos)}, { { STRING_WITH_LEN("COT") }, BUILDER(Create_func_cot)}, { { STRING_WITH_LEN("CRC32") }, BUILDER(Create_func_crc32)}, + { { STRING_WITH_LEN("DATABASE") }, BUILDER(Create_func_database)}, { { STRING_WITH_LEN("DATEDIFF") }, BUILDER(Create_func_datediff)}, + { { STRING_WITH_LEN("DATE_FORMAT") }, BUILDER(Create_func_date_format)}, { { STRING_WITH_LEN("DAYNAME") }, BUILDER(Create_func_dayname)}, { { STRING_WITH_LEN("DAYOFMONTH") }, BUILDER(Create_func_dayofmonth)}, { { STRING_WITH_LEN("DAYOFWEEK") }, BUILDER(Create_func_dayofweek)}, @@ -5660,6 +5997,8 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("MASTER_GTID_WAIT") }, BUILDER(Create_func_master_gtid_wait)}, { { STRING_WITH_LEN("MASTER_POS_WAIT") }, BUILDER(Create_func_master_pos_wait)}, { { STRING_WITH_LEN("MD5") }, BUILDER(Create_func_md5)}, + { { STRING_WITH_LEN("MICROSECOND") }, BUILDER(Create_func_microsecond)}, + { { STRING_WITH_LEN("MOD") }, BUILDER(Create_func_mod)}, { { STRING_WITH_LEN("MONTHNAME") }, BUILDER(Create_func_monthname)}, { { STRING_WITH_LEN("NAME_CONST") }, BUILDER(Create_func_name_const)}, { { STRING_WITH_LEN("NVL") }, BUILDER(Create_func_ifnull)}, @@ -5667,12 +6006,15 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("NULLIF") }, BUILDER(Create_func_nullif)}, { { STRING_WITH_LEN("OCT") }, BUILDER(Create_func_oct)}, { { STRING_WITH_LEN("OCTET_LENGTH") }, BUILDER(Create_func_octet_length)}, + { { STRING_WITH_LEN("OLD_PASSWORD") }, BUILDER(Create_func_old_password)}, { { STRING_WITH_LEN("ORD") }, BUILDER(Create_func_ord)}, + { { STRING_WITH_LEN("PASSWORD") }, BUILDER(Create_func_password)}, { { STRING_WITH_LEN("PERIOD_ADD") }, BUILDER(Create_func_period_add)}, { { STRING_WITH_LEN("PERIOD_DIFF") }, BUILDER(Create_func_period_diff)}, { { STRING_WITH_LEN("PI") }, BUILDER(Create_func_pi)}, { { STRING_WITH_LEN("POW") }, BUILDER(Create_func_pow)}, { { STRING_WITH_LEN("POWER") }, BUILDER(Create_func_pow)}, + { { STRING_WITH_LEN("QUARTER") }, BUILDER(Create_func_quarter)}, { { STRING_WITH_LEN("QUOTE") }, BUILDER(Create_func_quote)}, { { STRING_WITH_LEN("REGEXP_INSTR") }, BUILDER(Create_func_regexp_instr)}, { { STRING_WITH_LEN("REGEXP_REPLACE") }, BUILDER(Create_func_regexp_replace)}, @@ -5686,11 +6028,14 @@ const Native_func_registry func_array[] = BUILDER(Create_func_replace_oracle)}, { { STRING_WITH_LEN("REVERSE") }, BUILDER(Create_func_reverse)}, { { STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)}, + { { STRING_WITH_LEN("ROW_COUNT") }, BUILDER(Create_func_row_count)}, { { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad)}, { { STRING_WITH_LEN("RPAD_ORACLE") }, BUILDER(Create_func_rpad_oracle)}, { { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim)}, { { STRING_WITH_LEN("RTRIM_ORACLE") }, BUILDER(Create_func_rtrim_oracle)}, { { STRING_WITH_LEN("SEC_TO_TIME") }, BUILDER(Create_func_sec_to_time)}, + { { STRING_WITH_LEN("SCHEMA") }, BUILDER(Create_func_database)}, + { { STRING_WITH_LEN("SCHEMAS") }, BUILDER(Create_func_database)}, { { STRING_WITH_LEN("SHA") }, BUILDER(Create_func_sha)}, { { STRING_WITH_LEN("SHA1") }, BUILDER(Create_func_sha)}, { { STRING_WITH_LEN("SHA2") }, BUILDER(Create_func_sha2)}, @@ -5725,6 +6070,7 @@ const Native_func_registry func_array[] = { { STRING_WITH_LEN("UUID") }, BUILDER(Create_func_uuid)}, { { STRING_WITH_LEN("UUID_SHORT") }, BUILDER(Create_func_uuid_short)}, { { STRING_WITH_LEN("VERSION") }, BUILDER(Create_func_version)}, + { { STRING_WITH_LEN("WEEK") }, BUILDER(Create_func_week)}, { { STRING_WITH_LEN("WEEKDAY") }, BUILDER(Create_func_weekday)}, { { STRING_WITH_LEN("WEEKOFYEAR") }, BUILDER(Create_func_weekofyear)}, #ifdef WITH_WSREP diff --git a/sql/lex.h b/sql/lex.h index c2b83e67ded..d6241c50b6a 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -81,7 +81,6 @@ SYMBOL symbols[] = { { "AUTHORS", SYM(AUTHORS_SYM)}, { "AUTO_INCREMENT", SYM(AUTO_INC)}, { "AUTOEXTEND_SIZE", SYM(AUTOEXTEND_SIZE_SYM)}, - { "AUTO", SYM(AUTO_SYM)}, { "AVG", SYM(AVG_SYM)}, { "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)}, { "BACKUP", SYM(BACKUP_SYM)}, @@ -426,7 +425,6 @@ SYMBOL symbols[] = { { "NCHAR", SYM(NCHAR_SYM)}, { "NESTED", SYM(NESTED_SYM)}, { "NEVER", SYM(NEVER_SYM)}, - { "NEW", SYM(NEW_SYM)}, { "NEXT", SYM(NEXT_SYM)}, { "NEXTVAL", SYM(NEXTVAL_SYM)}, { "NO", SYM(NO_SYM)}, @@ -682,7 +680,6 @@ SYMBOL symbols[] = { { "TRUE", SYM(TRUE_SYM)}, { "TRUNCATE", SYM(TRUNCATE_SYM)}, { "TYPE", SYM(TYPE_SYM)}, - { "TYPES", SYM(TYPES_SYM)}, { "UNBOUNDED", SYM(UNBOUNDED_SYM)}, { "UNCOMMITTED", SYM(UNCOMMITTED_SYM)}, { "UNDEFINED", SYM(UNDEFINED_SYM)}, @@ -748,7 +745,6 @@ SYMBOL symbols[] = { SYMBOL sql_functions[] = { { "ADDDATE", SYM(ADDDATE_SYM)}, - { "ADD_MONTHS", SYM(ADD_MONTHS_SYM)}, { "BIT_AND", SYM(BIT_AND)}, { "BIT_OR", SYM(BIT_OR)}, { "BIT_XOR", SYM(BIT_XOR)}, @@ -759,7 +755,6 @@ SYMBOL sql_functions[] = { { "CURTIME", SYM(CURTIME)}, { "DATE_ADD", SYM(DATE_ADD_INTERVAL)}, { "DATE_SUB", SYM(DATE_SUB_INTERVAL)}, - { "DATE_FORMAT", SYM(DATE_FORMAT_SYM)}, { "DENSE_RANK", SYM(DENSE_RANK_SYM)}, { "EXTRACT", SYM(EXTRACT_SYM)}, { "FIRST_VALUE", SYM(FIRST_VALUE_SYM)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 92fd102bc1a..a4e3a4c6531 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -737,7 +737,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token ACTION /* SQL-2003-N */ %token ADMIN_SYM /* SQL-2003-N */ %token ADDDATE_SYM /* MYSQL-FUNC */ -%token ADD_MONTHS_SYM /* Oracle FUNC*/ %token AFTER_SYM /* SQL-2003-N */ %token AGAINST %token AGGREGATE_SYM @@ -750,7 +749,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token AUTHORS_SYM %token AUTOEXTEND_SIZE_SYM %token AUTO_INC -%token AUTO_SYM %token AVG_ROW_LENGTH %token AVG_SYM /* SQL-2003-N */ %token BACKUP_SYM @@ -812,7 +810,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token DATAFILE_SYM %token DATA_SYM /* SQL-2003-N */ %token DATETIME -%token DATE_FORMAT_SYM /* MYSQL-FUNC */ %token DATE_SYM /* SQL-2003-R, Oracle-R, PLSQL-R */ %token DAY_SYM /* SQL-2003-R */ %token DEALLOCATE_SYM /* SQL-2003-R */ @@ -963,7 +960,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token NATIONAL_SYM /* SQL-2003-R */ %token NCHAR_SYM /* SQL-2003-R */ %token NEVER_SYM /* MySQL */ -%token NEW_SYM /* SQL-2003-R */ %token NEXT_SYM /* SQL-2003-N */ %token NEXTVAL_SYM /* PostgreSQL sequence function */ %token NOCACHE_SYM @@ -1126,7 +1122,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token TRIGGERS_SYM %token TRIM_ORACLE %token TRUNCATE_SYM -%token TYPES_SYM %token TYPE_SYM /* SQL-2003-N */ %token UDF_RETURNS_SYM %token UNBOUNDED_SYM /* SQL-2011-N */ @@ -1317,6 +1312,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type IDENT_sys + ident_func ident label_ident sp_decl_ident @@ -1341,6 +1337,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); IDENT_cli ident_cli ident_cli_set_usual_case + ident_cli_func %type ident_sys_alloc @@ -1355,6 +1352,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); keyword_sp_block_section keyword_sp_decl keyword_sp_head + keyword_func_sp_var_and_label + keyword_func_sp_var_not_label keyword_sp_var_and_label keyword_sp_var_not_label keyword_sysvar_name @@ -10411,14 +10410,7 @@ substring_operands_special: discouraged. */ function_call_nonkeyword: - ADD_MONTHS_SYM '(' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5, - INTERVAL_MONTH, 0); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | ADDDATE_SYM '(' expr ',' expr ')' + ADDDATE_SYM '(' expr ',' expr ')' { $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5, INTERVAL_DAY, 0); @@ -10457,18 +10449,6 @@ function_call_nonkeyword: if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | DATE_FORMAT_SYM '(' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | DATE_FORMAT_SYM '(' expr ',' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5, $7); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } | EXTRACT_SYM '(' interval FROM expr ')' { $$=new (thd->mem_root) Item_extract(thd, $3, $5); @@ -10593,13 +10573,6 @@ function_call_nonkeyword: if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | - COLUMN_CHECK_SYM '(' expr ')' - { - $$= new (thd->mem_root) Item_func_dyncol_check(thd, $3); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } | COLUMN_CREATE_SYM '(' dyncall_create_list ')' { @@ -10637,43 +10610,12 @@ function_call_conflict: if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | COALESCE '(' expr_list ')' - { - $$= new (thd->mem_root) Item_func_coalesce(thd, *$3); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | COLLATION_SYM '(' expr ')' - { - $$= new (thd->mem_root) Item_func_collation(thd, $3); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | DATABASE '(' ')' - { - $$= new (thd->mem_root) Item_func_database(thd); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - Lex->safe_to_cache_query=0; - } | IF_SYM '(' expr ',' expr ',' expr ')' { $$= new (thd->mem_root) Item_func_if(thd, $3, $5, $7); if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | FORMAT_SYM '(' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_func_format(thd, $3, $5); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | FORMAT_SYM '(' expr ',' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_func_format(thd, $3, $5, $7); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } /* LAST_VALUE here conflicts with the definition for window functions. We have these 2 separate rules to remove the shift/reduce conflict. */ @@ -10695,25 +10637,12 @@ function_call_conflict: if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | MICROSECOND_SYM '(' expr ')' - { - $$= new (thd->mem_root) Item_func_microsecond(thd, $3); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } | MOD_SYM '(' expr ',' expr ')' { $$= new (thd->mem_root) Item_func_mod(thd, $3, $5); if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | OLD_PASSWORD_SYM '(' expr ')' - { - $$= new (thd->mem_root) - Item_func_password(thd, $3, Item_func_password::OLD); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } | PASSWORD_SYM '(' expr ')' { Item* i1; @@ -10722,12 +10651,6 @@ function_call_conflict: MYSQL_YYABORT; $$= i1; } - | QUARTER_SYM '(' expr ')' - { - $$= new (thd->mem_root) Item_func_quarter(thd, $3); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } | REPEAT_SYM '(' expr ',' expr ')' { $$= new (thd->mem_root) Item_func_repeat(thd, $3, $5); @@ -10740,38 +10663,12 @@ function_call_conflict: make_item_func_replace(thd, $3, $5, $7)))) MYSQL_YYABORT; } - | REVERSE_SYM '(' expr ')' - { - $$= new (thd->mem_root) Item_func_reverse(thd, $3); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | ROW_COUNT_SYM '(' ')' - { - $$= new (thd->mem_root) Item_func_row_count(thd); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); - Lex->safe_to_cache_query= 0; - } | TRUNCATE_SYM '(' expr ',' expr ')' { $$= new (thd->mem_root) Item_func_round(thd, $3, $5, 1); if (unlikely($$ == NULL)) MYSQL_YYABORT; } - | WEEK_SYM '(' expr ')' - { - $$= new (thd->mem_root) Item_func_week(thd, $3); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } - | WEEK_SYM '(' expr ',' expr ')' - { - $$= new (thd->mem_root) Item_func_week(thd, $3, $5); - if (unlikely($$ == NULL)) - MYSQL_YYABORT; - } | WEIGHT_STRING_SYM '(' expr opt_ws_levels ')' { $$= new (thd->mem_root) Item_func_weight_string(thd, $3, 0, 0, $4); @@ -10817,7 +10714,7 @@ function_call_conflict: in sql/item_create.cc */ function_call_generic: - IDENT_sys '(' + ident_func '(' { #ifdef HAVE_DLOPEN udf_func *udf= 0; @@ -15673,6 +15570,22 @@ IDENT_sys: } ; +ident_cli_func: + IDENT + | IDENT_QUOTED + | keyword_func_sp_var_and_label { $$= $1; } + | keyword_func_sp_var_not_label { $$= $1; } + ; + +ident_func: + ident_cli_func + { + if (unlikely(thd->to_ident_sys_alloc(&$$, &$1))) + MYSQL_YYABORT; + } + ; + + TEXT_STRING_sys: TEXT_STRING { @@ -15896,7 +15809,8 @@ non_reserved_keyword_udt: TODO: check if some of them can migrate to keyword_sp_var_and_label. */ keyword_sp_var_not_label: - ASCII_SYM + keyword_func_sp_var_not_label + | ASCII_SYM | BACKUP_SYM | BINLOG_SYM | BYTE_SYM @@ -15904,7 +15818,6 @@ keyword_sp_var_not_label: | CHECKSUM_SYM | CHECKPOINT_SYM | COLUMN_ADD_SYM - | COLUMN_CHECK_SYM | COLUMN_CREATE_SYM | COLUMN_DELETE_SYM | COLUMN_GET_SYM @@ -15916,7 +15829,6 @@ keyword_sp_var_not_label: | EXECUTE_SYM | FLUSH_SYM | FOLLOWING_SYM - | FORMAT_SYM | GET_SYM | HELP_SYM | HOST_SYM @@ -16070,29 +15982,21 @@ keyword_cast_type: ; -/* - These keywords are fine for both SP variable names and SP labels. -*/ -keyword_sp_var_and_label: - ACTION +keyword_func_sp_var_and_label: + ACTION | ACCOUNT_SYM - | ADDDATE_SYM - | ADD_MONTHS_SYM | ADMIN_SYM | AFTER_SYM | AGAINST | AGGREGATE_SYM | ALGORITHM_SYM | ALWAYS_SYM - | ANY_SYM | AT_SYM | ATOMIC_SYM | AUTHORS_SYM | AUTO_INC | AUTOEXTEND_SIZE_SYM - | AUTO_SYM | AVG_ROW_LENGTH - | AVG_SYM | BLOCK_SYM | BODY_MARIADB_SYM | BTREE_SYM @@ -16104,7 +16008,6 @@ keyword_sp_var_and_label: | CLIENT_SYM | CLASS_ORIGIN_SYM | COALESCE - | CODE_SYM | COLLATION_SYM | COLUMN_NAME_SYM | COLUMNS @@ -16130,16 +16033,15 @@ keyword_sp_var_and_label: | CURSOR_NAME_SYM | CYCLE_SYM | DATA_SYM + | DATABASE | DATAFILE_SYM - | DATE_FORMAT_SYM - | DAY_SYM | DEFINER_SYM | DELAY_KEY_WRITE_SYM | DES_KEY_FILE | DIAGNOSTICS_SYM + | DISCARD | DIRECTORY_SYM | DISABLE_SYM - | DISCARD | DISK_SYM | DUMPFILE | DUPLICATE_SYM @@ -16147,6 +16049,11 @@ keyword_sp_var_and_label: | ELSEIF_ORACLE_SYM | ELSIF_MARIADB_SYM | EMPTY_SYM + | EXPIRE_SYM + | EXPORT_SYM + | EXTENDED_SYM + | EXTENT_SIZE_SYM + | ENABLE_SYM | ENDS_SYM | ENGINE_SYM | ENGINES_SYM @@ -16159,29 +16066,21 @@ keyword_sp_var_and_label: | EXCEPTION_MARIADB_SYM | EXCHANGE_SYM | EXPANSION_SYM - | EXPIRE_SYM - | EXPORT_SYM - | EXTENDED_SYM - | EXTENT_SIZE_SYM | FAULTS_SYM | FAST_SYM - | FOUND_SYM - | ENABLE_SYM | FEDERATED_SYM - | FULL | FILE_SYM | FIRST_SYM + | FOUND_SYM + | FULL | GENERAL | GENERATED_SYM - | GET_FORMAT | GRANTS | GOTO_MARIADB_SYM | HASH_SYM | HARD_SYM | HISTORY_SYM | HOSTS_SYM - | HOUR_SYM - | ID_SYM | IDENTIFIED_SYM | IGNORE_SERVER_IDS_SYM | INCREMENT_SYM @@ -16199,9 +16098,7 @@ keyword_sp_var_and_label: | INVISIBLE_SYM | JSON_TABLE_SYM | KEY_BLOCK_SIZE - | LAST_VALUE | LAST_SYM - | LASTVAL_SYM | LEAVES | LESS_SYM | LEVEL_SYM @@ -16243,7 +16140,6 @@ keyword_sp_var_and_label: | MESSAGE_TEXT_SYM | MICROSECOND_SYM | MIGRATE_SYM - | MINUTE_SYM %ifdef MARIADB | MINUS_ORACLE_SYM %endif @@ -16252,7 +16148,6 @@ keyword_sp_var_and_label: | MODIFY_SYM | MODE_SYM | MONITOR_SYM - | MONTH_SYM | MUTEX_SYM | MYSQL_SYM | MYSQL_ERRNO_SYM @@ -16260,8 +16155,6 @@ keyword_sp_var_and_label: | NESTED_SYM | NEVER_SYM | NEXT_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2 - | NEXTVAL_SYM - | NEW_SYM | NOCACHE_SYM | NOCYCLE_SYM | NOMINVALUE_SYM @@ -16277,7 +16170,6 @@ keyword_sp_var_and_label: | ONLINE_SYM | ONLY_SYM | ORDINALITY_SYM - | OVERLAPS_SYM | PACKAGE_MARIADB_SYM | PACK_KEYS_SYM | PAGE_SYM @@ -16309,10 +16201,10 @@ keyword_sp_var_and_label: | REDOFILE_SYM | REDUNDANT_SYM | RELAY - | RELAYLOG_SYM | RELAY_LOG_FILE_SYM | RELAY_LOG_POS_SYM | RELAY_THREAD + | RELAYLOG_SYM | RELOAD | REORGANIZE_SYM | REPEATABLE_SYM @@ -16327,20 +16219,15 @@ keyword_sp_var_and_label: | REVERSE_SYM | ROLLUP_SYM | ROUTINE_SYM + | ROW_COUNT_SYM | ROWCOUNT_SYM | ROWTYPE_MARIADB_SYM - | ROW_COUNT_SYM | ROW_FORMAT_SYM -%ifdef MARIADB - | ROWNUM_SYM -%endif | RTREE_SYM | SCHEDULE_SYM | SCHEMA_NAME_SYM - | SECOND_SYM | SEQUENCE_SYM | SERIALIZABLE_SYM - | SETVAL_SYM | SIMPLE_SYM | SHARE_SYM | SKIP_SYM @@ -16348,7 +16235,6 @@ keyword_sp_var_and_label: | SLOW | SNAPSHOT_SYM | SOFT_SYM - | SOUNDS_SYM | SOURCE_SYM | SQL_CACHE_SYM | SQL_BUFFER_RESULT @@ -16361,7 +16247,6 @@ keyword_sp_var_and_label: | STORAGE_SYM | STRING_SYM | SUBCLASS_ORIGIN_SYM - | SUBDATE_SYM | SUBJECT_SYM | SUBPARTITION_SYM | SUBPARTITIONS_SYM @@ -16369,9 +16254,6 @@ keyword_sp_var_and_label: | SUSPEND_SYM | SWAPS_SYM | SWITCHES_SYM -%ifdef MARIADB - | SYSDATE -%endif | SYSTEM | SYSTEM_TIME_SYM | TABLE_NAME_SYM @@ -16385,10 +16267,6 @@ keyword_sp_var_and_label: | TRANSACTIONAL_SYM | THREADS_SYM | TRIGGERS_SYM - | TRIM_ORACLE - | TIMESTAMP_ADD - | TIMESTAMP_DIFF - | TYPES_SYM | TYPE_SYM | UDF_RETURNS_SYM | UNCOMMITTED_SYM @@ -16397,23 +16275,61 @@ keyword_sp_var_and_label: | UNDOFILE_SYM | UNKNOWN_SYM | UNTIL_SYM - | USER_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2 | USE_FRM | VARIABLES | VERSIONING_SYM | VIEW_SYM | VIRTUAL_SYM | VISIBLE_SYM - | VALUE_SYM | WARNINGS | WAIT_SYM - | WEEK_SYM - | WEIGHT_STRING_SYM | WITHOUT | WORK_SYM | X509_SYM | XML_SYM | VIA_SYM + | WEEK_SYM + ; + +keyword_func_sp_var_not_label: + FORMAT_SYM + | COLUMN_CHECK_SYM + ; +/* + These keywords are fine for both SP variable names and SP labels. +*/ +keyword_sp_var_and_label: + keyword_func_sp_var_and_label + | ADDDATE_SYM + | ANY_SYM + | AVG_SYM + | CODE_SYM + | DAY_SYM + | GET_FORMAT + | HOUR_SYM + | ID_SYM + | LAST_VALUE + | LASTVAL_SYM + | MINUTE_SYM + | MONTH_SYM + | NEXTVAL_SYM + | OVERLAPS_SYM +%ifdef MARIADB + | ROWNUM_SYM +%endif + | SECOND_SYM + | SETVAL_SYM + | SOUNDS_SYM + | SUBDATE_SYM +%ifdef MARIADB + | SYSDATE +%endif + | TRIM_ORACLE + | TIMESTAMP_ADD + | TIMESTAMP_DIFF + | USER_SYM %prec PREC_BELOW_CONTRACTION_TOKEN2 + | VALUE_SYM + | WEIGHT_STRING_SYM ; @@ -16454,7 +16370,6 @@ reserved_keyword_udt_not_param_type: | CURRENT_USER | CURRENT_ROLE | CURTIME - | DATABASE | DATABASES | DATE_ADD_INTERVAL | DATE_SUB_INTERVAL From f738cc9876fee50909a9a5f5740617e95d46cf54 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 24 Nov 2023 13:23:56 +0400 Subject: [PATCH 100/121] MDEV-29095 REGEXP_REPLACE treats empty strings different than REPLACE in ORACLE mode Turning REGEXP_REPLACE into two schema-qualified functions: - mariadb_schema.regexp_replace() - oracle_schema.regexp_replace() Fixing oracle_schema.regexp_replace(subj,pattern,replacement) to treat NULL in "replacement" as an empty string. Adding new classes implementing oracle_schema.regexp_replace(): - Item_func_regexp_replace_oracle - Create_func_regexp_replace_oracle Adding helper methods: - String *Item::val_str_null_to_empty(String *to) - String *Item::val_str_null_to_empty(String *to, bool null_to_empty) and reusing these methods in both Item_func_replace and Item_func_regexp_replace. --- .../compat/oracle/r/func_qualified.result | 79 +++++++++++++++++++ .../oracle/r/func_regexp_replace.result | 34 ++++++++ .../suite/compat/oracle/t/func_qualified.test | 1 + .../compat/oracle/t/func_regexp_replace.test | 26 ++++++ sql/item.h | 13 +++ sql/item_create.cc | 38 ++++++--- sql/item_strfunc.cc | 34 +++----- sql/item_strfunc.h | 40 +++++++++- 8 files changed, 230 insertions(+), 35 deletions(-) create mode 100644 mysql-test/suite/compat/oracle/r/func_regexp_replace.result create mode 100644 mysql-test/suite/compat/oracle/t/func_regexp_replace.test diff --git a/mysql-test/suite/compat/oracle/r/func_qualified.result b/mysql-test/suite/compat/oracle/r/func_qualified.result index f8224b7ce81..4750a625ebd 100644 --- a/mysql-test/suite/compat/oracle/r/func_qualified.result +++ b/mysql-test/suite/compat/oracle/r/func_qualified.result @@ -1772,6 +1772,85 @@ Level Code Message Note 1003 select trim(both ' ' from 'a') AS "oracle_schema.TRIM(BOTH ' ' FROM 'a')" Warnings: Note 1003 select trim(both ' ' from 'a') AS "oracle_schema.TRIM(BOTH ' ' FROM 'a')" +CALL p3('REGEXP_REPLACE(''test'',''t'','''')'); +---------- +sql_mode='' qualifier='' +query +EXPLAIN EXTENDED SELECT REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select regexp_replace('test','t','') AS `REGEXP_REPLACE('test','t','')` +---------- +sql_mode='' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REGEXP_REPLACE('test','t','') +errmsg +ERROR: FUNCTION unknown_schema.REGEXP_REPLACE does not exist +---------- +sql_mode='' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select regexp_replace('test','t','') AS `mariadb_schema.REGEXP_REPLACE('test','t','')` +---------- +sql_mode='' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select regexp_replace('test','t','') AS `maxdb_schema.REGEXP_REPLACE('test','t','')` +---------- +sql_mode='' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select oracle_schema.regexp_replace('test','t','') AS `oracle_schema.REGEXP_REPLACE('test','t','')` +---------- +sql_mode='ORACLE' qualifier='' +query +EXPLAIN EXTENDED SELECT REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select regexp_replace('test','t','') AS "REGEXP_REPLACE('test','t','')" +---------- +sql_mode='ORACLE' qualifier='unknown_schema.' +query +EXPLAIN EXTENDED SELECT unknown_schema.REGEXP_REPLACE('test','t','') +errmsg +ERROR: FUNCTION unknown_schema.REGEXP_REPLACE does not exist +---------- +sql_mode='ORACLE' qualifier='mariadb_schema.' +query +EXPLAIN EXTENDED SELECT mariadb_schema.REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select mariadb_schema.regexp_replace('test','t','') AS "mariadb_schema.REGEXP_REPLACE('test','t','')" +---------- +sql_mode='ORACLE' qualifier='maxdb_schema.' +query +EXPLAIN EXTENDED SELECT maxdb_schema.REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select mariadb_schema.regexp_replace('test','t','') AS "maxdb_schema.REGEXP_REPLACE('test','t','')" +---------- +sql_mode='ORACLE' qualifier='oracle_schema.' +query +EXPLAIN EXTENDED SELECT oracle_schema.REGEXP_REPLACE('test','t','') +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select regexp_replace('test','t','') AS "oracle_schema.REGEXP_REPLACE('test','t','')" +Warnings: +Note 1003 select regexp_replace('test','t','') AS "oracle_schema.REGEXP_REPLACE('test','t','')" CALL p3('CONCAT_OPERATOR_ORACLE(''a'')'); ---------- sql_mode='' qualifier='' diff --git a/mysql-test/suite/compat/oracle/r/func_regexp_replace.result b/mysql-test/suite/compat/oracle/r/func_regexp_replace.result new file mode 100644 index 00000000000..7d0c5f79611 --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/func_regexp_replace.result @@ -0,0 +1,34 @@ +SET sql_mode=ORACLE; +# +# MDEV-29095 REGEXP_REPLACE treats empty strings different than REPLACE in ORACLE mode +# +CREATE TABLE t1 (replacement VARCHAR(10)); +INSERT INTO t1 VALUES (NULL), (''); +SELECT replacement, REGEXP_REPLACE('abba','a',replacement) FROM t1 ORDER BY replacement; +replacement REGEXP_REPLACE('abba','a',replacement) +NULL bb + bb +DROP TABLE t1; +SELECT REGEXP_REPLACE('abba','a',null); +REGEXP_REPLACE('abba','a',null) +bb +EXPLAIN EXTENDED SELECT REPLACE('abba','a',null) ; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select replace('abba','a',NULL) AS "REPLACE('abba','a',null)" +CREATE VIEW v1 AS SELECT REPLACE('abba','a',null) ; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select replace('abba','a',NULL) AS "REPLACE('abba','a',null)" latin1 latin1_swedish_ci +SELECT * FROM v1; +REPLACE('abba','a',null) +bb +SET sql_mode=DEFAULT; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select oracle_schema.replace('abba','a',NULL) AS `REPLACE('abba','a',null)` latin1 latin1_swedish_ci +SELECT * FROM v1; +REPLACE('abba','a',null) +bb +DROP VIEW v1; diff --git a/mysql-test/suite/compat/oracle/t/func_qualified.test b/mysql-test/suite/compat/oracle/t/func_qualified.test index 842015dbbd6..f2c019ec063 100644 --- a/mysql-test/suite/compat/oracle/t/func_qualified.test +++ b/mysql-test/suite/compat/oracle/t/func_qualified.test @@ -165,6 +165,7 @@ CALL p3('TRIM(1,2)'); CALL p3('TRIM(''a'')'); CALL p3('TRIM(BOTH '' '' FROM ''a'')'); +CALL p3('REGEXP_REPLACE(''test'',''t'','''')'); # Deprecated compatibility XXX_ORACLE functions. # These functions are implemented as simple native functions diff --git a/mysql-test/suite/compat/oracle/t/func_regexp_replace.test b/mysql-test/suite/compat/oracle/t/func_regexp_replace.test new file mode 100644 index 00000000000..8841d524c4a --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/func_regexp_replace.test @@ -0,0 +1,26 @@ +SET sql_mode=ORACLE; + +--echo # +--echo # MDEV-29095 REGEXP_REPLACE treats empty strings different than REPLACE in ORACLE mode +--echo # + +#SELECT REGEXP_REPLACE(null,'a','b') ; +#SELECT REGEXP_REPLACE('ab',null,'b') ; +#SELECT REGEXP_REPLACE('ab','a',null) ; +#SELECT REGEXP_REPLACE('ab',null,null) ; + +CREATE TABLE t1 (replacement VARCHAR(10)); +INSERT INTO t1 VALUES (NULL), (''); +SELECT replacement, REGEXP_REPLACE('abba','a',replacement) FROM t1 ORDER BY replacement; +DROP TABLE t1; + +SELECT REGEXP_REPLACE('abba','a',null); +EXPLAIN EXTENDED SELECT REPLACE('abba','a',null) ; + +CREATE VIEW v1 AS SELECT REPLACE('abba','a',null) ; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +SET sql_mode=DEFAULT; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; diff --git a/sql/item.h b/sql/item.h index 4e756f81c3f..3d971230413 100644 --- a/sql/item.h +++ b/sql/item.h @@ -904,6 +904,19 @@ public: expressions with subqueries in the ORDER/GROUP clauses. */ String *val_str() { return val_str(&str_value); } + String *val_str_null_to_empty(String *to) + { + String *res= val_str(to); + if (res) + return res; + to->set_charset(collation.collation); + to->length(0); + return to; + } + String *val_str_null_to_empty(String *to, bool null_to_empty) + { + return null_to_empty ? val_str_null_to_empty(to) : val_str(to); + } virtual Item_func *get_item_func() { return NULL; } const MY_LOCALE *locale_from_val_str(); diff --git a/sql/item_create.cc b/sql/item_create.cc index 43c869c05ef..12d7232f5f6 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2666,7 +2666,10 @@ protected: class Create_func_regexp_replace : public Create_func_arg3 { public: - virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3); + Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) override + { + return new (thd->mem_root) Item_func_regexp_replace(thd, arg1, arg2, arg3); + } static Create_func_regexp_replace s_singleton; @@ -2675,6 +2678,28 @@ protected: virtual ~Create_func_regexp_replace() = default; }; +Create_func_regexp_replace Create_func_regexp_replace::s_singleton; + + +class Create_func_regexp_replace_oracle : public Create_func_arg3 +{ +public: + Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) override + { + return new (thd->mem_root) Item_func_regexp_replace_oracle(thd, arg1, + arg2, arg3); + } + + static Create_func_regexp_replace_oracle s_singleton; + +protected: + Create_func_regexp_replace_oracle() = default; + virtual ~Create_func_regexp_replace_oracle() = default; +}; + +Create_func_regexp_replace_oracle + Create_func_regexp_replace_oracle::s_singleton; + class Create_func_regexp_substr : public Create_func_arg2 { @@ -6464,15 +6489,6 @@ Create_func_regexp_instr::create_2_arg(THD *thd, Item *arg1, Item *arg2) } -Create_func_regexp_replace Create_func_regexp_replace::s_singleton; - -Item* -Create_func_regexp_replace::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) -{ - return new (thd->mem_root) Item_func_regexp_replace(thd, arg1, arg2, arg3); -} - - Create_func_regexp_substr Create_func_regexp_substr::s_singleton; Item* @@ -7616,6 +7632,8 @@ const Native_func_registry func_array_oracle_overrides[] = { { STRING_WITH_LEN("LENGTH") }, BUILDER(Create_func_char_length)}, { { STRING_WITH_LEN("LPAD") }, BUILDER(Create_func_lpad_oracle)}, { { STRING_WITH_LEN("LTRIM") }, BUILDER(Create_func_ltrim_oracle)}, + { { STRING_WITH_LEN("REGEXP_REPLACE") }, + BUILDER(Create_func_regexp_replace_oracle)}, { { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad_oracle)}, { { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim_oracle)}, diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0373d2a94a6..697d4fdf2ea 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1149,8 +1149,7 @@ bool Item_func_reverse::fix_length_and_dec() Fix that this works with binary strings when using USE_MB */ -String *Item_func_replace::val_str_internal(String *str, - String *empty_string_for_null) +String *Item_func_replace::val_str_internal(String *str, bool null_to_empty) { DBUG_ASSERT(fixed == 1); String *res,*res2,*res3; @@ -1168,13 +1167,8 @@ String *Item_func_replace::val_str_internal(String *str, res=args[0]->val_str(str); if (args[0]->null_value) goto null; - res2=args[1]->val_str(&tmp_value); - if (args[1]->null_value) - { - if (!empty_string_for_null) - goto null; - res2= empty_string_for_null; - } + if (!(res2= args[1]->val_str_null_to_empty(&tmp_value, null_to_empty))) + goto null; res->set_charset(collation.collation); #ifdef USE_MB @@ -1191,12 +1185,8 @@ String *Item_func_replace::val_str_internal(String *str, if (binary_cmp && (offset=res->strstr(*res2)) < 0) return res; #endif - if (!(res3=args[2]->val_str(&tmp_value2))) - { - if (!empty_string_for_null) - goto null; - res3= empty_string_for_null; - } + if (!(res3= args[2]->val_str_null_to_empty(&tmp_value2, null_to_empty))) + goto null; from_length= res2->length(); to_length= res3->length(); @@ -1279,7 +1269,7 @@ redo: } while ((offset=res->strstr(*res2,(uint) offset)) >= 0); } - if (empty_string_for_null && !res->length()) + if (null_to_empty && !res->length()) goto null; return res; @@ -1385,20 +1375,22 @@ bool Item_func_regexp_replace::append_replacement(String *str, } -String *Item_func_regexp_replace::val_str(String *str) +String *Item_func_regexp_replace::val_str_internal(String *str, + bool null_to_empty) { DBUG_ASSERT(fixed == 1); char buff0[MAX_FIELD_WIDTH]; char buff2[MAX_FIELD_WIDTH]; String tmp0(buff0,sizeof(buff0),&my_charset_bin); String tmp2(buff2,sizeof(buff2),&my_charset_bin); - String *source= args[0]->val_str(&tmp0); - String *replace= args[2]->val_str(&tmp2); + String *source, *replace; LEX_CSTRING src, rpl; int startoffset= 0; - if ((null_value= (args[0]->null_value || args[2]->null_value || - re.recompile(args[1])))) + if ((null_value= + (!(source= args[0]->val_str(&tmp0)) || + !(replace= args[2]->val_str_null_to_empty(&tmp2, null_to_empty)) || + re.recompile(args[1])))) return (String *) 0; if (!(source= re.convert_if_needed(source, &re.subject_converter)) || diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 826c7f784af..4fe7dd03d9c 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -353,12 +353,13 @@ public: class Item_func_replace :public Item_str_func { String tmp_value,tmp_value2; +protected: + String *val_str_internal(String *str, bool null_to_empty); public: Item_func_replace(THD *thd, Item *org, Item *find, Item *replace): Item_str_func(thd, org, find, replace) {} - String *val_str(String *to) { return val_str_internal(to, NULL); }; + String *val_str(String *to) { return val_str_internal(to, false); }; bool fix_length_and_dec(); - String *val_str_internal(String *str, String *empty_string_for_null); const Schema *schema() const { return &mariadb_schema; } void print(String *str, enum_query_type query_type) { @@ -377,7 +378,7 @@ class Item_func_replace_oracle :public Item_func_replace public: Item_func_replace_oracle(THD *thd, Item *org, Item *find, Item *replace): Item_func_replace(thd, org, find, replace) {} - String *val_str(String *to) { return val_str_internal(to, &tmp_emtpystr); }; + String *val_str(String *to) { return val_str_internal(to, true); }; const Schema *schema() const { return &oracle_schema_ref; } void print(String *str, enum_query_type query_type) { @@ -401,10 +402,18 @@ class Item_func_regexp_replace :public Item_str_func bool append_replacement(String *str, const LEX_CSTRING *source, const LEX_CSTRING *replace); +protected: + String *val_str_internal(String *str, bool null_to_empty); public: Item_func_regexp_replace(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} + const Schema *schema() const { return &mariadb_schema; } + void print(String *str, enum_query_type query_type) + { + print_sql_mode_qualified_name(str, query_type); + print_args_parenthesized(str, query_type); + } void cleanup() { DBUG_ENTER("Item_func_regex::cleanup"); @@ -412,7 +421,10 @@ public: re.cleanup(); DBUG_VOID_RETURN; } - String *val_str(String *str); + String *val_str(String *str) + { + return val_str_internal(str, false); + } bool fix_fields(THD *thd, Item **ref); bool fix_length_and_dec(); const char *func_name() const { return "regexp_replace"; } @@ -420,6 +432,26 @@ public: }; +class Item_func_regexp_replace_oracle: public Item_func_regexp_replace +{ +public: + Item_func_regexp_replace_oracle(THD *thd, Item *a, Item *b, Item *c) + :Item_func_regexp_replace(thd, a, b, c) + {} + const Schema *schema() const { return &oracle_schema_ref; } + bool fix_length_and_dec() + { + bool rc= Item_func_regexp_replace::fix_length_and_dec(); + maybe_null= true; // Empty result is converted to NULL + return rc; + } + String *val_str(String *str) + { + return val_str_internal(str, true); + } +}; + + class Item_func_regexp_substr :public Item_str_func { Regexp_processor_pcre re; From 97fcafb9ece62cd813e2dfe05ba59787229ae04b Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 10 Jan 2024 15:35:25 +0400 Subject: [PATCH 101/121] MDEV-32837 long unique does not work like unique key when using replace write_record() when performing REPLACE has an optimization: - if the unique violation happened in the last unique key, then do UPDATE - otherwise, do DELETE+INSERT This patch changes the way of detecting if this optimization can be applied if the table has long (hash based) unique (i.e. UNIQUE..USING HASH) constraints. Problem: The old condition did not take into account that TABLE_SHARE and TABLE see long uniques differently: - TABLE_SHARE sees as HA_KEY_ALG_LONG_HASH and HA_NOSAME - TABLE sees as usual non-unique indexes So the old condition could erroneously decide that the UPDATE optimization is possible when there are still some unique hash constraints in the table. Fix: - If the current key is a long unique, it now works as follows: UPDATE can be done if the current long unique is the last long unique, and there are no in-engine (normal) uniques. - For in-engine uniques nothing changes, it still works as before: If the current key is an in-engine (normal) unique: UPDATE can be done if it is the last normal unique. --- mysql-test/main/long_unique_bugs.result | 15 +++ mysql-test/main/long_unique_bugs.test | 13 +++ .../long_unique_bugs_no_sp_protocol.result | 95 +++++++++++++++++++ .../main/long_unique_bugs_no_sp_protocol.test | 68 +++++++++++++ sql/sql_insert.cc | 25 ++++- 5 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 mysql-test/main/long_unique_bugs_no_sp_protocol.result create mode 100644 mysql-test/main/long_unique_bugs_no_sp_protocol.test diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index 30ba3d0af9a..81482e68417 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -660,5 +660,20 @@ Table Op Msg_type Msg_text test.t1 check status OK drop table t1; # +# MDEV-32837 long unique does not work like unique key when using replace +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +REPLACE INTO t1 VALUES (3,1,1); +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +REPLACE INTO t1 VALUES (3,2,2); +SELECT * FROM t1; +a b c +3 2 2 +DROP TABLE t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 12367b1deb8..2441dfa59e8 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -642,6 +642,19 @@ insert into t1 values (0); check table t1 extended; drop table t1; + +--echo # +--echo # MDEV-32837 long unique does not work like unique key when using replace +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +REPLACE INTO t1 VALUES (3,1,1); +SELECT * FROM t1 ORDER BY a; +REPLACE INTO t1 VALUES (3,2,2); +SELECT * FROM t1; +DROP TABLE t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/long_unique_bugs_no_sp_protocol.result b/mysql-test/main/long_unique_bugs_no_sp_protocol.result new file mode 100644 index 00000000000..0776a130167 --- /dev/null +++ b/mysql-test/main/long_unique_bugs_no_sp_protocol.result @@ -0,0 +1,95 @@ +# +# Start of 10.5 tests +# +# +# MDEV-32837 long unique does not work like unique key when using replace +# +# +# Normal unique key + long unique key +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_delete 1 +Handler_read_key 2 +Handler_read_rnd 1 +Handler_write 1 +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_delete 1 +Handler_read_key 3 +Handler_read_rnd 2 +Handler_update 1 +Handler_write 1 +SELECT * FROM t1; +a b c +3 2 2 +DROP TABLE t1; +# +# Two long unique keys +# +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY a (a) USING HASH,UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_read_key 3 +Handler_read_rnd 1 +Handler_update 1 +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_delete 1 +Handler_read_key 4 +Handler_read_rnd 2 +Handler_update 1 +SELECT * FROM t1; +a b c +3 2 2 +DROP TABLE t1; +# +# One long unique key +# +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_read_key 1 +Handler_read_rnd 1 +Handler_update 1 +SELECT * FROM t1 ORDER BY a; +a b c +2 2 2 +3 1 1 +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +Variable_name Value +Handler_read_key 1 +Handler_read_rnd 1 +Handler_update 1 +SELECT * FROM t1; +a b c +3 1 1 +3 2 2 +DROP TABLE t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/long_unique_bugs_no_sp_protocol.test b/mysql-test/main/long_unique_bugs_no_sp_protocol.test new file mode 100644 index 00000000000..6bfa6182096 --- /dev/null +++ b/mysql-test/main/long_unique_bugs_no_sp_protocol.test @@ -0,0 +1,68 @@ +if (`SELECT $SP_PROTOCOL > 0`) +{ + --skip Test requires: sp-protocol disabled +} + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-32837 long unique does not work like unique key when using replace +--echo # + +# This test produces different Handler commands in the SHOW STATUS output +# with --sp-protocol. So it's here, in this *.test file with --sp-protocol disabled. + +--echo # +--echo # Normal unique key + long unique key +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1 ORDER BY a; +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # Two long unique keys +--echo # + +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY a (a) USING HASH,UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1 ORDER BY a; +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # One long unique key +--echo # + +CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE KEY `test` (b,c) USING HASH) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1,1),(2,2,2); +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,1,1); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1 ORDER BY a; +FLUSH STATUS; +REPLACE INTO t1 VALUES (3,2,2); +SHOW STATUS WHERE Variable_name LIKE 'handler%' AND Value>0; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ec9e379768f..b3314e075f0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1728,7 +1728,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, /* Check if there is more uniq keys after field */ -static int last_uniq_key(TABLE *table,uint keynr) +static int last_uniq_key(TABLE *table, const KEY *key, uint keynr) { /* When an underlying storage engine informs that the unique key @@ -1748,7 +1748,7 @@ static int last_uniq_key(TABLE *table,uint keynr) return 0; while (++keynr < table->s->keys) - if (table->key_info[keynr].flags & HA_NOSAME) + if (key[keynr].flags & HA_NOSAME) return 0; return 1; } @@ -2064,8 +2064,27 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) tables which have ON UPDATE but have no ON DELETE triggers, we just should not expose this fact to users by invoking ON UPDATE triggers. + + Note, TABLE_SHARE and TABLE see long uniques differently: + - TABLE_SHARE sees as HA_KEY_ALG_LONG_HASH and HA_NOSAME + - TABLE sees as usual non-unique indexes */ - if (last_uniq_key(table,key_nr) && + bool is_long_unique= table->s->key_info && + table->s->key_info[key_nr].algorithm == + HA_KEY_ALG_LONG_HASH; + if ((is_long_unique ? + /* + We have a long unique. Test that there are no in-engine + uniques and the current long unique is the last long unique. + */ + !(table->key_info[0].flags & HA_NOSAME) && + last_uniq_key(table, table->s->key_info, key_nr) : + /* + We have a normal key - not a long unique. + Test is the current normal key is unique and + it is the last normal unique. + */ + last_uniq_key(table, table->key_info, key_nr)) && !table->file->referenced_by_foreign_key() && (!table->triggers || !table->triggers->has_delete_triggers())) { From 1070575a890ad5fa52af01297b439073f63846a5 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 8 Jan 2024 17:50:19 +1100 Subject: [PATCH 102/121] MDEV-33191 spider: fix dbton_id when iterating over links There are two array fields in spider_share with similar names: share->use_sql_dbton_ids that maps from i to the i-th dbton used by share. Thus it should be used only when i iterates over all distinct dbtons used by share. share->sql_dbton_ids that maps from i to the dbton used by the i-th link of the share. Thus it should be used only when i iterates over all links of a share. We correct instances where share->sql_dbton_ids should be used instead of share->use_sql_dbton_ids. --- storage/spider/ha_spider.cc | 4 ++-- .../mysql-test/spider/bugfix/r/mdev_33191.result | 10 ++++++++++ .../spider/mysql-test/spider/bugfix/t/mdev_33191.test | 11 +++++++++++ storage/spider/spd_db_conn.cc | 2 +- storage/spider/spd_db_include.h | 6 ++++++ storage/spider/spd_include.h | 10 ++++++++++ 6 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 24ee6c5e902..89d86a9ca75 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -8392,7 +8392,7 @@ int ha_spider::ft_read_internal( } } else { #endif - uint dbton_id = share->use_sql_dbton_ids[roop_count]; + uint dbton_id = share->sql_dbton_ids[roop_count]; spider_db_handler *dbton_hdl = dbton_handler[dbton_id]; SPIDER_CONN *conn = conns[roop_count]; pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); @@ -13135,7 +13135,7 @@ int ha_spider::drop_tmp_tables() ) { if (spider_bit_is_set(result_list.tmp_table_created, roop_count)) { - uint dbton_id = share->use_sql_dbton_ids[roop_count]; + uint dbton_id = share->sql_dbton_ids[roop_count]; spider_db_handler *dbton_hdl = dbton_handler[dbton_id]; SPIDER_CONN *conn = conns[roop_count]; pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result new file mode 100644 index 00000000000..7ab2e952213 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33191.result @@ -0,0 +1,10 @@ +INSTALL SONAME 'ha_spider'; +set spider_same_server_link=on; +CREATE TABLE t2(c INT); +CREATE TABLE t1(c INT) ENGINE=Spider COMMENT='socket "$SOCKET", user "root", table "t2 t3"'; +ALTER TABLE t1 ENGINE=Spider; +TRUNCATE TABLE t1; +ERROR 42S02: Table 'test.t3' doesn't exist +drop table t1, t2; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test new file mode 100644 index 00000000000..90709127f46 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33191.test @@ -0,0 +1,11 @@ +INSTALL SONAME 'ha_spider'; +set spider_same_server_link=on; +CREATE TABLE t2(c INT); +--let $SOCKET=`SELECT @@global.socket` +evalp CREATE TABLE t1(c INT) ENGINE=Spider COMMENT='socket "$SOCKET", user "root", table "t2 t3"'; +ALTER TABLE t1 ENGINE=Spider; +--error ER_NO_SUCH_TABLE +TRUNCATE TABLE t1; +drop table t1, t2; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 5b96bfec3cd..52fde02ad0c 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -8215,7 +8215,7 @@ int spider_db_delete_all_rows( spider->conn_link_idx, roop_count, share->link_count, SPIDER_LINK_STATUS_RECOVERY) ) { - uint dbton_id = share->use_sql_dbton_ids[roop_count]; + uint dbton_id = share->sql_dbton_ids[roop_count]; spider_db_handler *dbton_hdl = spider->dbton_handler[dbton_id]; conn = spider->conns[roop_count]; pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index ee6202bf334..5add9fac3e4 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -1836,6 +1836,12 @@ enum spider_db_access_type SPIDER_DB_ACCESS_TYPE_NOSQL }; +/* + Type of singletons based on the type of the remote database. + + All such singletons are stored in the array `spider_dbton', see + `spider_db_init()'. +*/ typedef struct st_spider_dbton { uint dbton_id; diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index f3df1ed8378..0e72ce26696 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -1358,6 +1358,7 @@ typedef struct st_spider_share uint *hs_read_conn_keys_lengths; uint *hs_write_conn_keys_lengths; #endif + /* The index in `spider_dbton' of each data node link. */ uint *sql_dbton_ids; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) uint *hs_dbton_ids; @@ -1447,14 +1448,23 @@ typedef struct st_spider_share uchar dbton_bitmap[spider_bitmap_size(SPIDER_DBTON_SIZE)]; spider_db_share *dbton_share[SPIDER_DBTON_SIZE]; uint use_dbton_count; + /* Actual size is `use_dbton_count'. Values are the indices of item + in `spider_dbton'. */ uint use_dbton_ids[SPIDER_DBTON_SIZE]; + /* Inverse map of `use_dbton_ids'. */ uint dbton_id_to_seq[SPIDER_DBTON_SIZE]; uint use_sql_dbton_count; + /* Actual size is `use_sql_dbton_count'. Values are the indices of + item in `spider_dbton'. */ uint use_sql_dbton_ids[SPIDER_DBTON_SIZE]; + /* Inverse map of `use_sql_dbton_ids'. */ uint sql_dbton_id_to_seq[SPIDER_DBTON_SIZE]; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) uint use_hs_dbton_count; + /* Actual size is `use_hs_dbton_count'. Values are the indices of + item in `spider_dbton'. */ uint use_hs_dbton_ids[SPIDER_DBTON_SIZE]; + /* Inverse map of `use_hs_dbton_ids'. */ uint hs_dbton_id_to_seq[SPIDER_DBTON_SIZE]; #endif From c9c4f15e99c38057b90b923f4a39ef0071cad79f Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 25 Jan 2024 14:44:42 +0100 Subject: [PATCH 103/121] Remove bogus "perl not found" on Windows. Testing exit code from popen(), comparing it with 1, and deciding that perl.exe is not there, is a) wrong conclusion, and b) uninteresting, because MTR always runs with perl, and with MTR_PERL set. Background: Recent change in 7af50e4df456761c433838f0e65e88b9117f298c introduced exit code 1 from perl snippet, that broke Windows CI. Do not want to debug this ever again. --- client/mysqltest.cc | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index b839ae02606..545c2c9da1e 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -4648,15 +4648,11 @@ void do_perl(struct st_command *command) /* Check for error code that indicates perl could not be started */ int exstat= WEXITSTATUS(error); -#ifdef _WIN32 - if (exstat == 1) - /* Text must begin 'perl not found' as mtr looks for it */ - abort_not_supported_test("perl not found in path or did not start"); -#else +#ifndef _WIN32 if (exstat == 127) abort_not_supported_test("perl not found in path"); -#endif else +#endif handle_command_error(command, exstat, my_errno); } dynstr_free(&ds_delimiter); From 0f59810b9944929d2b3ffb64f6d197cf9a20e358 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 10 Sep 2021 02:20:16 +0200 Subject: [PATCH 104/121] MDEV-26579 Support minor MSI in Windows installer. With this patch, 4-component MSI version can be used, e.g by setting TINY_VERSION variable in CMake, or by adding a string, e.g MYSQL_VERSION_EXTRA=-2 which sets TINY_VERSION to 2, and also changes the package name. The 4-component MSI versions do not support MSI major upgrades, only minor ones, i.e do not reinstall components, just update existing ones based on versioning rules. To support these rules, add DefaultVersion for the files that won't otherwise be versioned - headers, static and import libraries, pdbs, text - xml, python and perl scripts Also silence WiX warning that MSI won't store hashes for those files anymore. --- cmake/mysql_version.cmake | 4 +++- win/packaging/create_msi.cmake | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake index cb12bf14b86..2924d6a0096 100644 --- a/cmake/mysql_version.cmake +++ b/cmake/mysql_version.cmake @@ -55,7 +55,9 @@ IF(NOT "${MAJOR_VERSION}" MATCHES "[0-9]+" OR NOT "${PATCH_VERSION}" MATCHES "[0-9]+") MESSAGE(FATAL_ERROR "VERSION file cannot be parsed.") ENDIF() - + IF((NOT TINY_VERSION) AND (EXTRA_VERSION MATCHES "[\\-][0-9]+")) + STRING(REPLACE "-" "" TINY_VERSION "${EXTRA_VERSION}") + ENDIF() SET(VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}${EXTRA_VERSION}") MESSAGE(STATUS "MariaDB ${VERSION}") SET(MYSQL_BASE_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}" CACHE INTERNAL "MySQL Base version") diff --git a/win/packaging/create_msi.cmake b/win/packaging/create_msi.cmake index f992915cd22..1b6f66d0f2c 100644 --- a/win/packaging/create_msi.cmake +++ b/win/packaging/create_msi.cmake @@ -248,6 +248,13 @@ FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) FILE(APPEND ${file} "\n") SET(NONEXEFILES) + FOREACH(v MAJOR_VERSION MINOR_VERSION PATCH_VERSION TINY_VERSION) + IF(NOT ${v}) + MESSAGE(FATAL_ERROR "${v} is not set") + ENDIF() + ENDFOREACH() + SET(default_version "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${TINY_VERSION}") + FOREACH(f ${all_files}) IF(NOT IS_DIRECTORY ${f}) FILE(RELATIVE_PATH rel ${topdir} ${f}) @@ -267,6 +274,7 @@ FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) FILE(APPEND ${file} " ${${id}.COMPONENT_CONDITION}\n") ENDIF() FILE(APPEND ${file} " \n${${id}.FILE_EXTRA}") ELSE() @@ -396,7 +404,7 @@ ENDIF() EXECUTE_PROCESS( COMMAND ${LIGHT_EXECUTABLE} -v -ext WixUIExtension -ext WixUtilExtension - -ext WixFirewallExtension -sice:ICE61 ${SILENCE_VCREDIST_MSM_WARNINGS} + -ext WixFirewallExtension -sice:ICE61 -sw1103 ${SILENCE_VCREDIST_MSM_WARNINGS} mysql_server.wixobj extra.wixobj -out ${CPACK_PACKAGE_FILE_NAME}.msi ${EXTRA_LIGHT_ARGS} ) From b62f25c6509c1b3c0a055316403850b0a8015179 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 10 Sep 2021 09:38:40 +0200 Subject: [PATCH 105/121] MDEV-26579 fixup --- cmake/mysql_version.cmake | 8 +++----- win/packaging/create_msi.cmake | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake index 2924d6a0096..2d4ed95478f 100644 --- a/cmake/mysql_version.cmake +++ b/cmake/mysql_version.cmake @@ -50,13 +50,15 @@ MACRO(GET_MYSQL_VERSION) MYSQL_GET_CONFIG_VALUE("MYSQL_VERSION_EXTRA" EXTRA_VERSION) MYSQL_GET_CONFIG_VALUE("SERVER_MATURITY" SERVER_MATURITY) -IF(NOT "${MAJOR_VERSION}" MATCHES "[0-9]+" OR + IF(NOT "${MAJOR_VERSION}" MATCHES "[0-9]+" OR NOT "${MINOR_VERSION}" MATCHES "[0-9]+" OR NOT "${PATCH_VERSION}" MATCHES "[0-9]+") MESSAGE(FATAL_ERROR "VERSION file cannot be parsed.") ENDIF() IF((NOT TINY_VERSION) AND (EXTRA_VERSION MATCHES "[\\-][0-9]+")) STRING(REPLACE "-" "" TINY_VERSION "${EXTRA_VERSION}") + ELSE() + SET(TINY_VERSION "0") ENDIF() SET(VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}${EXTRA_VERSION}") MESSAGE(STATUS "MariaDB ${VERSION}") @@ -120,10 +122,6 @@ ENDIF() IF(MSVC) # Tiny version is used to identify the build, it can be set with cmake -DTINY_VERSION= # to bzr revno for example (in the CI builds) - IF(NOT TINY_VERSION) - SET(TINY_VERSION "0") - ENDIF() - GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) SET(FILETYPE VFT_APP) diff --git a/win/packaging/create_msi.cmake b/win/packaging/create_msi.cmake index 1b6f66d0f2c..83a8882f823 100644 --- a/win/packaging/create_msi.cmake +++ b/win/packaging/create_msi.cmake @@ -249,8 +249,8 @@ FUNCTION(TRAVERSE_FILES dir topdir file file_comp dir_root) SET(NONEXEFILES) FOREACH(v MAJOR_VERSION MINOR_VERSION PATCH_VERSION TINY_VERSION) - IF(NOT ${v}) - MESSAGE(FATAL_ERROR "${v} is not set") + IF(NOT DEFINED ${v}) + MESSAGE(FATAL_ERROR "${v} is not defined") ENDIF() ENDFOREACH() SET(default_version "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${TINY_VERSION}") From 220c0fb4054c57fe7f6992e0688af4fb97e13151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 26 Jan 2024 11:21:14 +0200 Subject: [PATCH 106/121] MDEV-33317 [Warning] InnoDB: Could not free any blocks in the buffer pool! Let us suppress this timing-sensitive warning globally. We added it in commit d34479dc664d4cbd4e9dad6b0f92d7c8e55595d1 (MDEV-33053) so that in case InnoDB hangs due to running out of buffer pool, there would be a warning about it. On a heavily loaded system that is running with a small buffer pool, these warnings may be occasionally issued while page writes are in progress. --- mysql-test/mariadb-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 2750e10ecf5..3253de4185f 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -4454,6 +4454,7 @@ sub extract_warning_lines ($$) { qr/InnoDB: Warning: a long semaphore wait:/, qr/InnoDB: Dumping buffer pool.*/, qr/InnoDB: Buffer pool.*/, + qr/InnoDB: Could not free any blocks in the buffer pool!/, qr/InnoDB: Warning: Writer thread is waiting this semaphore:/, qr/InnoDB: innodb_open_files .* should not be greater than/, qr/Slave: Unknown table 't1' .* 1051/, From e96a05948b98c4e034ad31eef55936d349d141e7 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 26 Jan 2024 10:48:54 +0100 Subject: [PATCH 107/121] update C/C --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index f1a72768d42..9155b19b462 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit f1a72768d4256416e5c0bf01b254c303f6135bd0 +Subproject commit 9155b19b462ac15fc69d0b58ae51370b7523ced5 From daca0c059b87d30ca067ab388983865fe238ac22 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Fri, 26 Jan 2024 12:24:50 +0530 Subject: [PATCH 108/121] fix failing test on buildbot for MDEV-27087 --- plugin/sql_errlog/sql_errlog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c index d668ed8779b..83f80327640 100644 --- a/plugin/sql_errlog/sql_errlog.c +++ b/plugin/sql_errlog/sql_errlog.c @@ -107,7 +107,7 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), { if (event->database.str) { - logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d %llu " + logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d %lu " "%s %`s ERROR %d: %s : %s \n", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, event->general_thread_id, event->general_user, event->database.str, @@ -115,7 +115,7 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), } else { - logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d %llu " + logger_printf(logfile, "%04d-%02d-%02d %2d:%02d:%02d %lu " "%s %s ERROR %d: %s : %s \n", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, event->general_thread_id, event->general_user, "NULL", From 112eb14f7e0611371522f1555af2c74bd3eb3247 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Fri, 26 Jan 2024 10:34:40 -0700 Subject: [PATCH 109/121] MDEV-27850: rpl_seconds_behind_master_spike debug_sync fix A debug_sync signal could remain for the SQL thread that should have begun a wait_for upon seeing a GTID event, but would instead see the old signal and continue on without waiting. This broke an "idle" condition in SHOW SLAVE STATUS which should have automatically negated Seconds_Behind_Master. Instead, because the SQL thread had already processed the GTID event, it set sql_thread_caught_up to false, and thereby calculated the value of Seconds_behind_master, when the test expected 0. This patch fixes this by resetting the debug_sync state before creating a new transaction which sends a GTID event to the replica --- mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test index d96863a14c2..9e73e6678a2 100644 --- a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test +++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test @@ -132,6 +132,7 @@ while (!$caught_up) } sleep 0.1; } +set debug_sync="RESET"; --enable_query_log --connection master From e20693c167911872afc531d5e86ca197dc05dd60 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 27 Jan 2024 16:29:16 +0200 Subject: [PATCH 110/121] Fixed some wrong printf() usage after changing m_table_id to ulonglong This caused some crashes on 32 bit platforms. --- sql/log_event_client.cc | 5 +++-- sql/log_event_old.cc | 11 ++++++----- sql/log_event_server.cc | 8 ++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index 3b7df6e0f66..69f29cb09e7 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -1502,8 +1502,9 @@ bool Rows_log_event::print_verbose(IO_CACHE *file, if (!(map= print_event_info->m_table_map.get_table(m_table_id)) || !(td= map->create_table_def())) { - return (my_b_printf(file, "### Row event for unknown table #%llu", - (ulonglong) m_table_id)); + char llbuff[22]; + return (my_b_printf(file, "### Row event for unknown table #%s", + ullstr(m_table_id, llbuff))); } /* If the write rows event contained no values for the AI */ diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index b7325225b0a..dff4ca29f6f 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1251,7 +1251,7 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf); - DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %zu", + DBUG_PRINT("info",("m_table_id: %llu m_flags: %d m_width: %lu data_size: %zu", m_table_id, m_flags, m_width, data_size)); DBUG_DUMP("rows_data", (uchar*) ptr_rows_data, data_size); @@ -1790,7 +1790,7 @@ bool Old_rows_log_event::write_data_header() DBUG_ASSERT(m_table_id != UINT32_MAX); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { - int4store(buf + 0, m_table_id); + int4store(buf + 0, (ulong) m_table_id); int2store(buf + 4, m_flags); return write_data(buf, 6); }); @@ -1837,7 +1837,7 @@ void Old_rows_log_event::pack_info(Protocol *protocol) char const *const flagstr= get_flags(STMT_END_F) ? " flags: STMT_END_F" : ""; size_t bytes= my_snprintf(buf, sizeof(buf), - "table_id: %lu%s", m_table_id, flagstr); + "table_id: %llu%s", m_table_id, flagstr); protocol->store(buf, bytes, &my_charset_bin); } #endif @@ -1859,9 +1859,10 @@ bool Old_rows_log_event::print_helper(FILE *file, if (!print_event_info->short_form) { + char llbuff[22]; if (print_header(head, print_event_info, !do_print_encoded) || - my_b_printf(head, "\t%s: table id %lu%s\n", - name, m_table_id, + my_b_printf(head, "\t%s: table id %s%s\n", + name, ullstr(m_table_id, llbuff), do_print_encoded ? " flags: STMT_END_F" : "") || print_base64(body, print_event_info, do_print_encoded)) goto err; diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 3e7fcc9df85..96e5866e0cc 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -6074,7 +6074,7 @@ bool Rows_log_event::write_data_header() DBUG_ASSERT(m_table_id != UINT32_MAX); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { - int4store(buf + 0, m_table_id); + int4store(buf + 0, (ulong) m_table_id); int2store(buf + 4, m_flags); return (write_data(buf, 6)); }); @@ -6588,7 +6588,7 @@ int Table_map_log_event::do_apply_event(rpl_group_info *rgi) char buf[256]; my_snprintf(buf, sizeof(buf), - "Found table map event mapping table id %u which " + "Found table map event mapping table id %llu which " "was already mapped but with different settings.", table_list->table_id); @@ -6633,7 +6633,7 @@ bool Table_map_log_event::write_data_header() uchar buf[TABLE_MAP_HEADER_LEN]; DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { - int4store(buf + 0, m_table_id); + int4store(buf + 0, (ulong) m_table_id); int2store(buf + 4, m_flags); return (write_data(buf, 6)); }); @@ -7069,7 +7069,7 @@ void Table_map_log_event::pack_info(Protocol *protocol) { char buf[256]; size_t bytes= my_snprintf(buf, sizeof(buf), - "table_id: %llu (%s.%s)", + "table_id: %llu (%s.%s)", m_table_id, m_dbnam, m_tblnam); protocol->store(buf, bytes, &my_charset_bin); } From ed76a2e8ac265792f6ca4e49f4c8e04898fb7889 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 27 Jan 2024 16:32:49 +0200 Subject: [PATCH 111/121] Updated some 32 bit result files in sys_vars --- .../r/sysvars_server_embedded,32bit.rdiff | 170 ++++++++--------- .../r/sysvars_server_notembedded,32bit.rdiff | 175 +++++++++--------- 2 files changed, 177 insertions(+), 168 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index 4ebd48ad6bd..a8aa785fcd9 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1,5 +1,5 @@ ---- sysvars_server_embedded.result -+++ sysvars_server_embedded.result +--- suite/sys_vars/r/sysvars_server_embedded.result ++++ suite/sys_vars/r/sysvars_server_embedded,32bit.reject @@ -34,7 +34,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE @@ -290,16 +290,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -914,7 +914,7 @@ - COMMAND_LINE_ARGUMENT REQUIRED - VARIABLE_NAME EXPIRE_LOGS_DAYS - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 99 -@@ -944,7 +944,7 @@ +@@ -954,7 +954,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME EXTRA_MAX_CONNECTIONS VARIABLE_SCOPE GLOBAL @@ -723,6 +714,15 @@ NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 @@ -2274,7 +2274,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_ADJUST_SECONDARY_KEY_COSTS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT 0 = No changes. 1 = Update secondary key costs for ranges to be at least 5x of clustered primary key costs. 2 = Remove 'max_seek optimization' for secondary keys and slight adjustment of filter cost. This option will be deleted in MariaDB 11.0 as it is not needed with the new 11.0 optimizer. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 2 +@@ -2284,7 +2284,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS VARIABLE_SCOPE SESSION @@ -731,7 +731,7 @@ VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2284,7 +2284,7 @@ +@@ -2294,7 +2294,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT VARIABLE_SCOPE SESSION @@ -740,7 +740,7 @@ VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2294,7 +2294,7 @@ +@@ -2304,7 +2304,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -749,7 +749,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2304,7 +2304,7 @@ +@@ -2314,7 +2314,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -758,7 +758,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2314,7 +2314,7 @@ +@@ -2324,7 +2324,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -767,7 +767,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2344,17 +2344,17 @@ +@@ -2354,17 +2354,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE VARIABLE_SCOPE SESSION @@ -788,7 +788,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2374,7 +2374,7 @@ +@@ -2384,7 +2384,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -797,7 +797,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2384,7 +2384,7 @@ +@@ -2394,7 +2394,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -806,7 +806,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2394,7 +2394,7 @@ +@@ -2404,7 +2404,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -815,7 +815,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2404,7 +2404,7 @@ +@@ -2414,7 +2414,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -824,7 +824,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2414,7 +2414,7 @@ +@@ -2424,7 +2424,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -833,7 +833,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2424,7 +2424,7 @@ +@@ -2434,7 +2434,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -842,7 +842,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2434,7 +2434,7 @@ +@@ -2444,7 +2444,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -851,7 +851,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2444,7 +2444,7 @@ +@@ -2454,7 +2454,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -860,7 +860,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2454,7 +2454,7 @@ +@@ -2464,7 +2464,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -869,7 +869,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2464,7 +2464,7 @@ +@@ -2474,7 +2474,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -878,7 +878,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2474,7 +2474,7 @@ +@@ -2484,7 +2484,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -887,7 +887,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2484,7 +2484,7 @@ +@@ -2494,7 +2494,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -896,7 +896,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2494,7 +2494,7 @@ +@@ -2504,7 +2504,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -905,7 +905,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2504,7 +2504,7 @@ +@@ -2514,7 +2514,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -914,7 +914,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2514,7 +2514,7 @@ +@@ -2524,7 +2524,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -923,7 +923,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2524,7 +2524,7 @@ +@@ -2534,7 +2534,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -932,7 +932,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2534,7 +2534,7 @@ +@@ -2544,7 +2544,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -941,7 +941,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2544,7 +2544,7 @@ +@@ -2554,7 +2554,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_INDEX_STAT VARIABLE_SCOPE GLOBAL @@ -950,7 +950,7 @@ VARIABLE_COMMENT Maximum number of index statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2554,7 +2554,7 @@ +@@ -2564,7 +2564,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MEMORY_CLASSES VARIABLE_SCOPE GLOBAL @@ -959,7 +959,7 @@ VARIABLE_COMMENT Maximum number of memory pool instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2564,7 +2564,7 @@ +@@ -2574,7 +2574,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_METADATA_LOCKS VARIABLE_SCOPE GLOBAL @@ -968,7 +968,7 @@ VARIABLE_COMMENT Maximum number of metadata locks. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2574,7 +2574,7 @@ +@@ -2584,7 +2584,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -977,7 +977,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2584,7 +2584,7 @@ +@@ -2594,7 +2594,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -986,7 +986,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2594,7 +2594,7 @@ +@@ -2604,7 +2604,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PREPARED_STATEMENTS_INSTANCES VARIABLE_SCOPE GLOBAL @@ -995,7 +995,7 @@ VARIABLE_COMMENT Maximum number of instrumented prepared statements. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2604,7 +2604,7 @@ +@@ -2614,7 +2614,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PROGRAM_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1004,7 +1004,7 @@ VARIABLE_COMMENT Maximum number of instrumented programs. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2614,7 +2614,7 @@ +@@ -2624,7 +2624,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -1013,7 +1013,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2624,7 +2624,7 @@ +@@ -2634,7 +2634,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1022,7 +1022,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2634,7 +2634,7 @@ +@@ -2644,7 +2644,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -1031,7 +1031,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2644,7 +2644,7 @@ +@@ -2654,7 +2654,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1040,7 +1040,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2654,7 +2654,7 @@ +@@ -2664,7 +2664,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SQL_TEXT_LENGTH VARIABLE_SCOPE GLOBAL @@ -1049,7 +1049,7 @@ VARIABLE_COMMENT Maximum length of displayed sql text. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2664,7 +2664,7 @@ +@@ -2674,7 +2674,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -1058,7 +1058,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2674,7 +2674,7 @@ +@@ -2684,7 +2684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -1067,7 +1067,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2684,7 +2684,7 @@ +@@ -2694,7 +2694,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_STACK VARIABLE_SCOPE GLOBAL @@ -1076,7 +1076,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_CURRENT. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 256 -@@ -2694,7 +2694,7 @@ +@@ -2704,7 +2704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -1085,7 +1085,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2704,7 +2704,7 @@ +@@ -2714,7 +2714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1094,7 +1094,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2714,7 +2714,7 @@ +@@ -2724,7 +2724,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_LOCK_STAT VARIABLE_SCOPE GLOBAL @@ -1103,7 +1103,7 @@ VARIABLE_COMMENT Maximum number of lock statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2724,7 +2724,7 @@ +@@ -2734,7 +2734,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -1112,7 +1112,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2734,7 +2734,7 @@ +@@ -2744,7 +2744,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1121,7 +1121,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2744,7 +2744,7 @@ +@@ -2754,7 +2754,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -1130,7 +1130,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2754,7 +2754,7 @@ +@@ -2764,7 +2764,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1139,7 +1139,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2764,7 +2764,7 @@ +@@ -2774,7 +2774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1148,7 +1148,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2774,7 +2774,7 @@ +@@ -2784,7 +2784,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1157,7 +1157,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2824,7 +2824,7 @@ +@@ -2834,7 +2834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1166,7 +1166,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2844,7 +2844,7 @@ +@@ -2854,7 +2854,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1175,7 +1175,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -2854,7 +2854,7 @@ +@@ -2864,7 +2864,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1184,7 +1184,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2914,7 +2914,7 @@ +@@ -2924,7 +2924,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1193,7 +1193,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2924,7 +2924,7 @@ +@@ -2934,7 +2934,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1202,7 +1202,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2934,7 +2934,7 @@ +@@ -2944,7 +2944,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1211,7 +1211,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2947,7 +2947,7 @@ +@@ -2957,7 +2957,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1220,7 +1220,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2984,7 +2984,7 @@ +@@ -2994,7 +2994,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1229,7 +1229,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2997,7 +2997,7 @@ +@@ -3007,7 +3007,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1238,7 +1238,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3007,14 +3007,14 @@ +@@ -3017,14 +3017,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1255,7 +1255,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3024,7 +3024,7 @@ +@@ -3034,7 +3034,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME READ_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1264,7 +1264,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3044,7 +3044,7 @@ +@@ -3054,7 +3054,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1273,7 +1273,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3064,10 +3064,10 @@ +@@ -3074,10 +3074,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1286,7 +1286,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3104,7 +3104,7 @@ +@@ -3114,7 +3114,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1295,7 +1295,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3174,7 +3174,7 @@ +@@ -3184,7 +3184,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL @@ -1304,7 +1304,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3184,7 +3184,7 @@ +@@ -3194,7 +3194,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1313,7 +1313,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3227,7 +3227,7 @@ +@@ -3237,7 +3237,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1322,7 +1322,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3444,7 +3444,7 @@ +@@ -3454,7 +3454,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1331,7 +1331,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -3524,7 +3524,7 @@ +@@ -3534,7 +3534,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1340,7 +1340,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -3534,7 +3534,7 @@ +@@ -3544,7 +3544,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1349,7 +1349,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -3594,7 +3594,7 @@ +@@ -3604,7 +3604,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1358,7 +1358,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -3677,7 +3677,7 @@ +@@ -3687,7 +3687,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1367,7 +1367,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3687,7 +3687,7 @@ +@@ -3697,7 +3697,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 0 @@ -1376,7 +1376,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3697,14 +3697,14 @@ +@@ -3707,14 +3707,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 0 @@ -1393,7 +1393,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3714,7 +3714,7 @@ +@@ -3724,7 +3724,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1402,7 +1402,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3854,7 +3854,7 @@ +@@ -3864,7 +3864,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1411,7 +1411,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -3881,7 +3881,7 @@ +@@ -3891,7 +3891,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index dfe7e0d829d..0fad61d69a7 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1,5 +1,5 @@ ---- sysvars_server_notembedded.result -+++ sysvars_server_notembedded.result +--- suite/sys_vars/r/sysvars_server_notembedded.result ++++ suite/sys_vars/r/sysvars_server_notembedded,32bit.reject @@ -34,7 +34,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME ARIA_BLOCK_SIZE @@ -714,6 +714,15 @@ NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 @@ -2434,7 +2434,7 @@ + COMMAND_LINE_ARGUMENT REQUIRED + VARIABLE_NAME OPTIMIZER_ADJUST_SECONDARY_KEY_COSTS + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT 0 = No changes. 1 = Update secondary key costs for ranges to be at least 5x of clustered primary key costs. 2 = Remove 'max_seek optimization' for secondary keys and slight adjustment of filter cost. This option will be deleted in MariaDB 11.0 as it is not needed with the new 11.0 optimizer. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 2 +@@ -2444,7 +2444,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARGS VARIABLE_SCOPE SESSION @@ -722,7 +731,7 @@ VARIABLE_COMMENT The maximum number of SEL_ARG objects created when optimizing a range. If more objects would be needed, the range will not be used by the optimizer. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2444,7 +2444,7 @@ +@@ -2454,7 +2454,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_MAX_SEL_ARG_WEIGHT VARIABLE_SCOPE SESSION @@ -731,7 +740,7 @@ VARIABLE_COMMENT The maximum weight of the SEL_ARG graph. Set to 0 for no limit NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2454,7 +2454,7 @@ +@@ -2464,7 +2464,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_PRUNE_LEVEL VARIABLE_SCOPE SESSION @@ -740,7 +749,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2464,7 +2464,7 @@ +@@ -2474,7 +2474,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SEARCH_DEPTH VARIABLE_SCOPE SESSION @@ -749,7 +758,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2474,7 +2474,7 @@ +@@ -2484,7 +2484,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SELECTIVITY_SAMPLING_LIMIT VARIABLE_SCOPE SESSION @@ -758,7 +767,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2504,17 +2504,17 @@ +@@ -2514,17 +2514,17 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE VARIABLE_SCOPE SESSION @@ -779,7 +788,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2534,7 +2534,7 @@ +@@ -2544,7 +2544,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME PERFORMANCE_SCHEMA_ACCOUNTS_SIZE VARIABLE_SCOPE GLOBAL @@ -788,7 +797,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2544,7 +2544,7 @@ +@@ -2554,7 +2554,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_DIGESTS_SIZE VARIABLE_SCOPE GLOBAL @@ -797,7 +806,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2554,7 +2554,7 @@ +@@ -2564,7 +2564,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -806,7 +815,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2564,7 +2564,7 @@ +@@ -2574,7 +2574,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STAGES_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -815,7 +824,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2574,7 +2574,7 @@ +@@ -2584,7 +2584,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -824,7 +833,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2584,7 +2584,7 @@ +@@ -2594,7 +2594,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_STATEMENTS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -833,7 +842,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2594,7 +2594,7 @@ +@@ -2604,7 +2604,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -842,7 +851,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2604,7 +2604,7 @@ +@@ -2614,7 +2614,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_TRANSACTIONS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -851,7 +860,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2614,7 +2614,7 @@ +@@ -2624,7 +2624,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE VARIABLE_SCOPE GLOBAL @@ -860,7 +869,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2624,7 +2624,7 @@ +@@ -2634,7 +2634,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_SIZE VARIABLE_SCOPE GLOBAL @@ -869,7 +878,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2634,7 +2634,7 @@ +@@ -2644,7 +2644,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_HOSTS_SIZE VARIABLE_SCOPE GLOBAL @@ -878,7 +887,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2644,7 +2644,7 @@ +@@ -2654,7 +2654,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_CLASSES VARIABLE_SCOPE GLOBAL @@ -887,7 +896,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2654,7 +2654,7 @@ +@@ -2664,7 +2664,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_COND_INSTANCES VARIABLE_SCOPE GLOBAL @@ -896,7 +905,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2664,7 +2664,7 @@ +@@ -2674,7 +2674,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_DIGEST_LENGTH VARIABLE_SCOPE GLOBAL @@ -905,7 +914,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2674,7 +2674,7 @@ +@@ -2684,7 +2684,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_CLASSES VARIABLE_SCOPE GLOBAL @@ -914,7 +923,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2684,7 +2684,7 @@ +@@ -2694,7 +2694,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_HANDLES VARIABLE_SCOPE GLOBAL @@ -923,7 +932,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2694,7 +2694,7 @@ +@@ -2704,7 +2704,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_FILE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -932,7 +941,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2704,7 +2704,7 @@ +@@ -2714,7 +2714,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_INDEX_STAT VARIABLE_SCOPE GLOBAL @@ -941,7 +950,7 @@ VARIABLE_COMMENT Maximum number of index statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2714,7 +2714,7 @@ +@@ -2724,7 +2724,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MEMORY_CLASSES VARIABLE_SCOPE GLOBAL @@ -950,7 +959,7 @@ VARIABLE_COMMENT Maximum number of memory pool instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2724,7 +2724,7 @@ +@@ -2734,7 +2734,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_METADATA_LOCKS VARIABLE_SCOPE GLOBAL @@ -959,7 +968,7 @@ VARIABLE_COMMENT Maximum number of metadata locks. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2734,7 +2734,7 @@ +@@ -2744,7 +2744,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_CLASSES VARIABLE_SCOPE GLOBAL @@ -968,7 +977,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2744,7 +2744,7 @@ +@@ -2754,7 +2754,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_MUTEX_INSTANCES VARIABLE_SCOPE GLOBAL @@ -977,7 +986,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2754,7 +2754,7 @@ +@@ -2764,7 +2764,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PREPARED_STATEMENTS_INSTANCES VARIABLE_SCOPE GLOBAL @@ -986,7 +995,7 @@ VARIABLE_COMMENT Maximum number of instrumented prepared statements. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2764,7 +2764,7 @@ +@@ -2774,7 +2774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_PROGRAM_INSTANCES VARIABLE_SCOPE GLOBAL @@ -995,7 +1004,7 @@ VARIABLE_COMMENT Maximum number of instrumented programs. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2774,7 +2774,7 @@ +@@ -2784,7 +2784,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_CLASSES VARIABLE_SCOPE GLOBAL @@ -1004,7 +1013,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2784,7 +2784,7 @@ +@@ -2794,7 +2794,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_RWLOCK_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1013,7 +1022,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2794,7 +2794,7 @@ +@@ -2804,7 +2804,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_CLASSES VARIABLE_SCOPE GLOBAL @@ -1022,7 +1031,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2804,7 +2804,7 @@ +@@ -2814,7 +2814,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SOCKET_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1031,7 +1040,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2814,7 +2814,7 @@ +@@ -2824,7 +2824,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_SQL_TEXT_LENGTH VARIABLE_SCOPE GLOBAL @@ -1040,7 +1049,7 @@ VARIABLE_COMMENT Maximum length of displayed sql text. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2824,7 +2824,7 @@ +@@ -2834,7 +2834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STAGE_CLASSES VARIABLE_SCOPE GLOBAL @@ -1049,7 +1058,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2834,7 +2834,7 @@ +@@ -2844,7 +2844,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES VARIABLE_SCOPE GLOBAL @@ -1058,7 +1067,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2844,7 +2844,7 @@ +@@ -2854,7 +2854,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_STACK VARIABLE_SCOPE GLOBAL @@ -1067,7 +1076,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_CURRENT. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 256 -@@ -2854,7 +2854,7 @@ +@@ -2864,7 +2864,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_HANDLES VARIABLE_SCOPE GLOBAL @@ -1076,7 +1085,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2864,7 +2864,7 @@ +@@ -2874,7 +2874,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1085,7 +1094,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2874,7 +2874,7 @@ +@@ -2884,7 +2884,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_TABLE_LOCK_STAT VARIABLE_SCOPE GLOBAL @@ -1094,7 +1103,7 @@ VARIABLE_COMMENT Maximum number of lock statistics for instrumented tables. Use 0 to disable, -1 for automated scaling. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2884,7 +2884,7 @@ +@@ -2894,7 +2894,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_CLASSES VARIABLE_SCOPE GLOBAL @@ -1103,7 +1112,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2894,7 +2894,7 @@ +@@ -2904,7 +2904,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_THREAD_INSTANCES VARIABLE_SCOPE GLOBAL @@ -1112,7 +1121,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2904,7 +2904,7 @@ +@@ -2914,7 +2914,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SESSION_CONNECT_ATTRS_SIZE VARIABLE_SCOPE GLOBAL @@ -1121,7 +1130,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2914,7 +2914,7 @@ +@@ -2924,7 +2924,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_ACTORS_SIZE VARIABLE_SCOPE GLOBAL @@ -1130,7 +1139,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2924,7 +2924,7 @@ +@@ -2934,7 +2934,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_SETUP_OBJECTS_SIZE VARIABLE_SCOPE GLOBAL @@ -1139,7 +1148,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2934,7 +2934,7 @@ +@@ -2944,7 +2944,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_USERS_SIZE VARIABLE_SCOPE GLOBAL @@ -1148,7 +1157,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2984,7 +2984,7 @@ +@@ -2994,7 +2994,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PRELOAD_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1157,7 +1166,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3004,7 +3004,7 @@ +@@ -3014,7 +3014,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME PROFILING_HISTORY_SIZE VARIABLE_SCOPE SESSION @@ -1166,7 +1175,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3014,7 +3014,7 @@ +@@ -3024,7 +3024,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PROGRESS_REPORT_TIME VARIABLE_SCOPE SESSION @@ -1175,7 +1184,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3074,7 +3074,7 @@ +@@ -3084,7 +3084,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME QUERY_ALLOC_BLOCK_SIZE VARIABLE_SCOPE SESSION @@ -1184,7 +1193,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3084,7 +3084,7 @@ +@@ -3094,7 +3094,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_LIMIT VARIABLE_SCOPE GLOBAL @@ -1193,7 +1202,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3094,7 +3094,7 @@ +@@ -3104,7 +3104,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME QUERY_CACHE_MIN_RES_UNIT VARIABLE_SCOPE GLOBAL @@ -1202,7 +1211,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3107,7 +3107,7 @@ +@@ -3117,7 +3117,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1211,7 +1220,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3144,7 +3144,7 @@ +@@ -3154,7 +3154,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME QUERY_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1220,7 +1229,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3157,7 +3157,7 @@ +@@ -3167,7 +3167,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1229,7 +1238,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3167,14 +3167,14 @@ +@@ -3177,14 +3177,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1246,7 +1255,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3187,14 +3187,14 @@ +@@ -3197,14 +3197,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) NUMERIC_MIN_VALUE 0 @@ -1263,7 +1272,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3214,7 +3214,7 @@ +@@ -3224,7 +3224,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME READ_RND_BUFFER_SIZE VARIABLE_SCOPE SESSION @@ -1272,7 +1281,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3424,10 +3424,10 @@ +@@ -3434,10 +3434,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME ROWID_MERGE_BUFF_SIZE VARIABLE_SCOPE SESSION @@ -1285,7 +1294,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3444,20 +3444,20 @@ +@@ -3454,20 +3454,20 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TIMEOUT VARIABLE_SCOPE GLOBAL @@ -1310,7 +1319,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3514,10 +3514,10 @@ +@@ -3524,10 +3524,10 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL VARIABLE_SCOPE GLOBAL @@ -1323,7 +1332,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3554,7 +3554,7 @@ +@@ -3564,7 +3564,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID VARIABLE_SCOPE SESSION @@ -1332,7 +1341,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3684,7 +3684,7 @@ +@@ -3694,7 +3694,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_DOMAIN_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1341,7 +1350,7 @@ VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3714,7 +3714,7 @@ +@@ -3724,7 +3724,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_MAX_ALLOWED_PACKET VARIABLE_SCOPE GLOBAL @@ -1350,7 +1359,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3734,7 +3734,7 @@ +@@ -3744,7 +3744,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_MAX_QUEUED VARIABLE_SCOPE GLOBAL @@ -1359,7 +1368,7 @@ VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2147483647 -@@ -3754,7 +3754,7 @@ +@@ -3764,7 +3764,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME SLAVE_PARALLEL_THREADS VARIABLE_SCOPE GLOBAL @@ -1368,7 +1377,7 @@ VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3764,7 +3764,7 @@ +@@ -3774,7 +3774,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_PARALLEL_WORKERS VARIABLE_SCOPE GLOBAL @@ -1377,7 +1386,7 @@ VARIABLE_COMMENT Alias for slave_parallel_threads NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3804,7 +3804,7 @@ +@@ -3814,7 +3814,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME SLAVE_TRANSACTION_RETRIES VARIABLE_SCOPE GLOBAL @@ -1386,7 +1395,7 @@ VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock, elapsed lock wait timeout or listed in slave_transaction_retry_errors, before giving up and stopping NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3824,7 +3824,7 @@ +@@ -3834,7 +3834,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_TRANSACTION_RETRY_INTERVAL VARIABLE_SCOPE GLOBAL @@ -1395,7 +1404,7 @@ VARIABLE_COMMENT Interval of the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout or listed in slave_transaction_retry_errors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 3600 -@@ -3844,7 +3844,7 @@ +@@ -3854,7 +3854,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLOW_LAUNCH_TIME VARIABLE_SCOPE GLOBAL @@ -1404,7 +1413,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3887,7 +3887,7 @@ +@@ -3897,7 +3897,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1413,7 +1422,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4114,7 +4114,7 @@ +@@ -4124,7 +4124,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME STORED_PROGRAM_CACHE VARIABLE_SCOPE GLOBAL @@ -1422,7 +1431,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -4214,7 +4214,7 @@ +@@ -4224,7 +4224,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME TABLE_DEFINITION_CACHE VARIABLE_SCOPE GLOBAL @@ -1431,7 +1440,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 2097152 -@@ -4224,7 +4224,7 @@ +@@ -4234,7 +4234,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TABLE_OPEN_CACHE VARIABLE_SCOPE GLOBAL @@ -1440,7 +1449,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -4284,7 +4284,7 @@ +@@ -4294,7 +4294,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE VARIABLE_SCOPE GLOBAL @@ -1449,7 +1458,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -4457,7 +4457,7 @@ +@@ -4467,7 +4467,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Max size for data for an internal temporary on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1458,7 +1467,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4467,7 +4467,7 @@ +@@ -4477,7 +4477,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 0 @@ -1467,7 +1476,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4477,14 +4477,14 @@ +@@ -4487,14 +4487,14 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 0 @@ -1484,7 +1493,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4494,7 +4494,7 @@ +@@ -4504,7 +4504,7 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TRANSACTION_PREALLOC_SIZE VARIABLE_SCOPE SESSION @@ -1493,7 +1502,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4634,7 +4634,7 @@ +@@ -4644,7 +4644,7 @@ COMMAND_LINE_ARGUMENT NULL VARIABLE_NAME WAIT_TIMEOUT VARIABLE_SCOPE SESSION @@ -1502,7 +1511,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4661,7 +4661,7 @@ +@@ -4671,7 +4671,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL From 4dbf55bbfcdffb495ea25c6fcfe6c04b624b9654 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 27 Jan 2024 16:47:00 +0200 Subject: [PATCH 112/121] Disable perfschema.misc_session_status for 32 bit 32bit uses less memory so the test for max_memory_usage does not work --- mysql-test/suite/perfschema/t/misc_session_status.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/perfschema/t/misc_session_status.test b/mysql-test/suite/perfschema/t/misc_session_status.test index ea662ce6738..c9e7d066b0c 100644 --- a/mysql-test/suite/perfschema/t/misc_session_status.test +++ b/mysql-test/suite/perfschema/t/misc_session_status.test @@ -1,5 +1,7 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +# This does not crash on 32 bit because of less memory used +--source include/have_64bit.inc --echo # --echo # MDEV-33150 double-locking of LOCK_thd_kill in performance_schema.session_status --echo # From c75905cacbd2e8429dc5abd00835e099227851b2 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 29 Jan 2024 15:17:57 -0700 Subject: [PATCH 113/121] MDEV-33327: rpl_seconds_behind_master_spike Sensitive to IO Thread Stop Position rpl.rpl_seconds_behind_master_spike uses the DEBUG_SYNC mechanism to count how many format descriptor events (FDEs) have been executed, to attempt to pause on a specific relay log FDE after executing transactions. However, depending on when the IO thread is stopped, it can send an extra FDE before sending the transactions, forcing the test to pause before executing any transactions, resulting in a table not existing, that is attempted to be read for COUNT. This patch fixes this by no longer counting FDEs, but rather by programmatically waiting until the SQL thread has executed the transaction and then automatically activating the DEBUG_SYNC point to trigger at the next relay log FDE. --- .../rpl/r/rpl_seconds_behind_master_spike.result | 8 ++------ .../rpl/t/rpl_seconds_behind_master_spike.test | 9 ++------- sql/slave.cc | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result index bb71f6c92b0..3234a512d86 100644 --- a/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result +++ b/mysql-test/suite/rpl/r/rpl_seconds_behind_master_spike.result @@ -3,7 +3,8 @@ include/master-slave.inc connection slave; include/stop_slave.inc SET @save_dbug= @@GLOBAL.debug_dbug; -SET @@global.debug_dbug="+d,pause_sql_thread_on_fde,negate_clock_diff_with_master"; +SET @@global.debug_dbug="+d,pause_sql_thread_on_relay_fde_after_trans"; +SET @@global.debug_dbug="+d,negate_clock_diff_with_master"; include/start_slave.inc # Future events must be logged at least 2 seconds after # the slave starts @@ -15,11 +16,6 @@ insert into t1 values (1); # event in its relay log flush logs; connection slave; -# Ignore FDEs that happen before the CREATE/INSERT commands -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; # On the next FDE, the slave should have the master CREATE/INSERT events SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; select count(*)=1 from t1; diff --git a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test index 9e73e6678a2..cd6311c5e19 100644 --- a/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test +++ b/mysql-test/suite/rpl/t/rpl_seconds_behind_master_spike.test @@ -27,7 +27,8 @@ --connection slave --source include/stop_slave.inc SET @save_dbug= @@GLOBAL.debug_dbug; -SET @@global.debug_dbug="+d,pause_sql_thread_on_fde,negate_clock_diff_with_master"; +SET @@global.debug_dbug="+d,pause_sql_thread_on_relay_fde_after_trans"; +SET @@global.debug_dbug="+d,negate_clock_diff_with_master"; --source include/start_slave.inc --let $sleep_time=2 @@ -46,12 +47,6 @@ insert into t1 values (1); flush logs; --connection slave ---echo # Ignore FDEs that happen before the CREATE/INSERT commands -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; -SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; -SET DEBUG_SYNC='now SIGNAL sql_thread_continue'; - --echo # On the next FDE, the slave should have the master CREATE/INSERT events SET DEBUG_SYNC='now WAIT_FOR paused_on_fde'; select count(*)=1 from t1; diff --git a/sql/slave.cc b/sql/slave.cc index f4d76e447cd..d37b00f2888 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4301,6 +4301,15 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, { Gtid_log_event *gev= static_cast(ev); +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF( + "pause_sql_thread_on_relay_fde_after_trans", + { + DBUG_SET("-d,pause_sql_thread_on_relay_fde_after_trans"); + DBUG_SET("+d,pause_sql_thread_on_next_relay_fde"); + }); +#endif + /* For GTID, allocate a new sub_id for the given domain_id. The sub_id must be allocated in increasing order of binlog order. @@ -4451,12 +4460,14 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, #endif /* WITH_WSREP */ #ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF( - "pause_sql_thread_on_fde", - if (ev && typ == FORMAT_DESCRIPTION_EVENT) { + "pause_sql_thread_on_next_relay_fde", + if (ev && typ == FORMAT_DESCRIPTION_EVENT && + ((Format_description_log_event *) ev)->is_relay_log_event()) { DBUG_ASSERT(!debug_sync_set_action( thd, STRING_WITH_LEN( "now SIGNAL paused_on_fde WAIT_FOR sql_thread_continue"))); + DBUG_SET("-d,pause_sql_thread_on_next_relay_fde"); }); #endif From 908c9cf90cbada86fd25bd3b45d686c49d1dacf5 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 30 Jan 2024 17:00:15 +0100 Subject: [PATCH 114/121] workaround for MDEV-33218 --- sql/sql_lex.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 847bd1d72d2..9ef08bd346a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4146,9 +4146,12 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, { Query_arena_stmt on_stmt_arena(thd); changed_elements|= TOUCHED_SEL_COND; + /* + TODO: return after MDEV-33218 fix DBUG_ASSERT( active_arena->is_stmt_prepare_or_first_stmt_execute() || active_arena->state == Query_arena::STMT_SP_QUERY_ARGUMENTS); + */ if (group_list.first) { if (!group_list_ptrs) From d1744ee7a2f1ce5cab486ccf18a754ab3e8d8f63 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 31 Jan 2024 11:18:40 +0100 Subject: [PATCH 115/121] MDEV-33343 spider.mdev_28739_simple fails in buildbot test disabled, until fixed --- storage/spider/mysql-test/spider/bugfix/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/spider/mysql-test/spider/bugfix/disabled.def b/storage/spider/mysql-test/spider/bugfix/disabled.def index 559feeff4bd..7b5c72823b7 100644 --- a/storage/spider/mysql-test/spider/bugfix/disabled.def +++ b/storage/spider/mysql-test/spider/bugfix/disabled.def @@ -1,2 +1,3 @@ wait_timeout : MDEV-26045 mdev_27575 : MDEV-32997 +mdev_28739_simple : MDEV-33343 From e5147c8140450f28505a227159d2feba37dd1c39 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 30 Jan 2024 16:39:28 +0100 Subject: [PATCH 116/121] regression introduced by MDEV-14448 --- client/mysql.cc | 3 --- mysql-test/main/mysql-interactive.result | 24 ++++++++++++++++++++ mysql-test/main/mysql-interactive.test | 29 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 mysql-test/main/mysql-interactive.result create mode 100644 mysql-test/main/mysql-interactive.test diff --git a/client/mysql.cc b/client/mysql.cc index fe086f29dac..c917501fdc3 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2136,10 +2136,7 @@ static int read_and_execute(bool interactive) the readline/libedit library. */ if (line) - { free(line); - glob_buffer.length(0); - } line= readline(prompt); #ifdef USE_LIBEDIT_INTERFACE /* diff --git a/mysql-test/main/mysql-interactive.result b/mysql-test/main/mysql-interactive.result new file mode 100644 index 00000000000..a18c018b932 --- /dev/null +++ b/mysql-test/main/mysql-interactive.result @@ -0,0 +1,24 @@ +# +# regression introduced by MDEV-14448 +# +delimiter $ +select 1; +$ +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is X +Server version: Y +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [(none)]> delimiter $ +MariaDB [(none)]> select 1; + -> $ ++---+ +| 1 | ++---+ +| 1 | ++---+ +1 row in set + +MariaDB [(none)]> \ No newline at end of file diff --git a/mysql-test/main/mysql-interactive.test b/mysql-test/main/mysql-interactive.test new file mode 100644 index 00000000000..2015e9d667d --- /dev/null +++ b/mysql-test/main/mysql-interactive.test @@ -0,0 +1,29 @@ +--echo # +--echo # regression introduced by MDEV-14448 +--echo # +source include/not_embedded.inc; +source include/not_windows.inc; + +error 0,1; +exec $MYSQL -V|grep -q readline; +if ($sys_errno == 1) +{ + # strangely enough + skip does not work with libedit; +} + +write_file $MYSQL_TMP_DIR/mysql_in; +delimiter $ +select 1; +$ +EOF +let TERM=dumb; +replace_regex /id is \d+/id is X/ /Server version: .*/Server version: Y/ / \(\d+\.\d+ sec\)//; +error 0,127; +exec socat EXEC:"$MYSQL",pty STDIO < $MYSQL_TMP_DIR/mysql_in; +if ($sys_errno == 127) +{ + remove_file $MYSQL_TMP_DIR/mysql_in; + skip no socat; +} +remove_file $MYSQL_TMP_DIR/mysql_in; From 46e3a7658b774942e9320a1acb234373bb44e874 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 31 Jan 2024 17:07:46 +0100 Subject: [PATCH 117/121] funcs_1.innodb_views times out in --ps --- mysql-test/suite/funcs_1/views/views_master.inc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mysql-test/suite/funcs_1/views/views_master.inc b/mysql-test/suite/funcs_1/views/views_master.inc index 526e9e3426e..3b33f2150b1 100644 --- a/mysql-test/suite/funcs_1/views/views_master.inc +++ b/mysql-test/suite/funcs_1/views/views_master.inc @@ -3085,8 +3085,10 @@ eval SHOW CREATE VIEW test1.v$level; # the following line as written as '--eror ER_TOO_MANY_TABLES' and the command # is successful so assuming no expected error was intended # --error ER_TOO_MANY_TABLES +--disable_ps2_protocol eval SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM test1.v$level; +--enable_ps2_protocol let $message= The output of following EXPLAIN is deactivated, because the result differs on some platforms FIXME Is this a bug ? ; @@ -3116,16 +3118,20 @@ SELECT f1 as f2, f2 as f1 FROM test2.t1; CREATE OR REPLACE VIEW test2.v0 AS SELECT CAST('0001-01-01' AS DATE) as f1, f2 FROM test3.t1; eval SHOW CREATE VIEW test1.v$toplevel; +--disable_ps2_protocol eval SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM test1.v$toplevel; +--enable_ps2_protocol eval EXPLAIN SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM test1.v$toplevel; # 2.3.3 UCS2 string instead of common string CREATE OR REPLACE VIEW test3.v0 AS SELECT f1 , CONVERT('ßÄäÖöÜü§' USING UCS2) as f2 FROM test1.t1; eval SHOW CREATE VIEW test1.v$toplevel; +--disable_ps2_protocol eval SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM test1.v$toplevel; +--enable_ps2_protocol eval EXPLAIN SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM test1.v$toplevel; @@ -3133,8 +3139,10 @@ eval EXPLAIN SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CREATE OR REPLACE VIEW test3.v0 AS SELECT CONVERT('ßÄäÖöÜü§' USING UCS2) as f1, f2 FROM test1.t1; eval SHOW CREATE VIEW test1.v$toplevel; +--disable_ps2_protocol eval SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM test1.v$toplevel; +--enable_ps2_protocol eval EXPLAIN SELECT CAST(f1 AS SIGNED INTEGER) AS f1, CAST(f2 AS CHAR) AS f2 FROM test1.v$toplevel; --enable_result_log From 2278f3503e5239f3abf8f77cdc393e48297d48d9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 31 Jan 2024 22:02:59 +0100 Subject: [PATCH 118/121] fix columnstore compilation on fc39 --- storage/columnstore/columnstore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/columnstore/columnstore b/storage/columnstore/columnstore index fcd637addcf..07e7301631a 160000 --- a/storage/columnstore/columnstore +++ b/storage/columnstore/columnstore @@ -1 +1 @@ -Subproject commit fcd637addcfbe0e9c55ebfc83303e8415cda8e96 +Subproject commit 07e7301631a5ac5ce86c3449d539eb4856119e1c From dd95c58b5864c8b6f57630df67afd19a9552350e Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Tue, 30 Jan 2024 21:50:13 +0100 Subject: [PATCH 119/121] MDEV-33331: IO Thread Relay Log Inconsistent Statistics After MDEV-32551 After MDEV-32551, in a master/slave setup, if the replica's IO thread quickly and successively reconnects (i.e quickly running STOP SLAVE IO_THREAD followed by START SLAVE IO_THREAD), the relay log rotation behavior changes. That is, MDEV-32551 changed the logic of the binlog_dump_thread on the primary, such that it can stop itself before sending any events if it sees a new connection has been created to a replica with the same server_id. Pre MDEV-32551, the connection would establish and it would send a "fake" rotate event to populate the log name. Post MDEV-32551, the connection stops itself, and a rotate event is not sent. This made the test rpl.rpl_mariadb_slave_capability unstable because it is reliant on the name of the relay logs (which is dependent on the number of rotates); and the pre-amble of the test would quickly start/stop the IO thread. There a binlog dump thread could end itself before sending a rotate event to the replica, thereby changing the name of the relay log. This patch fixes this by adding in a synchronization in-between IO thread restarts, such that it waits for the primary's binlog dump threads to sync up with the state of the replica. --- .../suite/rpl/r/rpl_mariadb_slave_capability.result | 5 +++++ .../suite/rpl/t/rpl_mariadb_slave_capability.test | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result b/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result index 68e8b22dd02..fddb07c9cbf 100644 --- a/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result +++ b/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result @@ -6,6 +6,11 @@ connection slave; include/stop_slave.inc CHANGE MASTER TO MASTER_USE_GTID=NO; include/start_slave.inc +connection master; +# Ensure only the new binlog dump thread is alive (wait for the old one +# to complete its kill) +# And that it has already sent its fake rotate +connection slave; include/stop_slave.inc # Test slave with no capability gets dummy event, which is ignored. set @old_dbug= @@global.debug_dbug; diff --git a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test index 2ad9124d886..ee890a8fd03 100644 --- a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test +++ b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test @@ -18,6 +18,18 @@ connection slave; CHANGE MASTER TO MASTER_USE_GTID=NO; --source include/start_slave.inc +--connection master +--echo # Ensure only the new binlog dump thread is alive (wait for the old one +--echo # to complete its kill) +--let $wait_condition= select count(*)=1 from information_schema.processlist where command='Binlog Dump' +--source include/wait_condition.inc + +--echo # And that it has already sent its fake rotate +--let $wait_condition= select count(*)=1 from information_schema.processlist where state LIKE '%Master has sent all binlog to slave%' and command='Binlog Dump' +--source include/wait_condition.inc + + +--connection slave --source include/stop_slave.inc --echo # Test slave with no capability gets dummy event, which is ignored. set @old_dbug= @@global.debug_dbug; From 15c75ad083a55e198ae78324f22970694b72f22b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 1 Feb 2024 11:26:36 +0100 Subject: [PATCH 120/121] pcre.cmake: always check the library with check_library_exists() even if pkg-config has it. otherwise build dependencies aren't detected. --- cmake/pcre.cmake | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmake/pcre.cmake b/cmake/pcre.cmake index c2eb26074ac..3c427b881fc 100644 --- a/cmake/pcre.cmake +++ b/cmake/pcre.cmake @@ -81,18 +81,15 @@ MACRO (CHECK_PCRE) FIND_PACKAGE(PkgConfig QUIET) PKG_CHECK_MODULES(PCRE libpcre2-8) # in case pkg-config or libpcre2-8.pc is not installed: - IF(NOT PCRE_FOUND) - UNSET(PCRE_FOUND CACHE) - CHECK_LIBRARY_EXISTS(pcre2-8 pcre2_match_8 "" PCRE_FOUND) - ENDIF() + CHECK_LIBRARY_EXISTS(pcre2-8 pcre2_match_8 "${PCRE_LIBRARY_DIRS}" HAVE_PCRE2_MATCH_8) ENDIF() - IF(NOT PCRE_FOUND OR WITH_PCRE STREQUAL "bundled") + IF(NOT HAVE_PCRE2_MATCH_8 OR WITH_PCRE STREQUAL "bundled") IF (WITH_PCRE STREQUAL "system") MESSAGE(FATAL_ERROR "system pcre2-8 library is not found or unusable") ENDIF() BUNDLE_PCRE2() ELSE() - CHECK_LIBRARY_EXISTS(pcre2-posix PCRE2regcomp "" NEEDS_PCRE2_DEBIAN_HACK) + CHECK_LIBRARY_EXISTS(pcre2-posix PCRE2regcomp "${PCRE_LIBRARY_DIRS}" NEEDS_PCRE2_DEBIAN_HACK) IF(NEEDS_PCRE2_DEBIAN_HACK) SET(PCRE2_DEBIAN_HACK "-Dregcomp=PCRE2regcomp -Dregexec=PCRE2regexec -Dregerror=PCRE2regerror -Dregfree=PCRE2regfree") ENDIF() From b5c367cd88e37091ab5f8dab0396c01c97d037e2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 1 Feb 2024 16:15:02 +0100 Subject: [PATCH 121/121] MDEV-32815 test main.func_sformat Locale + test failures under Fedora 39 (fmt-10.0.0+) FMT_STATIC_THOUSANDS_SEPARATOR stopped working in 10.0.0 Let's not use this fmt version for now --- cmake/libfmt.cmake | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cmake/libfmt.cmake b/cmake/libfmt.cmake index 70b6a07216f..da3479424b1 100644 --- a/cmake/libfmt.cmake +++ b/cmake/libfmt.cmake @@ -1,4 +1,4 @@ -INCLUDE (CheckCXXSourceCompiles) +INCLUDE (CheckCXXSourceRuns) INCLUDE (ExternalProject) SET(WITH_LIBFMT "auto" CACHE STRING @@ -27,17 +27,15 @@ ENDMACRO() MACRO (CHECK_LIBFMT) IF(WITH_LIBFMT STREQUAL "system" OR WITH_LIBFMT STREQUAL "auto") SET(CMAKE_REQUIRED_INCLUDES ${LIBFMT_INCLUDE_DIR}) - CHECK_CXX_SOURCE_COMPILES( + CHECK_CXX_SOURCE_RUNS( "#define FMT_STATIC_THOUSANDS_SEPARATOR ',' #define FMT_HEADER_ONLY 1 #include - #include int main() { - int answer= 42; + int answer= 4321; fmt::format_args::format_arg arg= fmt::detail::make_arg(answer); - std::cout << fmt::vformat(\"The answer is {}.\", - fmt::format_args(&arg, 1)); + return fmt::vformat(\"{:L}\", fmt::format_args(&arg, 1)).compare(\"4,321\"); }" HAVE_SYSTEM_LIBFMT) SET(CMAKE_REQUIRED_INCLUDES) ENDIF()