From 66832e3a6474967da7dcf22cd1c5e9368b699ef1 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 14 Apr 2022 13:28:51 +1000 Subject: [PATCH 01/94] mtr: extend gdb backtace info bt full - to include args and locals. set print sevenbit on - it is more useful to be able to see the exact bytes (in case something is dumped as a string and not hexadecimal digits) set print static-members off - there are many interesting (non-const) static members set frame-arguments all - even non-printables are useful to see. Let's make our bb logs give a little bit more detail on those hard to reproduce bugs. Tests on rhel7's gdb-7.6.1-120.el7 --- mysql-test/lib/My/CoreDump.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/My/CoreDump.pm b/mysql-test/lib/My/CoreDump.pm index 1ba94223b68..9d1dd27cf88 100644 --- a/mysql-test/lib/My/CoreDump.pm +++ b/mysql-test/lib/My/CoreDump.pm @@ -78,7 +78,10 @@ sub _gdb { my ($tmp, $tmp_name) = tempfile(); print $tmp "bt\n", - "thread apply all bt\n", + "set print sevenbit on\n", + "set print static-members off\n", + "set print frame-arguments all\n", + "thread apply all bt full\n", "quit\n"; close $tmp or die "Error closing $tmp_name: $!"; From c05fd700970ad45735caed3a6f9930d4ce19a3bd Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 14 Apr 2022 16:11:04 +0400 Subject: [PATCH 02/94] MDEV-26323 use-after-poison issue of MariaDB server --- mysql-test/r/plugin.result | 9 +++++++++ mysql-test/t/plugin.test | 17 +++++++++++++++++ sql/sql_plugin.cc | 3 ++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result index 04931001901..6020747aec4 100644 --- a/mysql-test/r/plugin.result +++ b/mysql-test/r/plugin.result @@ -353,4 +353,13 @@ select * from mysql.plugin WHERE name='unexisting_plugin'; name dl UNINSTALL PLUGIN unexisting_plugin; ERROR 42000: PLUGIN unexisting_plugin does not exist +# +# MDEV-26323 use-after-poison issue of MariaDB server +# +INSTALL PLUGIN DEALLOCATE SONAME ''; +ERROR HY000: Can't open shared library '.so' +INSTALL PLUGIN DEALLOCATE SONAME 'x'; +ERROR HY000: Can't open shared library 'x.so' +INSTALL PLUGIN DEALLOCATE SONAME 'xx'; +ERROR HY000: Can't open shared library 'xx.so' # End of 10.2 tests diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test index d2e828b2589..5ac616a1310 100644 --- a/mysql-test/t/plugin.test +++ b/mysql-test/t/plugin.test @@ -295,4 +295,21 @@ select * from mysql.plugin WHERE name='unexisting_plugin'; --error ER_SP_DOES_NOT_EXIST UNINSTALL PLUGIN unexisting_plugin; +--echo # +--echo # MDEV-26323 use-after-poison issue of MariaDB server +--echo # + +--replace_regex /library '.*[\\/].(dll|so)' [(].*[)]/library '.so'/ +--error ER_CANT_OPEN_LIBRARY +INSTALL PLUGIN DEALLOCATE SONAME ''; + +--replace_regex /library '.*[\\/]x.(dll|so)' [(].*[)]/library 'x.so'/ +--error ER_CANT_OPEN_LIBRARY +INSTALL PLUGIN DEALLOCATE SONAME 'x'; + +--replace_regex /library '.*[\\/]xx.(dll|so)' [(].*[)]/library 'xx.so'/ +--error ER_CANT_OPEN_LIBRARY +INSTALL PLUGIN DEALLOCATE SONAME 'xx'; + + --echo # End of 10.2 tests diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 97bc17042b2..75631faccaa 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -372,7 +372,8 @@ bool check_valid_path(const char *path, size_t len) static void fix_dl_name(MEM_ROOT *root, LEX_STRING *dl) { const size_t so_ext_len= sizeof(SO_EXT) - 1; - if (my_strcasecmp(&my_charset_latin1, dl->str + dl->length - so_ext_len, + if (dl->length < so_ext_len || + my_strcasecmp(&my_charset_latin1, dl->str + dl->length - so_ext_len, SO_EXT)) { char *s= (char*)alloc_root(root, dl->length + so_ext_len + 1); From b5e16a6e0381b28b598da80b414168ce9a5016e5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Apr 2022 22:48:46 +0200 Subject: [PATCH 03/94] MDEV-26061 MariaDB server crash at Field::set_default * Item_default_value::fix_fields creates a copy of its argument's field. * Field::default_value is changed when its expression is prepared in unpack_vcol_info_from_frm() This means we must unpack any vcol expression that includes DEFAULT(x) strictly after unpacking x->default_value. To avoid building and solving this dependency graph on every table open, we update Item_default_value::field->default_value after all vcols are unpacked and fixed. --- mysql-test/r/check_constraint.result | 15 +++++++++++++++ mysql-test/t/check_constraint.test | 17 +++++++++++++++++ sql/item.cc | 6 ++++++ sql/item.h | 1 + 4 files changed, 39 insertions(+) diff --git a/mysql-test/r/check_constraint.result b/mysql-test/r/check_constraint.result index 3511af84166..988e49b274d 100644 --- a/mysql-test/r/check_constraint.result +++ b/mysql-test/r/check_constraint.result @@ -235,3 +235,18 @@ a b insert t1 (b) values (1); ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1` drop table t1; +# +# MDEV-26061 MariaDB server crash at Field::set_default +# +create table t1 (v2 date check (v1 like default (v1)), v1 date default (from_days ('x'))); +Warnings: +Warning 1292 Truncated incorrect INTEGER value: 'x' +insert ignore into t1 values ( 'x' , 'x' ) ; +Warnings: +Warning 1265 Data truncated for column 'v2' at row 1 +Warning 1265 Data truncated for column 'v1' at row 1 +Warning 1292 Truncated incorrect INTEGER value: 'x' +drop table t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/check_constraint.test b/mysql-test/t/check_constraint.test index 93538fd1666..05145d9d434 100644 --- a/mysql-test/t/check_constraint.test +++ b/mysql-test/t/check_constraint.test @@ -176,3 +176,20 @@ select * from t1 where a is null; --error ER_CONSTRAINT_FAILED insert t1 (b) values (1); drop table t1; + +--echo # +--echo # MDEV-26061 MariaDB server crash at Field::set_default +--echo # + +create table t1 (v2 date check (v1 like default (v1)), v1 date default (from_days ('x'))); +insert ignore into t1 values ( 'x' , 'x' ) ; +drop table t1; + +--echo # +--echo # End of 10.2 tests +--echo # + +# 10.3 test +#create table t1 (d timestamp check (default (d) is true)) as select 1; +#show create table t1; +#drop table t1; diff --git a/sql/item.cc b/sql/item.cc index 6e5d2ee45a2..cf824039b56 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -8976,6 +8976,12 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const } +bool Item_default_value::check_field_expression_processor(void *) +{ + field->default_value= ((Item_field *)(arg->real_item()))->field->default_value; + return 0; +} + bool Item_default_value::fix_fields(THD *thd, Item **items) { Item *real_arg; diff --git a/sql/item.h b/sql/item.h index 290ff11a0f8..0823f064af8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5507,6 +5507,7 @@ public: Item *get_tmp_table_item(THD *thd) { return this; } Item_field *field_for_view_update() { return 0; } bool update_vcol_processor(void *arg) { return 0; } + bool check_field_expression_processor(void *arg); bool check_func_default_processor(void *arg) { return true; } bool enchant_default_with_arg_processor(void *arg); From cc08c43ed642ce8f5fc2c35bd1e917f220987c66 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Apr 2022 10:16:54 +0200 Subject: [PATCH 04/94] cleanup: remove Item_default_value::cached_field --- sql/item.cc | 7 ++----- sql/item.h | 9 ++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index cf824039b56..502ca799181 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1055,8 +1055,7 @@ bool Item_field::check_field_expression_processor(void *arg) (!field->vcol_info && !org_field->vcol_info)) && field->field_index >= org_field->field_index)) { - my_error(ER_EXPRESSION_REFERS_TO_UNINIT_FIELD, - MYF(0), + my_error(ER_EXPRESSION_REFERS_TO_UNINIT_FIELD, MYF(0), org_field->field_name, field->field_name); return 1; } @@ -9024,7 +9023,6 @@ bool Item_default_value::fix_fields(THD *thd, Item **items) } if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of()))) goto error; - cached_field= def_field; memcpy((void *)def_field, (void *)field_arg->field, field_arg->field->size_of()); def_field->reset_fields(); @@ -9063,8 +9061,7 @@ bool Item_default_value::enchant_default_with_arg_processor(void *proc_arg) void Item_default_value::cleanup() { - delete cached_field; // Free cached blob data - cached_field= 0; + delete field; // Free cached blob data Item_field::cleanup(); } diff --git a/sql/item.h b/sql/item.h index 0823f064af8..35454c69734 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5455,18 +5455,17 @@ protected: Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, (const char *)NULL), - arg(a), cached_field(NULL) {} + arg(a) {} public: Item *arg; - Field *cached_field; Item_default_value(THD *thd, Name_resolution_context *context_arg) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, (const char *)NULL), - arg(NULL), cached_field(NULL) {} + arg(NULL) {} Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, (const char *)NULL), - arg(NULL),cached_field(NULL) {} + arg(NULL) {} enum Type type() const { return DEFAULT_VALUE_ITEM; } bool vcol_assignment_allowed_value() const { return true; } bool eq(const Item *item, bool binary_cmp) const; @@ -5498,7 +5497,7 @@ public: return false; } table_map used_tables() const; - virtual void update_used_tables() + void update_used_tables() { if (field && field->default_value) field->default_value->expr->update_used_tables(); From 4681b6f2d8c82b4ec5cf115e83698251963d80d5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Apr 2022 21:45:20 +0200 Subject: [PATCH 05/94] MDEV-26281 ASAN use-after-poison when complex conversion is involved in blob the bug was that in_vector array in Item_func_in was allocated in the statement arena, not in the table->expr_arena. revert part of the 5acd391e8b2d. Instead, change the arena correctly in fix_all_session_vcol_exprs(). Remove TABLE_ARENA, that was introduced in 5acd391e8b2d to force item tree changes to be rolled back (because they were allocated in the wrong arena and didn't persist. now they do) --- mysql-test/suite/vcol/r/wrong_arena.result | 19 ++++++++++++++++++ mysql-test/suite/vcol/t/wrong_arena.test | 23 ++++++++++++++++------ sql/sql_base.cc | 9 +++------ sql/sql_class.h | 5 ++--- sql/table.cc | 15 ++------------ 5 files changed, 43 insertions(+), 28 deletions(-) diff --git a/mysql-test/suite/vcol/r/wrong_arena.result b/mysql-test/suite/vcol/r/wrong_arena.result index c105a069b7f..8edcd5c881f 100644 --- a/mysql-test/suite/vcol/r/wrong_arena.result +++ b/mysql-test/suite/vcol/r/wrong_arena.result @@ -1,3 +1,6 @@ +# +# MDEV-9690 concurrent queries with virtual columns crash in temporal code +# create table t1 (a datetime, # get_datetime_value b int as (a > 1), # Arg_comparator @@ -59,6 +62,9 @@ a b Warnings: Warning 1292 Incorrect datetime value: '1' drop table t1; +# +# MDEV-13435 Crash when selecting virtual columns generated using JSON functions +# create table t1 ( id int not null , js varchar(1000) not null, @@ -68,3 +74,16 @@ select * from t1; id js t 0 {"default" : {"start": "00:00:00", "end":"23:59:50"}} NULL drop table t1; +# +# MDEV-26281 ASAN use-after-poison when complex conversion is involved in blob +# +create table t1 (v2 blob as ('a' is null), a1 int, a char(1) as (cast(a1 in (0,current_user() is null) as char(16777216) ))); +insert ignore into t1 values ('x','x',v2) ; +Warnings: +Warning 1906 The value specified for generated column 'v2' in table 't1' has been ignored +Warning 1366 Incorrect integer value: 'x' for column `test`.`t1`.`a1` at row 1 +Warning 1906 The value specified for generated column 'a' in table 't1' has been ignored +drop table t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/suite/vcol/t/wrong_arena.test b/mysql-test/suite/vcol/t/wrong_arena.test index 8ac1af5c36b..296cb68f5c0 100644 --- a/mysql-test/suite/vcol/t/wrong_arena.test +++ b/mysql-test/suite/vcol/t/wrong_arena.test @@ -3,9 +3,9 @@ # not in the TABLE::expr_arena. # -# -# MDEV-9690 concurrent queries with virtual columns crash in temporal code -# +--echo # +--echo # MDEV-9690 concurrent queries with virtual columns crash in temporal code +--echo # create table t1 (a datetime, # get_datetime_value b int as (a > 1), # Arg_comparator @@ -40,9 +40,9 @@ connection default; select * from t1; drop table t1; -# -# MDEV-13435 Crash when selecting virtual columns generated using JSON functions -# +--echo # +--echo # MDEV-13435 Crash when selecting virtual columns generated using JSON functions +--echo # create table t1 ( id int not null , js varchar(1000) not null, @@ -50,3 +50,14 @@ create table t1 ( insert into t1(id,js) values (0, '{"default" : {"start": "00:00:00", "end":"23:59:50"}}'); select * from t1; drop table t1; + +--echo # +--echo # MDEV-26281 ASAN use-after-poison when complex conversion is involved in blob +--echo # +create table t1 (v2 blob as ('a' is null), a1 int, a char(1) as (cast(a1 in (0,current_user() is null) as char(16777216) ))); +insert ignore into t1 values ('x','x',v2) ; +drop table t1; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a6c07600591..ce6fd4cbe64 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5010,16 +5010,13 @@ static bool fix_all_session_vcol_exprs(THD *thd, TABLE_LIST *tables) if (!table->placeholder() && t->s->vcols_need_refixing && table->lock_type >= TL_WRITE_ALLOW_WRITE) { - Query_arena *stmt_backup= thd->stmt_arena; - if (thd->stmt_arena->is_conventional()) - thd->stmt_arena= t->expr_arena; + Query_arena backup_arena; + thd->set_n_backup_active_arena(t->expr_arena, &backup_arena); if (table->security_ctx) thd->security_ctx= table->security_ctx; - error= t->fix_vcol_exprs(thd); - thd->security_ctx= save_security_ctx; - thd->stmt_arena= stmt_backup; + thd->restore_active_arena(t->expr_arena, &backup_arena); } } DBUG_RETURN(error); diff --git a/sql/sql_class.h b/sql/sql_class.h index d3d54e11671..54c9d4ac870 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -967,7 +967,7 @@ public: /* We build without RTTI, so dynamic_cast can't be used. */ enum Type { - STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE, TABLE_ARENA + STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE }; Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) : @@ -3728,8 +3728,7 @@ public: bool is_item_tree_change_register_required() { - return !stmt_arena->is_conventional() - || stmt_arena->type() == Query_arena::TABLE_ARENA; + return !stmt_arena->is_conventional(); } void change_item_tree(Item **place, Item *new_value) diff --git a/sql/table.cc b/sql/table.cc index 1f7b6452303..81116cb19cc 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -47,17 +47,6 @@ #define MYSQL57_GENERATED_FIELD 128 #define MYSQL57_GCOL_HEADER_SIZE 4 -class Table_arena: public Query_arena -{ -public: - Table_arena(MEM_ROOT *mem_root, enum enum_state state_arg) : - Query_arena(mem_root, state_arg){} - virtual Type type() const - { - return TABLE_ARENA; - } -}; - static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *, TABLE *, String *, Virtual_column_info **, bool *); static bool check_vcol_forward_refs(Field *, Virtual_column_info *); @@ -1031,8 +1020,8 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, We need to use CONVENTIONAL_EXECUTION here to ensure that any new items created by fix_fields() are not reverted. */ - table->expr_arena= new (alloc_root(mem_root, sizeof(Table_arena))) - Table_arena(mem_root, + table->expr_arena= new (alloc_root(mem_root, sizeof(Query_arena))) + Query_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION); if (!table->expr_arena) DBUG_RETURN(1); From c274853c0797801de0398699d60c8579c45d1f61 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Apr 2022 21:54:19 +0200 Subject: [PATCH 06/94] MDEV-25638 Assertion `!result' failed in convert_const_to_int When fixing vcols, fix_fields might call convert_const_to_int(). And that will try to read the field value (from record[0]). Mark the table as having no data to prevent that, because record[0] is not initialized yet. --- mysql-test/r/check_constraint.result | 31 ++++++++++++++++++++++++++++ mysql-test/t/check_constraint.test | 19 +++++++++++++++++ sql/table.cc | 1 + 3 files changed, 51 insertions(+) diff --git a/mysql-test/r/check_constraint.result b/mysql-test/r/check_constraint.result index 988e49b274d..345441a71eb 100644 --- a/mysql-test/r/check_constraint.result +++ b/mysql-test/r/check_constraint.result @@ -236,6 +236,37 @@ insert t1 (b) values (1); ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1` drop table t1; # +# MDEV-25638 Assertion `!result' failed in convert_const_to_int +# +create table t1 (v1 bigint check (v1 not in ('x' , 'x111'))) ; +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +Warning 1292 Truncated incorrect DOUBLE value: 'x111' +select * from t1; +v1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +Warning 1292 Truncated incorrect DOUBLE value: 'x111' +select v1 from t1; +v1 +select * from t1; +v1 +prepare stmt from "select * from t1"; +execute stmt; +v1 +execute stmt; +v1 +flush tables; +select * from t1; +v1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +Warning 1292 Truncated incorrect DOUBLE value: 'x111' +select * from t1; +v1 +deallocate prepare stmt; +drop table t1; +# # MDEV-26061 MariaDB server crash at Field::set_default # create table t1 (v2 date check (v1 like default (v1)), v1 date default (from_days ('x'))); diff --git a/mysql-test/t/check_constraint.test b/mysql-test/t/check_constraint.test index 05145d9d434..70d5a0c73ca 100644 --- a/mysql-test/t/check_constraint.test +++ b/mysql-test/t/check_constraint.test @@ -177,6 +177,25 @@ select * from t1 where a is null; insert t1 (b) values (1); drop table t1; +--echo # +--echo # MDEV-25638 Assertion `!result' failed in convert_const_to_int +--echo # + +--enable_prepare_warnings +create table t1 (v1 bigint check (v1 not in ('x' , 'x111'))) ; +select * from t1; +select v1 from t1; +select * from t1; +prepare stmt from "select * from t1"; +execute stmt; +execute stmt; +flush tables; +select * from t1; +select * from t1; +deallocate prepare stmt; +drop table t1; +--disable_prepare_warnings + --echo # --echo # MDEV-26061 MariaDB server crash at Field::set_default --echo # diff --git a/sql/table.cc b/sql/table.cc index 81116cb19cc..a5f1a5d96cf 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3093,6 +3093,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, outparam->s= share; outparam->db_stat= db_stat; outparam->write_row_record= NULL; + outparam->status= STATUS_NO_RECORD; if (share->incompatible_version && !(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR))) From e4e25d2bacc067417c35750f5f6c44cad10c81de Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 14 Apr 2022 13:51:46 +0200 Subject: [PATCH 07/94] MDEV-26423 MariaDB server crash in Create_tmp_table::finalize Removed prohibition of creating temporary field of Item_default_value (added by mistake by 1d9b043a1f5db7ff229d5200652cff7a78ea6266 fix of MDEV-10780 and MDEV-11265). --- mysql-test/r/default.result | 9 +++++++++ mysql-test/r/default_innodb.result | 18 ++++++++++++++++++ mysql-test/t/default.test | 9 +++++++++ mysql-test/t/default_innodb.test | 22 ++++++++++++++++++++++ sql/item.h | 1 - 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/default_innodb.result create mode 100644 mysql-test/t/default_innodb.test diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index c7179e29723..0c91e6b7e08 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -3404,4 +3404,13 @@ ERROR 01000: Expression for field `a` is referring to uninitialized field `a` show warnings; Level Code Message Error 4029 Expression for field `a` is referring to uninitialized field `a` +# +# MDEV-26423: MariaDB server crash in Create_tmp_table::finalize +# +CREATE TABLE t1 (pk varchar(36) DEFAULT uuid()); +INSERT INTO t1 VALUES (),(); +SELECT 1 FROM t1 GROUP BY DEFAULT(pk); +1 +1 +DROP TABLE t1; # end of 10.2 test diff --git a/mysql-test/r/default_innodb.result b/mysql-test/r/default_innodb.result new file mode 100644 index 00000000000..81e9672df24 --- /dev/null +++ b/mysql-test/r/default_innodb.result @@ -0,0 +1,18 @@ +# +# MDEV-26423: MariaDB server crash in Create_tmp_table::finalize +# +CREATE TABLE v0 ( +v2 DATE DEFAULT ( v1 MOD 68321183.000000 ) , +v1 DATETIME NULL ) engine=innodb; +SHOW DATABASES LIKE 'x'; +Database (x) +SELECT DISTINCT v2 , v1 , DEFAULT ( v2 ) FROM v0; +v2 v1 DEFAULT ( v2 ) +DROP TABLE v0; +CREATE TABLE t1 (v1 DATE, v2 DATE DEFAULT(v1)) engine=innodb; +SELECT DISTINCT DEFAULT(v2) FROM t1 ; +DEFAULT(v2) +DROP TABLE t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index a4fe74aefb5..e0233a3929a 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -2116,4 +2116,13 @@ DROP TABLE t1; create table t1 (a int as (a)); show warnings; + +--echo # +--echo # MDEV-26423: MariaDB server crash in Create_tmp_table::finalize +--echo # + +CREATE TABLE t1 (pk varchar(36) DEFAULT uuid()); +INSERT INTO t1 VALUES (),(); +SELECT 1 FROM t1 GROUP BY DEFAULT(pk); +DROP TABLE t1; --echo # end of 10.2 test diff --git a/mysql-test/t/default_innodb.test b/mysql-test/t/default_innodb.test new file mode 100644 index 00000000000..2fc74950845 --- /dev/null +++ b/mysql-test/t/default_innodb.test @@ -0,0 +1,22 @@ + +--source include/have_innodb.inc + +--echo # +--echo # MDEV-26423: MariaDB server crash in Create_tmp_table::finalize +--echo # + +CREATE TABLE v0 ( + v2 DATE DEFAULT ( v1 MOD 68321183.000000 ) , + v1 DATETIME NULL ) engine=innodb; +SHOW DATABASES LIKE 'x'; +SELECT DISTINCT v2 , v1 , DEFAULT ( v2 ) FROM v0; +DROP TABLE v0; + +CREATE TABLE t1 (v1 DATE, v2 DATE DEFAULT(v1)) engine=innodb; +SELECT DISTINCT DEFAULT(v2) FROM t1 ; +DROP TABLE t1; + + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/item.h b/sql/item.h index 35454c69734..6b4ca89f3c7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5502,7 +5502,6 @@ public: if (field && field->default_value) field->default_value->expr->update_used_tables(); } - Field *get_tmp_table_field() { return 0; } Item *get_tmp_table_item(THD *thd) { return this; } Item_field *field_for_view_update() { return 0; } bool update_vcol_processor(void *arg) { return 0; } From 5aef0123a707415c56ffae48fc872e7d3ad292d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 19 Apr 2022 12:40:05 +0300 Subject: [PATCH 08/94] MDEV-28317 Assertion failures in row_undo_mod on recovery Starting with 10.3, an assertion would fail on the rollback of a recovered incomplete transaction if a table definition violates a FOREIGN KEY constraint. DICT_ERR_IGNORE_RECOVER_LOCK: Include also DICT_ERR_IGNORE_FK_NOKEY so that trx_resurrect_table_locks() will be able to load table definitions and resurrect IX locks. Previously, if the FOREIGN KEY constraints of a table were incomplete, the table would fail to load until rollback, and in 10.3 or later an assertion would fail that the rollback was not protected by a table IX lock. Thanks to commit 9de2e60d7491fcf3cd1f20a4be715ef0bedc316f there will be no problems to enforce subsequent FOREIGN KEY operations even though a table with invalid REFERENCES clause was loaded. --- mysql-test/suite/innodb/r/foreign_key.result | 27 ++++++++++++++++ mysql-test/suite/innodb/t/foreign_key.test | 34 ++++++++++++++++++++ storage/innobase/include/dict0types.h | 4 +-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index d6420118f34..dc958724fef 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -137,6 +137,33 @@ SELECT unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2'; unique_constraint_name PRIMARY +# +# MDEV-28317 Assertion failure on rollback of FOREIGN KEY operation +# +SET foreign_key_checks=0; +CREATE TABLE parent(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE child(a INT,FOREIGN KEY(a) REFERENCES parent(a) ON DELETE CASCADE) +ENGINE=InnoDB; +INSERT INTO child VALUES(1); +ALTER TABLE child DROP INDEX a; +connect incomplete, localhost, root,,; +BEGIN; +DELETE FROM child; +connection default; +INSERT INTO parent SET a=0; +FLUSH TABLES; +disconnect incomplete; +INSERT INTO child SET a=0; +INSERT INTO child SET a=1; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE) +DELETE FROM parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE) +ALTER TABLE child ADD INDEX(a); +DELETE FROM parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE) +ALTER TABLE child FORCE; +DELETE FROM parent; +DROP TABLE child,parent; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SELECT unique_constraint_name FROM information_schema.referential_constraints diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 1d4e5fd9d2a..af23dbdbb28 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -102,7 +102,41 @@ INSERT INTO t2 VALUES (1); SELECT unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2'; +--echo # +--echo # MDEV-28317 Assertion failure on rollback of FOREIGN KEY operation +--echo # + +SET foreign_key_checks=0; +CREATE TABLE parent(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE child(a INT,FOREIGN KEY(a) REFERENCES parent(a) ON DELETE CASCADE) +ENGINE=InnoDB; +INSERT INTO child VALUES(1); +ALTER TABLE child DROP INDEX a; + +connect(incomplete, localhost, root,,); +BEGIN; +DELETE FROM child; + +connection default; +INSERT INTO parent SET a=0; +FLUSH TABLES; + +--let $shutdown_timeout=0 --source include/restart_mysqld.inc +--let $shutdown_timeout= +disconnect incomplete; + +INSERT INTO child SET a=0; +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO child SET a=1; +--error ER_ROW_IS_REFERENCED_2 +DELETE FROM parent; +ALTER TABLE child ADD INDEX(a); +--error ER_ROW_IS_REFERENCED_2 +DELETE FROM parent; +ALTER TABLE child FORCE; +DELETE FROM parent; +DROP TABLE child,parent; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index bea08f398de..04c8b163b14 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2022, 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 @@ -64,7 +64,7 @@ enum dict_err_ignore_t { DICT_ERR_IGNORE_INDEX_ROOT = 2, /*!< ignore error if index root page is FIL_NULL or incorrect value */ DICT_ERR_IGNORE_CORRUPT = 4, /*!< skip corrupted indexes */ - DICT_ERR_IGNORE_RECOVER_LOCK = 8, + DICT_ERR_IGNORE_RECOVER_LOCK = 8 | DICT_ERR_IGNORE_FK_NOKEY, /*!< Used when recovering table locks for resurrected transactions. Silently load a missing From a59f483c06b12e606747da3f864ed94615f038c0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 16 Apr 2022 11:40:15 +0200 Subject: [PATCH 09/94] MDEV-28092 MariaDB SEGV issue add test --- mysql-test/suite/vcol/r/vcol_misc.result | 11 +++++++++++ mysql-test/suite/vcol/t/vcol_misc.test | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index 6c4975f2178..f13a20bf4c9 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -510,6 +510,17 @@ a b 13 14 DROP TABLE t1; SET sql_mode=DEFAULT; +create table t1 (b timestamp, a int as (1 in (dayofmonth (b between 'x' and current_user) = b))); +insert into t1(b) values ('2022-03-17 14:55:37'); +select 1 from t1 x natural join t1; +1 +1 +Warnings: +Warning 1292 Incorrect datetime value: 'x' +Warning 1292 Incorrect datetime value: 'root@localhost' +Warning 1292 Incorrect datetime value: 'x' +Warning 1292 Incorrect datetime value: 'root@localhost' +drop table t1; # # End of 10.2 tests # diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 07f96f4e0b8..821dd418e64 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -488,6 +488,14 @@ SELECT * FROM t1; DROP TABLE t1; SET sql_mode=DEFAULT; +# +# MDEV-28092 MariaDB SEGV issue +# +create table t1 (b timestamp, a int as (1 in (dayofmonth (b between 'x' and current_user) = b))); +insert into t1(b) values ('2022-03-17 14:55:37'); +select 1 from t1 x natural join t1; +drop table t1; + --echo # --echo # End of 10.2 tests --echo # From 9c5fd0f624df846686742182825d964c546fac58 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 16 Apr 2022 11:53:44 +0200 Subject: [PATCH 10/94] vcols: cannot use CONTEXT_ANALYSIS_ONLY_VCOL_EXPR on fix_fields because CONTEXT_ANALYSIS_ONLY_VCOL_EXPR can be used only for, exactly, context analysys. Items fixed that way cannot be evaluated. But vcols are going to be evaluated, so they have to be fixed properly, for evaluation. --- mysql-test/suite/vcol/r/vcol_misc.result | 22 +++++++++++++++++++++- mysql-test/suite/vcol/t/vcol_misc.opt | 1 + mysql-test/suite/vcol/t/vcol_misc.test | 15 +++++++++++++++ sql/item.h | 8 ++++++++ sql/sql_lex.cc | 1 - 5 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/vcol/t/vcol_misc.opt diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index f13a20bf4c9..f4790a7cbec 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -227,7 +227,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` bigint(20) DEFAULT NULL, - `b` bigint(20) GENERATED ALWAYS AS (`a` > '2') VIRTUAL + `b` bigint(20) GENERATED ALWAYS AS (`a` > 2) VIRTUAL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 insert into t1 (a) values (1),(3); select * from t1; @@ -522,5 +522,25 @@ Warning 1292 Incorrect datetime value: 'x' Warning 1292 Incorrect datetime value: 'root@localhost' drop table t1; # +# CONTEXT_ANALYSIS_ONLY_VCOL_EXPR +# +create table t1 (c1 char(1) character set ucs2 collate ucs2_test_ci, +v1 char(1) character set ucs2 collate ucs2_test_ci as (c1), +v2 int as (c1 = 'b'), +v3 int as (v1 = 'b')); +insert into t1 (c1) values ('a'); +select * from t1 where v1 = 'b'; +c1 v1 v2 v3 +a a 1 1 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` char(1) CHARACTER SET ucs2 COLLATE ucs2_test_ci DEFAULT NULL, + `v1` char(1) CHARACTER SET ucs2 GENERATED ALWAYS AS (`c1`) VIRTUAL, + `v2` int(11) GENERATED ALWAYS AS (`c1` = 'b') VIRTUAL, + `v3` int(11) GENERATED ALWAYS AS (`v1` = 'b') VIRTUAL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +# # End of 10.2 tests # diff --git a/mysql-test/suite/vcol/t/vcol_misc.opt b/mysql-test/suite/vcol/t/vcol_misc.opt new file mode 100644 index 00000000000..fd1faea4f8e --- /dev/null +++ b/mysql-test/suite/vcol/t/vcol_misc.opt @@ -0,0 +1 @@ +--character-sets-dir=$MYSQL_TEST_DIR/std_data/ldml/ diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 821dd418e64..b37b9e8f3d5 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -496,6 +496,21 @@ insert into t1(b) values ('2022-03-17 14:55:37'); select 1 from t1 x natural join t1; drop table t1; +--echo # +--echo # CONTEXT_ANALYSIS_ONLY_VCOL_EXPR +--echo # + +--source include/have_ucs2.inc +create table t1 (c1 char(1) character set ucs2 collate ucs2_test_ci, + v1 char(1) character set ucs2 collate ucs2_test_ci as (c1), + v2 int as (c1 = 'b'), + v3 int as (v1 = 'b')); +insert into t1 (c1) values ('a'); +select * from t1 where v1 = 'b'; +show create table t1; +drop table t1; + --echo # --echo # End of 10.2 tests --echo # + diff --git a/sql/item.h b/sql/item.h index 6b4ca89f3c7..07c17901afd 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5807,10 +5807,18 @@ public: } return mark_unsupported_function("cache", arg, VCOL_IMPOSSIBLE); } + bool fix_fields(THD *thd, Item **ref) + { + fixed= 1; + if (example && !example->fixed) + return example->fix_fields(thd, ref); + return 0; + } void cleanup() { clear(); Item_basic_constant::cleanup(); + fixed= 0; } /** Check if saved item has a non-NULL value. diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 47ff2836aba..22ee8801e3a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -193,7 +193,6 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex) return TRUE; context->resolve_in_table_list_only(table_list); lex->use_only_table_context= TRUE; - lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VCOL_EXPR; select_lex->cur_pos_in_select_list= UNDEF_POS; table->map= 1; //To ensure correct calculation of const item table_list->table= table; From 5ba77222e9fe7af8ff403816b5338b18b342053c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 19 Apr 2022 17:09:19 +0200 Subject: [PATCH 11/94] MDEV-21028 Server crashes in Query_arena::set_query_arena upon SELECT from view if the view has algorithm=temptable it is not updatable, so DEFAULT() for its fields is meaningless, and thus it's NULL or 0/'' for NOT NULL columns. --- mysql-test/r/func_default.result | 43 ++++++++++++++++++++++++++++++++ mysql-test/t/func_default.test | 26 +++++++++++++++++++ sql/sql_select.cc | 3 ++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_default.result b/mysql-test/r/func_default.result index 8721270ca1c..2b5c869ee66 100644 --- a/mysql-test/r/func_default.result +++ b/mysql-test/r/func_default.result @@ -159,5 +159,48 @@ a 10 DROP TABLE t1; # +# MDEV-21028 Server crashes in Query_arena::set_query_arena upon SELECT from view +# +create table t1 (a datetime default current_timestamp); +insert into t1 () values (),(); +create algorithm=temptable view v1 as select * from t1; +create algorithm=merge view v2 as select * from t1; +select default(a) = now() from v1; +default(a) = now() +NULL +NULL +select default(a) = now() from v2; +default(a) = now() +1 +1 +select table_name,is_updatable from information_schema.views; +table_name is_updatable +v1 NO +v2 YES +drop view v1, v2; +drop table t1; +create table t1 (v1 timestamp) select 'x'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `v1` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `x` varchar(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select default(v1) from (select v1 from t1) dt; +default(v1) +2001-01-01 10:20:30 +select default(v1) from (select v1 from t1 group by v1) dt; +default(v1) +0000-00-00 00:00:00 +drop table t1; +create table t1 (a text default ''); +create algorithm=temptable view v1 as select * from t1; +insert into t1 values ('a'); +select default(a) from v1; +default(a) +NULL +drop view v1; +drop table t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/func_default.test b/mysql-test/t/func_default.test index cba7842c68f..f542a279478 100644 --- a/mysql-test/t/func_default.test +++ b/mysql-test/t/func_default.test @@ -139,6 +139,32 @@ FROM t1; SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END IS FALSE; DROP TABLE t1; +--echo # +--echo # MDEV-21028 Server crashes in Query_arena::set_query_arena upon SELECT from view +--echo # +create table t1 (a datetime default current_timestamp); +insert into t1 () values (),(); +create algorithm=temptable view v1 as select * from t1; +create algorithm=merge view v2 as select * from t1; +select default(a) = now() from v1; +select default(a) = now() from v2; +select table_name,is_updatable from information_schema.views; +drop view v1, v2; +drop table t1; + +create table t1 (v1 timestamp) select 'x'; +show create table t1; +select default(v1) from (select v1 from t1) dt; +select default(v1) from (select v1 from t1 group by v1) dt; +drop table t1; + +create table t1 (a text default ''); +create algorithm=temptable view v1 as select * from t1; +insert into t1 values ('a'); +select default(a) from v1; +drop view v1; +drop table t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2a646a9931d..d2186f60709 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16333,7 +16333,8 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, table->s->db_create_options|= HA_OPTION_PACK_RECORD; else if (org_field->type() == FIELD_TYPE_DOUBLE) ((Field_double *) new_field)->not_fixed= TRUE; - new_field->vcol_info= 0; + new_field->vcol_info= new_field->default_value= + new_field->check_constraint= 0; new_field->cond_selectivity= 1.0; new_field->next_equal_field= NULL; new_field->option_list= NULL; From 2be617d869e614e2c0e7313fd77649a03c891cfd Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 13 Apr 2022 17:17:17 +0400 Subject: [PATCH 12/94] MDEV-25243 ASAN heap-use-after-free in Item_func_sp::execute_impl upon concurrent view DDL and I_S query with view and function --- .../r/information_schema_columns.result | 47 +++++++++ mysql-test/r/information_schema_tables.result | 77 +++++++++++++++ mysql-test/t/information_schema_columns.test | 48 ++++++++++ mysql-test/t/information_schema_tables.test | 95 +++++++++++++++++++ sql/sp_cache.cc | 12 +++ sql/sql_class.cc | 9 +- sql/sql_class.h | 50 +++++++++- sql/sql_show.cc | 31 +++++- 8 files changed, 358 insertions(+), 11 deletions(-) create mode 100644 mysql-test/r/information_schema_columns.result create mode 100644 mysql-test/r/information_schema_tables.result create mode 100644 mysql-test/t/information_schema_columns.test create mode 100644 mysql-test/t/information_schema_tables.test diff --git a/mysql-test/r/information_schema_columns.result b/mysql-test/r/information_schema_columns.result new file mode 100644 index 00000000000..3624a6db368 --- /dev/null +++ b/mysql-test/r/information_schema_columns.result @@ -0,0 +1,47 @@ +# +# Start of 10.2 tests +# +# +# MDEV-25243 ASAN heap-use-after-free in Item_func_sp::execute_impl upon concurrent view DDL and I_S query with view and function +# +CREATE FUNCTION f1() RETURNS INT RETURN 1; +CREATE VIEW v01 AS SELECT f1(); +CREATE VIEW v02 AS SELECT f1(); +connect con1,localhost,root,,; +SELECT GET_LOCK('v01',30); +GET_LOCK('v01',30) +1 +SELECT GET_LOCK('v02',30); +GET_LOCK('v02',30) +1 +connection default; +SELECT * FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_SCHEMA='test' + AND TABLE_NAME LIKE 'v0%' + AND GET_LOCK(TABLE_NAME,30) +AND RELEASE_LOCK(TABLE_NAME) +AND f1()=1 +ORDER BY TABLE_NAME; +connection con1; +connection con1; +SELECT RELEASE_LOCK('v01') /* Let the first row evaluate f1 */; +RELEASE_LOCK('v01') +1 +CREATE FUNCTION f2() RETURNS INT RETURN 1 /* Invalidate SP cache*/; +SELECT RELEASE_LOCK('v02') /* Let the second row evaluate f1() */; +RELEASE_LOCK('v02') +1 +DROP FUNCTION f2; +disconnect con1; +connection default; +SELECT RELEASE_LOCK('v01'); +RELEASE_LOCK('v01') +NULL +SELECT RELEASE_LOCK('v02'); +RELEASE_LOCK('v02') +NULL +DROP VIEW v01, v02; +DROP FUNCTION f1; +# +# End of 10.2 tests +# diff --git a/mysql-test/r/information_schema_tables.result b/mysql-test/r/information_schema_tables.result new file mode 100644 index 00000000000..33dafaa39eb --- /dev/null +++ b/mysql-test/r/information_schema_tables.result @@ -0,0 +1,77 @@ +# +# Start of 10.2 tests +# +# +# MDEV-25243 ASAN heap-use-after-free in Item_func_sp::execute_impl upon concurrent view DDL and I_S query with view and function +# +# The originally reported non-deterministic test. +# It did not fail reliably on every run. +CREATE TABLE t (a INT); +INSERT INTO t VALUES (1),(2); +CREATE FUNCTION f(b INT) RETURNS INT RETURN 1; +CREATE VIEW v AS SELECT f(SUM(a)) FROM t; +connect con1,localhost,root,,test; +LOOP +CREATE OR REPLACE VIEW vv AS SELECT 1; +END LOOP $ +connection default; +SELECT v.* FROM v JOIN INFORMATION_SCHEMA.TABLES WHERE DATA_LENGTH = -1; +f(SUM(a)) +KILL CONID; +disconnect con1; +connection default; +DROP VIEW IF EXISTS vv; +DROP VIEW v; +DROP FUNCTION f; +DROP TABLE t; +# The second test version from the MDEV. +# It failed more reliably, but still was not deterministic. +CREATE FUNCTION f() RETURNS INT RETURN 1; +CREATE VIEW v AS SELECT f() FROM seq_1_to_10; +SELECT * FROM INFORMATION_SCHEMA.TABLES, v;; +connect con1,localhost,root,,; +CREATE VIEW v2 AS SELECT 1; +connection default; +disconnect con1; +DROP VIEW v; +DROP VIEW v2; +DROP FUNCTION f; +# The third test version from the MDEV. +# It failed reliably, and should be deterninistic. +CREATE FUNCTION f1() RETURNS INT RETURN 1; +CREATE VIEW v01 AS SELECT f1(); +CREATE VIEW v02 AS SELECT f1(); +connect con1,localhost,root,,; +SELECT GET_LOCK('v01',30); +GET_LOCK('v01',30) +1 +SELECT GET_LOCK('v02',30); +GET_LOCK('v02',30) +1 +connection default; +SELECT * FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA='test' + AND TABLE_NAME LIKE 'v0%' + AND GET_LOCK(TABLE_NAME,30) +AND RELEASE_LOCK(TABLE_NAME) +AND f1()=1 +ORDER BY TABLE_NAME; +connection con1; +SELECT RELEASE_LOCK('v01') /* Let the first row evaluate f1 */; +RELEASE_LOCK('v01') +1 +CREATE FUNCTION f2() RETURNS INT RETURN 1 /* Invalidate SP cache*/; +SELECT RELEASE_LOCK('v02') /* Let the second row evaluate f1() */; +RELEASE_LOCK('v02') +1 +DROP FUNCTION f2; +disconnect con1; +connection default; +TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT +def test v01 VIEW NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL VIEW +def test v02 VIEW NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL VIEW +DROP VIEW v01, v02; +DROP FUNCTION f1; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/information_schema_columns.test b/mysql-test/t/information_schema_columns.test new file mode 100644 index 00000000000..0171b221110 --- /dev/null +++ b/mysql-test/t/information_schema_columns.test @@ -0,0 +1,48 @@ +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-25243 ASAN heap-use-after-free in Item_func_sp::execute_impl upon concurrent view DDL and I_S query with view and function +--echo # + + +CREATE FUNCTION f1() RETURNS INT RETURN 1; +CREATE VIEW v01 AS SELECT f1(); +CREATE VIEW v02 AS SELECT f1(); + +--connect(con1,localhost,root,,) +SELECT GET_LOCK('v01',30); +SELECT GET_LOCK('v02',30); +--connection default + +--send + SELECT * FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA='test' + AND TABLE_NAME LIKE 'v0%' + AND GET_LOCK(TABLE_NAME,30) + AND RELEASE_LOCK(TABLE_NAME) + AND f1()=1 + ORDER BY TABLE_NAME; + +--connection con1 +--connection con1 +SELECT RELEASE_LOCK('v01') /* Let the first row evaluate f1 */; +CREATE FUNCTION f2() RETURNS INT RETURN 1 /* Invalidate SP cache*/; +SELECT RELEASE_LOCK('v02') /* Let the second row evaluate f1() */; +DROP FUNCTION f2; +--disconnect con1 + +--connection default +--disable_result_log +--reap +--enable_result_log +SELECT RELEASE_LOCK('v01'); +SELECT RELEASE_LOCK('v02'); + +DROP VIEW v01, v02; +DROP FUNCTION f1; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/t/information_schema_tables.test b/mysql-test/t/information_schema_tables.test new file mode 100644 index 00000000000..ebb1e21a65b --- /dev/null +++ b/mysql-test/t/information_schema_tables.test @@ -0,0 +1,95 @@ +--source include/have_sequence.inc + +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-25243 ASAN heap-use-after-free in Item_func_sp::execute_impl upon concurrent view DDL and I_S query with view and function +--echo # + +--echo # The originally reported non-deterministic test. +--echo # It did not fail reliably on every run. + +CREATE TABLE t (a INT); +INSERT INTO t VALUES (1),(2); +CREATE FUNCTION f(b INT) RETURNS INT RETURN 1; +CREATE VIEW v AS SELECT f(SUM(a)) FROM t; +--connect (con1,localhost,root,,test) +--let $conid= `SELECT CONNECTION_ID()` +--delimiter $ +--send +LOOP + CREATE OR REPLACE VIEW vv AS SELECT 1; +END LOOP $ +--delimiter ; +--connection default +--disable_warnings +SELECT v.* FROM v JOIN INFORMATION_SCHEMA.TABLES WHERE DATA_LENGTH = -1; +--enable_warnings +# Cleanup +--replace_result $conid CONID +--eval KILL $conid +--disconnect con1 +--connection default +DROP VIEW IF EXISTS vv; +DROP VIEW v; +DROP FUNCTION f; +DROP TABLE t; + + +--echo # The second test version from the MDEV. +--echo # It failed more reliably, but still was not deterministic. + + +CREATE FUNCTION f() RETURNS INT RETURN 1; +CREATE VIEW v AS SELECT f() FROM seq_1_to_10; +--send SELECT * FROM INFORMATION_SCHEMA.TABLES, v; +--connect(con1,localhost,root,,) +CREATE VIEW v2 AS SELECT 1; +--connection default +--disable_result_log +--reap +--enable_result_log +--disconnect con1 +DROP VIEW v; +DROP VIEW v2; +DROP FUNCTION f; + +--echo # The third test version from the MDEV. +--echo # It failed reliably, and should be deterninistic. + +CREATE FUNCTION f1() RETURNS INT RETURN 1; +CREATE VIEW v01 AS SELECT f1(); +CREATE VIEW v02 AS SELECT f1(); + +--connect(con1,localhost,root,,) +SELECT GET_LOCK('v01',30); +SELECT GET_LOCK('v02',30); +--connection default + +--send + SELECT * FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA='test' + AND TABLE_NAME LIKE 'v0%' + AND GET_LOCK(TABLE_NAME,30) + AND RELEASE_LOCK(TABLE_NAME) + AND f1()=1 + ORDER BY TABLE_NAME; + +--connection con1 +SELECT RELEASE_LOCK('v01') /* Let the first row evaluate f1 */; +CREATE FUNCTION f2() RETURNS INT RETURN 1 /* Invalidate SP cache*/; +SELECT RELEASE_LOCK('v02') /* Let the second row evaluate f1() */; +DROP FUNCTION f2; +--disconnect con1 +--connection default +--reap + + +DROP VIEW v01, v02; +DROP FUNCTION f1; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index bc91634eb32..9829167d29d 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -313,3 +313,15 @@ sp_cache::cleanup() { my_hash_free(&m_hashtable); } + + +void Sp_caches::sp_caches_clear() +{ + sp_cache_clear(&sp_proc_cache); + sp_cache_clear(&sp_func_cache); +#if MYSQL_VERSION_ID >= 100300 +#error Remove the preprocessor condition, !!!but keep the code!!! + sp_cache_clear(&sp_package_spec_cache); + sp_cache_clear(&sp_package_body_cache); +#endif +} diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4edf573e596..aa64e42e144 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -806,9 +806,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) (my_hash_get_key) get_var_key, (my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC); - sp_proc_cache= NULL; - sp_func_cache= NULL; - /* For user vars replication*/ if (opt_bin_log) my_init_dynamic_array(&user_var_events, @@ -1353,8 +1350,7 @@ void THD::change_user(void) my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key, (my_hash_free_key) free_user_var, 0); - sp_cache_clear(&sp_proc_cache); - sp_cache_clear(&sp_func_cache); + sp_caches_clear(); } @@ -1410,8 +1406,7 @@ void THD::cleanup(void) #endif /* defined(ENABLED_DEBUG_SYNC) */ my_hash_free(&user_vars); - sp_cache_clear(&sp_proc_cache); - sp_cache_clear(&sp_func_cache); + sp_caches_clear(); auto_inc_intervals_forced.empty(); auto_inc_intervals_in_cur_stmt_for_binlog.empty(); diff --git a/sql/sql_class.h b/sql/sql_class.h index 54c9d4ac870..cceefb1793c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2116,6 +2116,51 @@ struct wait_for_commit }; +class Sp_caches +{ +public: + sp_cache *sp_proc_cache; + sp_cache *sp_func_cache; +#if MYSQL_VERSION_ID >= 100300 +#error Remove the preprocessor condition, !!!but keep the code!!! + sp_cache *sp_package_spec_cache; + sp_cache *sp_package_body_cache; +#endif + Sp_caches() + :sp_proc_cache(NULL), + sp_func_cache(NULL) +#if MYSQL_VERSION_ID >= 100300 +#error Remove the preprocessor condition, !!!but keep the code!!! + , + sp_package_spec_cache(NULL), + sp_package_body_cache(NULL) +#endif + { } + ~Sp_caches() + { + // All caches must be freed by the caller explicitly + DBUG_ASSERT(sp_proc_cache == NULL); + DBUG_ASSERT(sp_func_cache == NULL); +#if MYSQL_VERSION_ID >= 100300 +#error Remove the preprocessor condition, !!!but keep the code!!! + DBUG_ASSERT(sp_package_spec_cache == NULL); + DBUG_ASSERT(sp_package_body_cache == NULL); +#endif + } + void sp_caches_swap(Sp_caches &rhs) + { + swap_variables(sp_cache*, sp_proc_cache, rhs.sp_proc_cache); + swap_variables(sp_cache*, sp_func_cache, rhs.sp_func_cache); +#if MYSQL_VERSION_ID >= 100300 +#error Remove the preprocessor condition, !!!but keep the code!!! + swap_variables(sp_cache*, sp_package_spec_cache, rhs.sp_package_spec_cache); + swap_variables(sp_cache*, sp_package_body_cache, rhs.sp_package_body_cache); +#endif + } + void sp_caches_clear(); +}; + + extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); class THD; @@ -2139,7 +2184,8 @@ class THD :public Statement, */ public Item_change_list, public MDL_context_owner, - public Open_tables_state + public Open_tables_state, + public Sp_caches { private: inline bool is_stmt_prepare() const @@ -3089,8 +3135,6 @@ public: int slave_expected_error; sp_rcontext *spcont; // SP runtime context - sp_cache *sp_proc_cache; - sp_cache *sp_func_cache; /** number of name_const() substitutions, see sp_head.cc:subst_spvars() */ uint query_name_consts; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index c708849d049..ee295eb3834 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4907,6 +4907,7 @@ public: int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) { + DBUG_ENTER("get_all_tables"); LEX *lex= thd->lex; TABLE *table= tables->table; TABLE_LIST table_acl_check; @@ -4923,7 +4924,28 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) #endif uint table_open_method= tables->table_open_method; bool can_deadlock; - DBUG_ENTER("get_all_tables"); + /* + We're going to open FRM files for tables. + In case of VIEWs that contain stored function calls, + these stored functions will be parsed and put to the SP cache. + + Suppose we have a view containing a stored function call: + CREATE VIEW v1 AS SELECT f1() AS c1; + and now we're running: + SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=f1(); + If a parallel thread invalidates the cache, + e.g. by creating or dropping some stored routine, + the SELECT query will re-parse f1() when processing "v1" + and replace the outdated cached version of f1() to a new one. + But the old version of f1() is referenced from the m_sp member + of the Item_func_sp instances used in the WHERE condition. + We cannot destroy it. To avoid such clashes, let's remember + all old routines into a temporary SP cache collection + and process tables with a new empty temporary SP cache collection. + Then restore to the old SP cache collection at the end. + */ + Sp_caches old_sp_caches; + old_sp_caches.sp_caches_swap(*thd); /* In cases when SELECT from I_S table being filled by this call is @@ -5092,6 +5114,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) err: thd->restore_backup_open_tables_state(&open_tables_state_backup); + /* + Now restore to the saved SP cache collection + and clear the temporary SP cache collection. + */ + old_sp_caches.sp_caches_swap(*thd); + old_sp_caches.sp_caches_clear(); + DBUG_RETURN(error); } From 4d1129006500ebc0febe173308cc09190238e91b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 21 Apr 2022 10:06:01 +0200 Subject: [PATCH 13/94] .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9af0e967db7..57e50ad2e46 100644 --- a/.gitignore +++ b/.gitignore @@ -125,6 +125,7 @@ scripts/mysqld_safe scripts/mysqldumpslow scripts/mysqlhotcopy scripts/mytop +scripts/wsrep_sst_backup scripts/wsrep_sst_common scripts/wsrep_sst_mysqldump scripts/wsrep_sst_rsync From 188aae65e4fa43b73ee1af6ce26724c3dca61380 Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Tue, 12 Apr 2022 13:39:04 +0300 Subject: [PATCH 14/94] MDEV-26224 InnoDB fails to remove AUTO_INCREMENT attribute Reset dict_table_t::persistent_autoinc when inplace alter table is committed successfully. --- .../innodb/r/alter_persistent_autoinc.result | 42 +++++++++ .../innodb/t/alter_persistent_autoinc.test | 86 +++++++++++++++++++ sql/ha_partition.cc | 11 ++- storage/innobase/handler/handler0alter.cc | 16 +++- 4 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/innodb/r/alter_persistent_autoinc.result create mode 100644 mysql-test/suite/innodb/t/alter_persistent_autoinc.test diff --git a/mysql-test/suite/innodb/r/alter_persistent_autoinc.result b/mysql-test/suite/innodb/r/alter_persistent_autoinc.result new file mode 100644 index 00000000000..52ac4d83ad9 --- /dev/null +++ b/mysql-test/suite/innodb/r/alter_persistent_autoinc.result @@ -0,0 +1,42 @@ +CREATE TABLE t1 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB; +ALTER TABLE t1 MODIFY c INT NULL, ALGORITHM=INSTANT; +INSERT INTO t1 SET c=1; +CREATE TABLE t2 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB; +ALTER TABLE t2 MODIFY c INT NULL, FORCE, ALGORITHM=INPLACE; +INSERT INTO t2 SET c=1; +CREATE TABLE t3 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB; +ALTER TABLE t3 MODIFY c INT NULL, ALGORITHM=INPLACE; +INSERT INTO t3 SET c=1; +CREATE TABLE t4 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB; +ALTER TABLE t4 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE; +INSERT INTO t4 SET c1=1; +CREATE TABLE t5 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT, c3 INTEGER GENERATED ALWAYS AS (c2)) ENGINE=InnoDB; +ALTER TABLE t5 MODIFY c1 INT NULL, MODIFY COLUMN c2 INT FIRST, ALGORITHM=INPLACE; +INSERT INTO t5 SET c1=1; +CREATE TABLE t6 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB +PARTITION BY LIST(c) ( +PARTITION p1 VALUES IN (1), +PARTITION p2 VALUES IN (2) +); +ALTER TABLE t6 MODIFY c INT NULL, ALGORITHM=INSTANT; +INSERT INTO t6 SET c=1; +INSERT INTO t6 SET c=2; +CREATE TABLE t7 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB +PARTITION BY LIST(c) ( +PARTITION p1 VALUES IN (1), +PARTITION p2 VALUES IN (2) +); +ALTER TABLE t7 MODIFY c INT NULL, ALGORITHM=INPLACE; +INSERT INTO t7 SET c=1; +INSERT INTO t7 SET c=2; +CREATE TABLE t8 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB +PARTITION BY LIST(c1) ( +PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2)); +ALTER TABLE t8 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE; +INSERT INTO t8 SET c1=1; +INSERT INTO t8 SET c1=2; +FLUSH TABLES t1, t2, t3, t4, t5, t6, t7, t8 FOR EXPORT; +AUTO_INCREMENT not partitioned: 0 0 0 0 0 +AUTO_INCREMENT partitioned: (0, 0) (0, 0) (0, 0) +UNLOCK TABLES; +DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8; diff --git a/mysql-test/suite/innodb/t/alter_persistent_autoinc.test b/mysql-test/suite/innodb/t/alter_persistent_autoinc.test new file mode 100644 index 00000000000..dcaea32700c --- /dev/null +++ b/mysql-test/suite/innodb/t/alter_persistent_autoinc.test @@ -0,0 +1,86 @@ +# Test the ability to remove AUTO_INCREMENT attribute +--source include/have_innodb.inc +--source include/have_partition.inc + +CREATE TABLE t1 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB; +ALTER TABLE t1 MODIFY c INT NULL, ALGORITHM=INSTANT; +INSERT INTO t1 SET c=1; + +CREATE TABLE t2 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB; +ALTER TABLE t2 MODIFY c INT NULL, FORCE, ALGORITHM=INPLACE; +INSERT INTO t2 SET c=1; + +CREATE TABLE t3 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB; +ALTER TABLE t3 MODIFY c INT NULL, ALGORITHM=INPLACE; +INSERT INTO t3 SET c=1; + +CREATE TABLE t4 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB; +ALTER TABLE t4 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE; +INSERT INTO t4 SET c1=1; + +CREATE TABLE t5 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT, c3 INTEGER GENERATED ALWAYS AS (c2)) ENGINE=InnoDB; +# ha_innobase::commit_inplace_alter_table() should invoke innobase_reload_table() +ALTER TABLE t5 MODIFY c1 INT NULL, MODIFY COLUMN c2 INT FIRST, ALGORITHM=INPLACE; +INSERT INTO t5 SET c1=1; + +CREATE TABLE t6 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB + PARTITION BY LIST(c) ( + PARTITION p1 VALUES IN (1), + PARTITION p2 VALUES IN (2) + ); +ALTER TABLE t6 MODIFY c INT NULL, ALGORITHM=INSTANT; +INSERT INTO t6 SET c=1; +INSERT INTO t6 SET c=2; + +CREATE TABLE t7 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB + PARTITION BY LIST(c) ( + PARTITION p1 VALUES IN (1), + PARTITION p2 VALUES IN (2) + ); +ALTER TABLE t7 MODIFY c INT NULL, ALGORITHM=INPLACE; +INSERT INTO t7 SET c=1; +INSERT INTO t7 SET c=2; + +CREATE TABLE t8 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB + PARTITION BY LIST(c1) ( + PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2)); +ALTER TABLE t8 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE; +INSERT INTO t8 SET c1=1; +INSERT INTO t8 SET c1=2; + +FLUSH TABLES t1, t2, t3, t4, t5, t6, t7, t8 FOR EXPORT; + +--let INNODB_PAGE_SIZE=`select @@innodb_page_size` +--let MYSQLD_DATADIR = `SELECT @@datadir` + +--perl +my $ps= $ENV{INNODB_PAGE_SIZE}; +my $PAGE_HEADER = 38; +my $PAGE_ROOT_AUTO_INC = 18; +print "AUTO_INCREMENT not partitioned: "; +for (my $i = 1; $i <= 5; ++$i) { + my $autoinc= read_autoinc("$ENV{MYSQLD_DATADIR}/test/t$i.ibd"); + print "$autoinc "; +} +print "\n"; +print "AUTO_INCREMENT partitioned: "; +for (my $i = 6; $i <= 8; ++$i) { + my $p1= read_autoinc("$ENV{MYSQLD_DATADIR}/test/t$i#P#p1.ibd"); + my $p2= read_autoinc("$ENV{MYSQLD_DATADIR}/test/t$i#P#p2.ibd"); + print "($p1, $p2) "; +} +print "\n"; +sub read_autoinc { + my $file= shift; + open(FILE, "<", $file) || die "Unable to open $file\n"; + sysseek(FILE, 3*$ps + $PAGE_HEADER + $PAGE_ROOT_AUTO_INC + 4, 0) + || die "Unable to seek $file\n"; + die "Unable to read $file\n" unless sysread(FILE, $_, 4) == 4; + my $t1=unpack("N",$_); + close(FILE); + return $t1; +} +EOF + +UNLOCK TABLES; +DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index ac6f4696895..0fcf966f71b 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -10437,7 +10437,16 @@ bool ha_partition::commit_inplace_alter_table(TABLE *altered_table, Loop over all other partitions as to follow the protocol! */ uint i; - DBUG_ASSERT(0); + /* + InnoDB does not set ha_alter_info->group_commit_ctx to NULL in the + case if autoincrement attribute is necessary to reset for all + partitions for INNOBASE_INPLACE_IGNORE handler flags. It does not + affect durability, because it is solely about updating the InnoDB data + dictionary caches (one InnoDB dict_table_t per partition or + sub-partition). + */ + DBUG_ASSERT(table->found_next_number_field + && !altered_table->found_next_number_field); for (i= 1; i < m_tot_parts; i++) { ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[i]; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index e79d9d67dbf..91a5fd3ca4a 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -10711,6 +10711,10 @@ commit_cache_norebuild( : NULL; DBUG_ASSERT((ctx->new_table->fts == NULL) == (ctx->new_table->fts_doc_id_index == NULL)); + if (table->found_next_number_field + && !altered_table->found_next_number_field) { + ctx->prebuilt->table->persistent_autoinc = 0; + } DBUG_RETURN(found); } @@ -11035,7 +11039,15 @@ ha_innobase::commit_inplace_alter_table( if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) { DBUG_ASSERT(!ctx0); MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE); - ha_alter_info->group_commit_ctx = NULL; + if (table->found_next_number_field + && !altered_table->found_next_number_field) { + m_prebuilt->table->persistent_autoinc = 0; + /* Don't reset ha_alter_info->group_commit_ctx to make + partitions engine to call this function for all + partitions. */ + } + else + ha_alter_info->group_commit_ctx = NULL; DBUG_RETURN(false); } @@ -11543,6 +11555,8 @@ foreign_fail: row_mysql_unlock_data_dictionary(trx); trx->free(); MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE); + /* There is no need to reset dict_table_t::persistent_autoinc + as the table is reloaded */ DBUG_RETURN(false); } From 32041e7058db02dd312833a0bfc50437a64546ea Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 22 Apr 2022 16:29:19 +1000 Subject: [PATCH 15/94] MDEV-28227 Error message Chinese translation (typos) Thanks Marko for noticing. --- sql/share/errmsg-utf8.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index dd95f2171b0..4fe847fd4bb 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7681,11 +7681,11 @@ ER_TABLE_IN_SYSTEM_TABLESPACE eng "Table %-.192s in system tablespace" ER_IO_READ_ERROR - chi "IO读取错误:(%lu,%s)%s" + chi "IO读取错误:(%lu,%s)%s" eng "IO Read error: (%lu, %s) %s" ER_IO_WRITE_ERROR - chi "IO写错错误:(%lu,%s)%s" + chi "IO写错错误:(%lu,%s)%s" eng "IO Write error: (%lu, %s) %s" ER_TABLESPACE_MISSING @@ -8570,7 +8570,7 @@ ER_REF_TO_RECURSIVE_WITH_TABLE_IN_DERIVED eng "Reference to recursive WITH table '%s' in materialized derived" ER_NOT_STANDARD_COMPLIANT_RECURSIVE chi "表'%s'R_WRONG_WINDOW_SPEC_NAME违反了递归定义的限制" - eng "Restrictions imposed on recursive definitions are violated for table '%s'"R_WRONG_WINDOW_SPEC_NAME + eng "Restrictions imposed on recursive definitions are violated for table '%s'" ER_WRONG_WINDOW_SPEC_NAME chi "没有定义名称'%s'的窗口规范" eng "Window specification with name '%s' is not defined" From 3c209bfc040ddfc41ece8357d772547432353fd2 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 21 Apr 2022 15:03:23 +0300 Subject: [PATCH 16/94] MDEV-25994: Crash with union of my_decimal type in ORDER BY clause When single-row subquery fails with "Subquery reutrns more than 1 row" error, it will raise an error and return NULL. On the other hand, Item_singlerow_subselect sets item->maybe_null=0 for table-less subqueries like "(SELECT not_null_value)" (*) This discrepancy (item with maybe_null=0 returning NULL) causes the code in Type_handler_decimal_result::make_sort_key_part() to crash. Fixed this by allowing inference (*) only when the subquery is NOT a UNION. --- mysql-test/r/order_by.result | 20 +++++++++++++++ mysql-test/r/subselect.result | 2 +- mysql-test/r/subselect_no_exists_to_in.result | 2 +- mysql-test/r/subselect_no_mat.result | 2 +- mysql-test/r/subselect_no_opts.result | 2 +- mysql-test/r/subselect_no_scache.result | 2 +- mysql-test/r/subselect_no_semijoin.result | 2 +- mysql-test/t/order_by.test | 25 +++++++++++++++++++ sql/item_subselect.cc | 15 ++++++++--- 9 files changed, 62 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index d1f2d067643..b21e350ac4a 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -3508,4 +3508,24 @@ DELETE FROM t1 ORDER BY c; DROP TABLE t1; SET @@SESSION.max_sort_length=DEFAULT; SET sql_mode=DEFAULT; +# +# MDEV-25994 Crash with union of my_decimal type in ORDER BY clause +# +CREATE TABLE t1 (v1 INTEGER) ; +INSERT INTO t1 (v1) VALUES (8); +UPDATE t1 SET v1 = 1 ORDER BY (SELECT 1.1 UNION SELECT -1); +ERROR 21000: Subquery returns more than 1 row +# This one must be successful +UPDATE t1 SET v1 = 2 ORDER BY (SELECT 1 UNION SELECT 1); +UPDATE t1 SET v1 = 3 ORDER BY (SELECT 'a' UNION SELECT 'b'); +ERROR 21000: Subquery returns more than 1 row +# Insert some more data +INSERT INTO t1 (v1) VALUES (8),(9),(100),(-234),(46584),(0); +UPDATE t1 SET v1 = v1+1 ORDER BY (SELECT 100.122 UNION SELECT -189.2); +ERROR 21000: Subquery returns more than 1 row +# This one must be successful +UPDATE t1 SET v1 = v1-200 ORDER BY (SELECT 1 UNION SELECT 1); +UPDATE t1 SET v1 = v1 ORDER BY (SELECT 'abc' UNION SELECT 'bbb'); +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1; # End of 10.2 tests diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a03a2cff207..ed3b49ff40d 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1261,7 +1261,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(20) NOT NULL + `a` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int); diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result index f7da3fdb2e2..499cad5538a 100644 --- a/mysql-test/r/subselect_no_exists_to_in.result +++ b/mysql-test/r/subselect_no_exists_to_in.result @@ -1265,7 +1265,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(20) NOT NULL + `a` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int); diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 6ab304c190b..a6e97636eed 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -1268,7 +1268,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(20) NOT NULL + `a` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int); diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 338ddd5808b..571d0553212 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -1264,7 +1264,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(20) NOT NULL + `a` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int); diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index 741b070a38b..b2b25c3efa8 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -1267,7 +1267,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(20) NOT NULL + `a` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int); diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index ebabafb9c77..af8df6a6331 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -1264,7 +1264,7 @@ a SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(20) NOT NULL + `a` bigint(20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int); diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 7cb24b7d03b..2187786deb7 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -2331,5 +2331,30 @@ DROP TABLE t1; SET @@SESSION.max_sort_length=DEFAULT; SET sql_mode=DEFAULT; +--echo # +--echo # MDEV-25994 Crash with union of my_decimal type in ORDER BY clause +--echo # + +CREATE TABLE t1 (v1 INTEGER) ; +INSERT INTO t1 (v1) VALUES (8); +--error ER_SUBQUERY_NO_1_ROW +UPDATE t1 SET v1 = 1 ORDER BY (SELECT 1.1 UNION SELECT -1); +--echo # This one must be successful +UPDATE t1 SET v1 = 2 ORDER BY (SELECT 1 UNION SELECT 1); +--error ER_SUBQUERY_NO_1_ROW +UPDATE t1 SET v1 = 3 ORDER BY (SELECT 'a' UNION SELECT 'b'); + +-- echo # Insert some more data +INSERT INTO t1 (v1) VALUES (8),(9),(100),(-234),(46584),(0); +--error ER_SUBQUERY_NO_1_ROW +UPDATE t1 SET v1 = v1+1 ORDER BY (SELECT 100.122 UNION SELECT -189.2); +--echo # This one must be successful +UPDATE t1 SET v1 = v1-200 ORDER BY (SELECT 1 UNION SELECT 1); +--error ER_SUBQUERY_NO_1_ROW +UPDATE t1 SET v1 = v1 ORDER BY (SELECT 'abc' UNION SELECT 'bbb'); + + +DROP TABLE t1; + --echo # End of 10.2 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index e01c92b7a4f..7033d38c07b 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1266,11 +1266,18 @@ bool Item_singlerow_subselect::fix_length_and_dec() } unsigned_flag= value->unsigned_flag; /* - If there are not tables in subquery then ability to have NULL value - depends on SELECT list (if single row subquery have tables then it - always can be NULL if there are not records fetched). + If the subquery has no tables (1) and is not a UNION (2), like: + + (SELECT subq_value) + + then its NULLability is the same as subq_value's NULLability. + + (1): A subquery that uses a table will return NULL when the table is empty. + (2): A UNION subquery will return NULL if it produces a "Subquery returns + more than one row" error. */ - if (engine->no_tables()) + if (engine->no_tables() && + engine->engine_type() != subselect_engine::UNION_ENGINE) maybe_null= engine->may_be_null(); else { From bc7ba7afee8ba6f7d8fe61078d4c46184dc6fa56 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Fri, 22 Apr 2022 18:47:19 +0700 Subject: [PATCH 17/94] MDEV-27758: Errors when building Connect engine on os x 11.6.2 Added checking for support of vfork by a platform where building being done. Set HAVE_VFORK macros in case vfork() system call is supported. Use vfork() system call if the macros HAVE_VFORK is set, else use fork(). --- config.h.cmake | 2 ++ configure.cmake | 16 ++++++++++++++++ storage/connect/tabrest.cpp | 6 +++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/config.h.cmake b/config.h.cmake index c74592b4a65..3a43c6132f0 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -577,3 +577,5 @@ #endif // !defined(__STDC_FORMAT_MACROS) #endif + +#cmakedefine HAVE_VFORK 1 diff --git a/configure.cmake b/configure.cmake index 942d5780ed9..3ac42e8e3e4 100644 --- a/configure.cmake +++ b/configure.cmake @@ -1033,3 +1033,19 @@ IF(NOT MSVC) HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE ) ENDIF() + +MY_CHECK_C_COMPILER_FLAG("-Werror") +IF(have_C__Werror) + SET(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror") + CHECK_C_SOURCE_COMPILES(" + #include + int main() + { + pid_t pid=vfork(); + return (int)pid; + }" + HAVE_VFORK + ) + SET(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS}) +ENDIF() diff --git a/storage/connect/tabrest.cpp b/storage/connect/tabrest.cpp index c66d8d76f3d..7e8b51714fb 100644 --- a/storage/connect/tabrest.cpp +++ b/storage/connect/tabrest.cpp @@ -112,7 +112,11 @@ int Xcurl(PGLOBAL g, PCSZ Http, PCSZ Uri, PCSZ filename) } // endif f - pID = vfork(); +#ifdef HAVE_VFORK + pID = vfork(); +#else + pID = fork(); +#endif sprintf(fn, "-o%s", filename); if (pID == 0) { From 88a9f13a9004180d447dfd405bcc4c0139308a04 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Fri, 22 Apr 2022 15:49:37 +0300 Subject: [PATCH 18/94] MDEV-25546 LIMIT partitioning does not respect ROLLBACK vers_info->hist_part retained stale value after ROLLBACK. The algorithm in vers_set_hist_part() continued iteration from that value. The simplest solution is to process partitions each time from start for LIMIT in vers_set_hist_part(). --- .../suite/versioning/r/partition.result | 41 ++++++++++++++++++ mysql-test/suite/versioning/t/partition.test | 42 +++++++++++++++++++ sql/partition_info.cc | 8 ++-- 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index d903315414d..70416360697 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -1,3 +1,5 @@ +set @save_persistent=@@global.innodb_stats_persistent; +set global innodb_stats_persistent= 0; set system_versioning_alter_history=keep; # Check conventional partitioning on temporal tables create or replace table t1 ( @@ -799,4 +801,43 @@ delete from t1 partition (p0, p1, pn); ERROR HY000: Not allowed for system-versioned table `test`.`t1` drop table t1; set timestamp= default; +# +# MDEV-25546 LIMIT partitioning does not respect ROLLBACK +# +create or replace table t1 (pk int primary key) +with system versioning engine innodb +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_1_to_90; +start transaction; +replace into t1 select seq from seq_1_to_80; +replace into t1 select seq from seq_1_to_70; +replace into t1 select seq from seq_1_to_60; +select partition_name, table_rows +from information_schema.partitions +where table_name = 't1'; +partition_name table_rows +p0 150 +p1 60 +pn 90 +rollback; +select partition_name, table_rows +from information_schema.partitions +where table_name = 't1'; +partition_name table_rows +p0 0 +p1 0 +pn 90 +replace into t1 select seq from seq_1_to_10; +select partition_name, table_rows +from information_schema.partitions +where table_name = 't1'; +partition_name table_rows +p0 10 +p1 0 +pn 90 +drop table t1; # End of 10.3 tests +set global innodb_stats_persistent= @save_persistent; diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index c5531d3c7f6..a687cd9b09f 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -1,6 +1,10 @@ -- source include/have_partition.inc -- source suite/versioning/common.inc -- source suite/versioning/engines.inc +-- source include/have_sequence.inc + +set @save_persistent=@@global.innodb_stats_persistent; +set global innodb_stats_persistent= 0; set system_versioning_alter_history=keep; --echo # Check conventional partitioning on temporal tables @@ -782,6 +786,44 @@ delete from t1 partition (p0, pn); delete from t1 partition (p0, p1, pn); drop table t1; set timestamp= default; + +--echo # +--echo # MDEV-25546 LIMIT partitioning does not respect ROLLBACK +--echo # +create or replace table t1 (pk int primary key) +with system versioning engine innodb +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); +insert into t1 select seq from seq_1_to_90; + +start transaction; +# Puts 80 rows into p0 +replace into t1 select seq from seq_1_to_80; +# Puts another 70 rows into p0 +replace into t1 select seq from seq_1_to_70; +# Puts 60 rows into p1 +replace into t1 select seq from seq_1_to_60; + +select partition_name, table_rows +from information_schema.partitions +where table_name = 't1'; +rollback; + +select partition_name, table_rows +from information_schema.partitions +where table_name = 't1'; + +# Should put 10 rows into the empty partition p0 +replace into t1 select seq from seq_1_to_10; +select partition_name, table_rows +from information_schema.partitions +where table_name = 't1'; + # Cleanup +drop table t1; --echo # End of 10.3 tests +set global innodb_stats_persistent= @save_persistent; + --source suite/versioning/common_finish.inc diff --git a/sql/partition_info.cc b/sql/partition_info.cc index edcdd6d2b37..f523415f6cc 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -843,12 +843,10 @@ int partition_info::vers_set_hist_part(THD *thd) if (vers_info->limit) { ha_partition *hp= (ha_partition*)(table->file); - partition_element *next= NULL; + partition_element *next; List_iterator it(partitions); - while (next != vers_info->hist_part) - next= it++; - DBUG_ASSERT(bitmap_is_set(&read_partitions, next->id)); - ha_rows records= hp->part_records(next); + ha_rows records= 0; + vers_info->hist_part= partitions.head(); while ((next= it++) != vers_info->now_part) { DBUG_ASSERT(bitmap_is_set(&read_partitions, next->id)); From 9286c9e6472e62b7cd5c5a0cf36006ce9b6f5893 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Fri, 22 Apr 2022 15:49:37 +0300 Subject: [PATCH 19/94] MDEV-28254 Wrong position for row_start, row_end after adding column to implicit versioned table Implicit system-versioned table does not contain system fields in SHOW CREATE. Therefore after mysqldump recovery such table has system fields in the last place in frm image. The original table meanwhile does not guarantee these system fields on last place because adding new fields via ALTER TABLE places them last. Thus the order of fields may be different between master and slave, so row-based replication may fail. To fix this on ALTER TABLE we now place system-invisible fields always last in frm image. If the table was created via old revision and has an incorrect order of fields it can be fixed via any copy operation of ALTER TABLE, f.ex.: ALTER TABLE t1 FORCE; To check the order of fields in frm file one can use hexdump: hexdump -C t1.frm Note, the replication fails only when all 3 conditions are met: 1. row-based or mixed mode replication; 2. table has new fields added via ALTER TABLE; 3. table was rebuilt on some, but not all nodes via mysqldump image. Otherwise it will operate properly even with incorrect order of fields. --- mysql-test/include/grep.inc | 16 ++++++++ mysql-test/suite/versioning/r/rpl_row.result | 38 ++++++++++++++++++ mysql-test/suite/versioning/t/rpl_row.test | 41 ++++++++++++++++++++ sql/sql_table.cc | 13 ++++++- 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 mysql-test/include/grep.inc diff --git a/mysql-test/include/grep.inc b/mysql-test/include/grep.inc new file mode 100644 index 00000000000..9ce7cddb7b7 --- /dev/null +++ b/mysql-test/include/grep.inc @@ -0,0 +1,16 @@ +# Grep file for regular expression and output to STDOUT +# +# Usage: +# --let $grep_file= /path/to/your/file +# --let $grep_regex= your_regex_string +# --source include/grep.inc + +--perl + open (my $fh, "<", "$ENV{grep_file}") or die $!; + while (<$fh>) + { + /$ENV{grep_regex}/ && + print; + } + close $fh; +EOF diff --git a/mysql-test/suite/versioning/r/rpl_row.result b/mysql-test/suite/versioning/r/rpl_row.result index 03ac8dc9eb8..e5db01b9e78 100644 --- a/mysql-test/suite/versioning/r/rpl_row.result +++ b/mysql-test/suite/versioning/r/rpl_row.result @@ -11,4 +11,42 @@ connection slave; connection master; drop table t1; set binlog_row_image= @old_row_image; +# +# MDEV-28254 Wrong position for row_start, row_end after adding column +# to implicit versioned table +# +set @@system_versioning_alter_history= keep; +set @@session.time_zone='+00:00'; +create table t1 (x int) with system versioning engine innodb; +alter table t1 add column y int, algorithm=inplace; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +connection slave; +drop table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x` int(11) DEFAULT NULL, + `y` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +connection master; +set timestamp= 12345; +insert t1 values (1, 1); +select *, unix_timestamp(row_start) as row_start, unix_timestamp(row_end) as row_end from t1; +x y row_start row_end +1 1 12345.000000 2147483647.999999 +set timestamp= default; +### INSERT INTO `test`.`t1` +### SET +### @1=1 +### @2=1 +### @3=12345.000000 +### @4=2147483647.999999 +connection slave; +select * from t1; +x y +1 1 +connection master; +drop table t1; include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl_row.test b/mysql-test/suite/versioning/t/rpl_row.test index 17ce2dfdcf8..2e5d4c76f4a 100644 --- a/mysql-test/suite/versioning/t/rpl_row.test +++ b/mysql-test/suite/versioning/t/rpl_row.test @@ -1,5 +1,6 @@ --source include/have_binlog_format_row.inc --source include/master-slave.inc +--source include/have_innodb.inc --echo # MDEV-16252: MINIMAL binlog_row_image does not work for versioned tables set @old_row_image= @@binlog_row_image; @@ -15,4 +16,44 @@ update t1 set i = 0; drop table t1; set binlog_row_image= @old_row_image; +--echo # +--echo # MDEV-28254 Wrong position for row_start, row_end after adding column +--echo # to implicit versioned table +--echo # +--let TMP= $MYSQLTEST_VARDIR/tmp +--let $MYSQLD_DATADIR= `select @@datadir` +set @@system_versioning_alter_history= keep; +set @@session.time_zone='+00:00'; + +create table t1 (x int) with system versioning engine innodb; +alter table t1 add column y int, algorithm=inplace; +check table t1; +--exec $MYSQL_DUMP --databases test > $TMP/dump.sql + +--sync_slave_with_master +drop table t1; +--exec $MYSQL_SLAVE test < $TMP/dump.sql +show create table t1; + +--connection master +set timestamp= 12345; +--let $start_pos= query_get_value("SHOW MASTER STATUS", Position, 1) +insert t1 values (1, 1); +select *, unix_timestamp(row_start) as row_start, unix_timestamp(row_end) as row_end from t1; +--let $stop_pos= query_get_value("SHOW MASTER STATUS", Position, 1) +set timestamp= default; + +# NOTE: pipe grep is not Windows-compatible +--let grep_file= $TMP/out.txt +--let grep_regex= ^### +--exec $MYSQL_BINLOG -v -j $start_pos --stop-position=$stop_pos -o 3 $MYSQLD_DATADIR/master-bin.000001 > $grep_file +--source include/grep.inc +--sync_slave_with_master +select * from t1; + +--connection master +drop table t1; +--remove_files_wildcard $TMP *.txt +--remove_files_wildcard $TMP *.sql + --source include/rpl_end.inc diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 648b2f3cba5..62b9cb22df0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8027,6 +8027,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { /* New column definitions are added here */ List new_create_list; + /* System-invisible fields must be added last */ + List new_create_tail; /* New key definitions are added here */ List new_key_list; List_iterator drop_it(alter_info->drop_list); @@ -8251,7 +8253,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, dropped_sys_vers_fields|= field->flags; drop_it.remove(); } - else + else if (field->invisible < INVISIBLE_SYSTEM) { /* This field was not dropped and not changed, add it to the list @@ -8276,6 +8278,12 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, alter_it.remove(); } } + else + { + DBUG_ASSERT(field->invisible == INVISIBLE_SYSTEM); + def= new (thd->mem_root) Create_field(thd, field, field); + new_create_tail.push_back(def, thd->mem_root); + } } dropped_sys_vers_fields &= VERS_SYSTEM_FIELD; if ((dropped_sys_vers_fields || @@ -8408,6 +8416,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, alter_it.remove(); } } + + new_create_list.append(&new_create_tail); + if (unlikely(alter_info->alter_list.elements)) { my_error(ER_BAD_FIELD_ERROR, MYF(0), From 807945f2eb5fa22e6f233cc17b85a2e141efe2c8 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 21 Apr 2022 22:45:31 +0300 Subject: [PATCH 20/94] MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order... When doing condition pushdown from HAVING into WHERE, Item_equal::create_pushable_equalities() calls item->set_extraction_flag(IMMUTABLE_FL) for constant items. Then, Item::cleanup_excluding_immutables_processor() checks for this flag to see if it should call item->cleanup() or leave the item as-is. The failure happens when a constant item has a non-constant one inside it, like: (tbl.col=0 AND impossible_cond) item->walk(cleanup_excluding_immutables_processor) works in a bottom-up way so it 1. will call Item_func_eq(tbl.col=0)->cleanup() 2. will not call Item_cond_and->cleanup (as the AND is constant) This creates an item tree where a fixed Item has an un-fixed Item inside it which eventually causes an assertion failure. Fixed by introducing this rule: instead of just calling item->set_extraction_flag(IMMUTABLE_FL); we call Item::walk() to set the flag for all sub-items of the item. --- mysql-test/main/having_cond_pushdown.result | 15 +++++++++++++++ mysql-test/main/having_cond_pushdown.test | 10 ++++++++++ sql/item.h | 6 ++++++ sql/item_cmpfunc.cc | 12 +++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result index 9b124296e3d..9a9ed2b9213 100644 --- a/mysql-test/main/having_cond_pushdown.result +++ b/mysql-test/main/having_cond_pushdown.result @@ -4924,3 +4924,18 @@ SELECT a FROM t1 GROUP BY a HAVING a = ( SELECT MIN(c) FROM t2 ); a 2 DROP TABLE t1,t2; +# +# MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1' +# +CREATE TABLE t1 (i int NOT NULL); +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL); +i +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0); +i +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0); +i +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'x' +DROP TABLE t1; diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test index fc75122615c..270eac2a46f 100644 --- a/mysql-test/main/having_cond_pushdown.test +++ b/mysql-test/main/having_cond_pushdown.test @@ -1440,3 +1440,13 @@ eval EXPLAIN FORMAT=JSON $q; eval $q; DROP TABLE t1,t2; + +--echo # +--echo # MDEV-26402: A SEGV in Item_field::used_tables/update_depend_map_for_order or Assertion `fixed == 1' +--echo # + +CREATE TABLE t1 (i int NOT NULL); +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL); +SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0); +SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0); +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index 9182b578cdb..af6f350216d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1938,6 +1938,12 @@ public: return 0; } + virtual bool set_extraction_flag_processor(void *arg) + { + set_extraction_flag(*(int*)arg); + return 0; + } + /** Check db/table_name if they defined in item and match arg values diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 15f1766b2e6..0ec20efdf27 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -7533,7 +7533,17 @@ bool Item_equal::create_pushable_equalities(THD *thd, if (!eq || equalities->push_back(eq, thd->mem_root)) return true; if (!clone_const) - right_item->set_extraction_flag(IMMUTABLE_FL); + { + /* + Also set IMMUTABLE_FL for any sub-items of the right_item. + This is needed to prevent Item::cleanup_excluding_immutables_processor + from peforming cleanup of the sub-items and so creating an item tree + where a fixed item has non-fixed items inside it. + */ + int new_flag= IMMUTABLE_FL; + right_item->walk(&Item::set_extraction_flag_processor, false, + (void*)&new_flag); + } } while ((item=it++)) From a83c7ab1ea62954ab81cd599315e76a2f115ff92 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 20 Oct 2021 20:13:45 -0600 Subject: [PATCH 21/94] MDEV-11853: semisync thread can be killed after sync binlog but before ACK in the sync state Problem: ======== If a primary is shutdown during an active semi-sync connection during the period when the primary is awaiting an ACK, the primary hard kills the active communication thread and does not ensure the transaction was received by a replica. This can lead to an inconsistent replication state. Solution: ======== During shutdown, the primary should wait for an ACK or timeout before hard killing a thread which is awaiting a communication. We extend the `SHUTDOWN WAIT FOR SLAVES` logic to identify and ignore any threads waiting for a semi-sync ACK in phase 1. Then, before stopping the ack receiver thread, the shutdown is delayed until all waiting semi-sync connections receive an ACK or time out. The connections are then killed in phase 2. Notes: 1) There remains an unresolved corner case that affects this patch. MDEV-28141: Slave crashes with Packets out of order when connecting to a shutting down master. Specifically, If a slave is connecting to a master which is actively shutting down, the slave can crash with a "Packets out of order" assertion error. To get around this issue in the MTR tests, the primary will wait a small amount of time before phase 1 killing threads to let the replicas safely stop (if applicable). 2) This patch also fixes MDEV-28114: Semi-sync Master ACK Receiver Thread Can Error on COM_QUIT Reviewed By ============ Andrei Elkin --- .../r/rpl_semi_sync_shutdown_await_ack.result | 517 ++++++++++++++++++ .../t/rpl_semi_sync_shutdown_await_ack.cnf | 14 + .../t/rpl_semi_sync_shutdown_await_ack.inc | 163 ++++++ .../t/rpl_semi_sync_shutdown_await_ack.test | 214 ++++++++ sql-common/client.c | 2 + sql/mysqld.cc | 46 +- sql/semisync_master.cc | 65 ++- sql/semisync_master.h | 39 ++ sql/semisync_slave.cc | 40 +- sql/semisync_slave.h | 1 + sql/slave.cc | 1 + sql/sql_class.cc | 3 +- sql/sql_class.h | 8 + 13 files changed, 1091 insertions(+), 22 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result new file mode 100644 index 00000000000..719b61b796b --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result @@ -0,0 +1,517 @@ +############################# +# Common setup for all tests +############################# +# Note: Simulated slave delay is hardcoded to 800 milliseconds +# Note: Simulated master shutdown delay is hardcoded to 500 milliseconds +include/rpl_init.inc [topology=1->2, 1->3] +connection server_1; +# Slaves which simulate an error will produce a timeout on the primary +call mtr.add_suppression("Timeout waiting"); +call mtr.add_suppression("did not exit"); +# Suppress slave errors related to the simulated error +connection server_2; +call mtr.add_suppression("reply failed"); +call mtr.add_suppression("Replication event checksum verification"); +call mtr.add_suppression("Relay log write failure"); +call mtr.add_suppression("Failed to kill the active semi-sync connection"); +connection server_3; +call mtr.add_suppression("reply failed"); +call mtr.add_suppression("Replication event checksum verification"); +call mtr.add_suppression("Relay log write failure"); +call mtr.add_suppression("Failed to kill the active semi-sync connection"); +connection server_1; +CREATE TABLE t1 (a int); +connection server_2; +connection server_3; +connect server_1_con2, localhost, root,,; +############################# +# Test cases +############################# +# +# Test Case 1) If both replicas simulate a delay that is within the +# allowed timeout, the primary should delay killing the suspended thread +# until an ACK is received (Rpl_semi_sync_master_yes_tx should be 1). +# +connection server_1; +#-- +#-- Semi-sync Setup +connection server_1; +#-- Enable semi-sync on slaves +let slave_last= 3 +connection server_2; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +connection server_3; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +#-- Enable semi-sync on master +connection server_1; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +set @@global.rpl_semi_sync_master_timeout= 1600; +#-- Wait for master to recognize semi-sync slaves +connection server_1; +#-- Master should have semi-sync enabled with 2 connections +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status ON +show status like 'Rpl_semi_sync_master_clients'; +Variable_name Value +Rpl_semi_sync_master_clients 2 +#-- Prepare servers to simulate delay or error +connection server_1; +SET @@GLOBAL.debug_dbug= ""; +connection server_2; +SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; +connection server_3; +SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; +#-- +#-- Test begins +connection server_1; +#-- Begin semi-sync transaction +INSERT INTO t1 VALUES (1); +connection server_1_con2; +#-- Wait until master recognizes a connection is awaiting semi-sync ACK +show status like 'Rpl_semi_sync_master_wait_sessions'; +Variable_name Value +Rpl_semi_sync_master_wait_sessions 1 +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; +#-- Begin master shutdown +SHUTDOWN WAIT FOR ALL SLAVES; +connection server_1; +#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) +show status like 'Rpl_semi_sync_master_yes_tx'; +Variable_name Value +Rpl_semi_sync_master_yes_tx 1 +show status like 'Rpl_semi_sync_master_no_tx'; +Variable_name Value +Rpl_semi_sync_master_no_tx 0 +connection server_1_con2; +# Check logs to ensure shutdown was delayed +FOUND 1 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err +# Validate slave data is in correct state +connection server_2; +select count(*)=1 from t1; +count(*)=1 +1 +connection server_3; +select count(*)=1 from t1; +count(*)=1 +1 +# +#-- Re-synchronize slaves with master and disable semi-sync +#-- Stop slaves +connection server_2; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +connection server_3; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +#-- Bring the master back up +connection server_1_con2; +connection default; +connection server_1; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status OFF +TRUNCATE TABLE t1; +#-- Bring slaves back up +connection server_2; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +connection server_3; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +# +# Test Case 2) If both replicas simulate an error before sending an ACK, +# the primary should delay killing the suspended thread until the +# timeout is reached (Rpl_semi_sync_master_no_tx should be 1). +# +connection server_1; +#-- +#-- Semi-sync Setup +connection server_1; +#-- Enable semi-sync on slaves +let slave_last= 3 +connection server_2; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +connection server_3; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +#-- Enable semi-sync on master +connection server_1; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +set @@global.rpl_semi_sync_master_timeout= 500; +#-- Wait for master to recognize semi-sync slaves +connection server_1; +#-- Master should have semi-sync enabled with 2 connections +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status ON +show status like 'Rpl_semi_sync_master_clients'; +Variable_name Value +Rpl_semi_sync_master_clients 2 +#-- Prepare servers to simulate delay or error +connection server_1; +SET @@GLOBAL.debug_dbug= "+d,mysqld_delay_kill_threads_phase_1"; +connection server_2; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event"; +connection server_3; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event"; +#-- +#-- Test begins +connection server_1; +#-- Begin semi-sync transaction +INSERT INTO t1 VALUES (1); +connection server_1_con2; +#-- Wait until master recognizes a connection is awaiting semi-sync ACK +show status like 'Rpl_semi_sync_master_wait_sessions'; +Variable_name Value +Rpl_semi_sync_master_wait_sessions 1 +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; +#-- Begin master shutdown +SHUTDOWN WAIT FOR ALL SLAVES; +connection server_1; +#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) +show status like 'Rpl_semi_sync_master_yes_tx'; +Variable_name Value +Rpl_semi_sync_master_yes_tx 0 +show status like 'Rpl_semi_sync_master_no_tx'; +Variable_name Value +Rpl_semi_sync_master_no_tx 1 +connection server_1_con2; +# Check logs to ensure shutdown was delayed +FOUND 2 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err +# Validate slave data is in correct state +connection server_2; +select count(*)=0 from t1; +count(*)=0 +1 +connection server_3; +select count(*)=0 from t1; +count(*)=0 +1 +# +#-- Re-synchronize slaves with master and disable semi-sync +#-- Stop slaves +connection server_2; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +connection server_3; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +#-- Bring the master back up +connection server_1_con2; +connection default; +connection server_1; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status OFF +TRUNCATE TABLE t1; +#-- Bring slaves back up +connection server_2; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +connection server_3; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +# +# Test Case 3) If one replica simulates a delay within the allowed +# timeout and the other simulates an error before sending an ACK, the +# primary should delay killing the suspended thread until it receives an +# ACK from the delayed slave (Rpl_semi_sync_master_yes_tx should be 1). +# +connection server_1; +#-- +#-- Semi-sync Setup +connection server_1; +#-- Enable semi-sync on slaves +let slave_last= 3 +connection server_2; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +connection server_3; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +#-- Enable semi-sync on master +connection server_1; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +set @@global.rpl_semi_sync_master_timeout= 1600; +#-- Wait for master to recognize semi-sync slaves +connection server_1; +#-- Master should have semi-sync enabled with 2 connections +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status ON +show status like 'Rpl_semi_sync_master_clients'; +Variable_name Value +Rpl_semi_sync_master_clients 2 +#-- Prepare servers to simulate delay or error +connection server_1; +SET @@GLOBAL.debug_dbug= "+d,mysqld_delay_kill_threads_phase_1"; +connection server_2; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event"; +connection server_3; +SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; +#-- +#-- Test begins +connection server_1; +#-- Begin semi-sync transaction +INSERT INTO t1 VALUES (1); +connection server_1_con2; +#-- Wait until master recognizes a connection is awaiting semi-sync ACK +show status like 'Rpl_semi_sync_master_wait_sessions'; +Variable_name Value +Rpl_semi_sync_master_wait_sessions 1 +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; +#-- Begin master shutdown +SHUTDOWN WAIT FOR ALL SLAVES; +connection server_1; +#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) +show status like 'Rpl_semi_sync_master_yes_tx'; +Variable_name Value +Rpl_semi_sync_master_yes_tx 1 +show status like 'Rpl_semi_sync_master_no_tx'; +Variable_name Value +Rpl_semi_sync_master_no_tx 0 +connection server_1_con2; +# Check logs to ensure shutdown was delayed +FOUND 3 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err +# Validate slave data is in correct state +connection server_2; +select count(*)=0 from t1; +count(*)=0 +1 +connection server_3; +select count(*)=1 from t1; +count(*)=1 +1 +# +#-- Re-synchronize slaves with master and disable semi-sync +#-- Stop slaves +connection server_2; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +connection server_3; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +#-- Bring the master back up +connection server_1_con2; +connection default; +connection server_1; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status OFF +TRUNCATE TABLE t1; +#-- Bring slaves back up +connection server_2; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +connection server_3; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +# +# Test Case 4) If a replica errors before sending an ACK, it will cause +# the IO thread to stop and handle the error. During error handling, if +# semi-sync is active, the replica will form a new connection with the +# primary to kill the active connection. However, if the primary is +# shutting down, it may kill the new connection, thereby leaving the +# active semi-sync connection in-tact. The slave should notice this, and +# not issue a `QUIT` command to the primary, which would otherwise be +# sent to kill an active connection. This test case validates that the +# slave does not send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx +# should be 1 because server_3 will send the ACK within a valid timeout). +# +connection server_1; +#-- +#-- Semi-sync Setup +connection server_1; +#-- Enable semi-sync on slaves +let slave_last= 3 +connection server_2; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +connection server_3; +set global rpl_semi_sync_slave_enabled = 1; +include/stop_slave.inc +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status ON +#-- Enable semi-sync on master +connection server_1; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +set @@global.rpl_semi_sync_master_timeout= 1600; +#-- Wait for master to recognize semi-sync slaves +connection server_1; +#-- Master should have semi-sync enabled with 2 connections +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status ON +show status like 'Rpl_semi_sync_master_clients'; +Variable_name Value +Rpl_semi_sync_master_clients 2 +#-- Prepare servers to simulate delay or error +connection server_1; +SET @@GLOBAL.debug_dbug= "+d,mysqld_delay_kill_threads_phase_1"; +connection server_2; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event,slave_delay_killing_semisync_connection"; +connection server_3; +SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; +#-- +#-- Test begins +connection server_1; +#-- Begin semi-sync transaction +INSERT INTO t1 VALUES (1); +connection server_1_con2; +#-- Wait until master recognizes a connection is awaiting semi-sync ACK +show status like 'Rpl_semi_sync_master_wait_sessions'; +Variable_name Value +Rpl_semi_sync_master_wait_sessions 1 +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; +#-- Begin master shutdown +SHUTDOWN WAIT FOR ALL SLAVES; +connection server_1; +#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) +show status like 'Rpl_semi_sync_master_yes_tx'; +Variable_name Value +Rpl_semi_sync_master_yes_tx 1 +show status like 'Rpl_semi_sync_master_no_tx'; +Variable_name Value +Rpl_semi_sync_master_no_tx 0 +connection server_1_con2; +# Check logs to ensure shutdown was delayed +FOUND 4 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err +# Validate slave data is in correct state +connection server_2; +select count(*)=0 from t1; +count(*)=0 +1 +connection server_3; +select count(*)=1 from t1; +count(*)=1 +1 +# +#-- Re-synchronize slaves with master and disable semi-sync +#-- Stop slaves +connection server_2; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +connection server_3; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; +include/stop_slave.inc +#-- Bring the master back up +connection server_1_con2; +connection default; +connection server_1; +SET @@GLOBAL.debug_dbug= ""; +SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status OFF +TRUNCATE TABLE t1; +#-- Bring slaves back up +connection server_2; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +connection server_3; +include/start_slave.inc +show status like 'Rpl_semi_sync_slave_status'; +Variable_name Value +Rpl_semi_sync_slave_status OFF +SELECT COUNT(*)=0 from t1; +COUNT(*)=0 +1 +############################# +# Cleanup +############################# +connection server_2; +include/stop_slave.inc +include/start_slave.inc +connection server_3; +include/stop_slave.inc +include/start_slave.inc +connection server_1; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf new file mode 100644 index 00000000000..2cf1b1786bd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf @@ -0,0 +1,14 @@ +!include ../my.cnf + +[mysqld.1] +log_warnings=9 + +[mysqld.2] +log_warnings=9 + +[mysqld.3] +log_warnings=9 + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc new file mode 100644 index 00000000000..a232f68540d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc @@ -0,0 +1,163 @@ +# +# Helper file to ensure that a primary waits for all ACKS (or timeout) from its +# replicas before shutting down. +# +# Parameters: +# server_1_dbug (string) Debug setting for primary (server 1) +# server_2_dbug (string) Debug setting to simulate delay or error on +# the first replica (server 2) +# server_3_dbug (string) Debug setting to simulate delay or error on +# the second replica (server 3) +# semisync_timeout (int) Rpl_semi_sync_master_timeout to use +# server_2_expect_row_count (int) The number of rows expected on the first +# replica after the shutdown +# server_3_expect_row_count (int) The number of rows expected on the second +# replica after the shutdown +# + +--connection server_1 +let $log_error_file= `SELECT @@GLOBAL.log_error`; + +--echo #-- +--echo #-- Semi-sync Setup + +--connection server_1 +--save_master_pos + +echo #-- Enable semi-sync on slaves +let slave_last= 3; +--let i= 2 +while (`SELECT $i <= $slave_last`) +{ + --connection server_$i + --sync_with_master + + set global rpl_semi_sync_slave_enabled = 1; + source include/stop_slave.inc; + source include/start_slave.inc; + show status like 'Rpl_semi_sync_slave_status'; + + --inc $i +} + +--echo #-- Enable semi-sync on master +--connection server_1 +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +--eval set @@global.rpl_semi_sync_master_timeout= $semisync_timeout + +--echo #-- Wait for master to recognize semi-sync slaves +--connection server_1 +let $status_var= Rpl_semi_sync_master_clients; +let $status_var_value= 2; +source include/wait_for_status_var.inc; + +--echo #-- Master should have semi-sync enabled with 2 connections +show status like 'Rpl_semi_sync_master_status'; +show status like 'Rpl_semi_sync_master_clients'; + +--echo #-- Prepare servers to simulate delay or error +--connection server_1 +--eval SET @@GLOBAL.debug_dbug= $server_1_dbug +--connection server_2 +--eval SET @@GLOBAL.debug_dbug= $server_2_dbug +--connection server_3 +--eval SET @@GLOBAL.debug_dbug= $server_3_dbug + +--echo #-- +--echo #-- Test begins + +--connection server_1 +--echo #-- Begin semi-sync transaction +--send INSERT INTO t1 VALUES (1) + +--connection server_1_con2 +--echo #-- Wait until master recognizes a connection is awaiting semi-sync ACK +let $status_var= Rpl_semi_sync_master_wait_sessions; +let $status_var_value= 1; +source include/wait_for_status_var.inc; +show status like 'Rpl_semi_sync_master_wait_sessions'; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +--echo #-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; + +--echo #-- Begin master shutdown +--send SHUTDOWN WAIT FOR ALL SLAVES + +--connection server_1 +--reap +--echo #-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) +show status like 'Rpl_semi_sync_master_yes_tx'; +show status like 'Rpl_semi_sync_master_no_tx'; + +--connection server_1_con2 +--reap +--source include/wait_until_disconnected.inc + +--echo # Check logs to ensure shutdown was delayed +--let SEARCH_FILE=$log_error_file +--let SEARCH_PATTERN=Delaying shutdown to await semi-sync ACK +--source include/search_pattern_in_file.inc + +--echo # Validate slave data is in correct state +--connection server_2 +--eval select count(*)=$server_2_expect_row_count from t1 +--connection server_3 +--eval select count(*)=$server_3_expect_row_count from t1 + +--echo # +--echo #-- Re-synchronize slaves with master and disable semi-sync + +--echo #-- Stop slaves + +--connection server_2 +--eval SET @@GLOBAL.debug_dbug= "$sav_server_2_dbug" +--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0 +source include/stop_slave.inc; + +--connection server_3 +--eval SET @@GLOBAL.debug_dbug= "$sav_server_3_dbug" +--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0 +source include/stop_slave.inc; + +--echo #-- Bring the master back up +--connection server_1_con2 +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection default +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--eval SET @@GLOBAL.debug_dbug= "$sav_master_dbug" +let $status_var= Rpl_semi_sync_master_clients; +let $status_var_value= 0; +source include/wait_for_status_var.inc; +--eval SET @@GLOBAL.rpl_semi_sync_master_enabled = 0 +show status like 'Rpl_semi_sync_master_status'; + +TRUNCATE TABLE t1; +--save_master_pos + +--echo #-- Bring slaves back up +--let i= 2 +while (`SELECT $i <= $slave_last`) +{ + --connection server_$i + source include/start_slave.inc; + show status like 'Rpl_semi_sync_slave_status'; + --sync_with_master + SELECT COUNT(*)=0 from t1; + --inc $i +} diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test new file mode 100644 index 00000000000..5e9cda6466e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test @@ -0,0 +1,214 @@ +# +# Purpose: +# This test validates that data is consistent between a primary and replica +# in semi-sync mode when the primary is issued `SHUTDOWN WAIT FOR SLAVES` +# during an active communication. More specifically, the primary should not +# kill the connection until it is sure a replica has received all binlog +# data, i.e. once the primary receives the ACK. If a primary is issued a +# shutdown before receiving an ACK, it should wait until either 1) the ACK is +# received, or 2) the configured timeout (rpl_semi_sync_master_timeout) is +# reached. +# +# Methodology: +# Using a topology consisting of one primary with two replicas, all in +# semi-sync mode, we use DEBUG_DBUG to simulate an error or delay on the +# replicas during an active communication while the primary is issued +# `SHUTDOWN WAIT FOR SLAVES`. We create four test cases to ensure the primary +# will correctly wait for the communication to finish, and use the semi-sync +# status variables Rpl_semi_sync_master_yes_tx and Rpl_semi_sync_master_no_tx +# to ensure the connection was not prematurely killed due to the shutdown. +# Test Case 1) If both replicas simulate a delay that is within the allowed +# timeout, the primary should delay killing the suspended thread +# until an ACK is received (Rpl_semi_sync_master_yes_tx should +# be 1). +# Test Case 2) If both replicas simulate an error before sending an ACK, the +# primary should delay killing the suspended thread until the +# the timeout is reached (Rpl_semi_sync_master_no_tx should be +# 1). +# Test Case 3) If one replica simulates a delay within the allowed timeout +# and the other simulates an error before sending an ACK, the +# primary should delay killing the suspended thread until it +# receives an ACK from the delayed slave +# (Rpl_semi_sync_master_yes_tx should be 1). +# Test Case 4) If a replica errors before sending an ACK, it will cause the +# IO thread to stop and handle the error. During error handling, +# if semi-sync is active, the replica will form a new connection +# with the primary to kill the active connection. However, if +# the primary is shutting down, it may kill the new connection, +# thereby leaving the active semi-sync connection in-tact. The +# slave should notice this, and not issue a `QUIT` command to +# the primary, which would otherwise be sent to kill an active +# connection. This test case validates that the slave does not +# send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx should +# be 1 because server_3 will send the ACK within a valid +# timeout). +# +# References: +# MDEV-11853: semisync thread can be killed after sync binlog but before ACK +# in the sync state +# MDEV-28114: Semi-sync Master ACK Receiver Thread Can Error on COM_QUIT +# + +--echo ############################# +--echo # Common setup for all tests +--echo ############################# + +--echo # Note: Simulated slave delay is hardcoded to 800 milliseconds +--echo # Note: Simulated master shutdown delay is hardcoded to 500 milliseconds + +--source include/have_debug.inc +--let $rpl_topology=1->2, 1->3 +--source include/rpl_init.inc + +--connection server_1 + +--echo # Slaves which simulate an error will produce a timeout on the primary +call mtr.add_suppression("Timeout waiting"); +call mtr.add_suppression("did not exit"); + +--let $sav_master_timeout= `SELECT @@global.rpl_semi_sync_master_timeout` +--let $sav_enabled_master= `SELECT @@GLOBAL.rpl_semi_sync_master_enabled` +--let $sav_master_dbug= `SELECT @@GLOBAL.debug_dbug` + +--echo # Suppress slave errors related to the simulated error +--connection server_2 +call mtr.add_suppression("reply failed"); +call mtr.add_suppression("Replication event checksum verification"); +call mtr.add_suppression("Relay log write failure"); +call mtr.add_suppression("Failed to kill the active semi-sync connection"); +--let $sav_enabled_server_2=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` +--let $sav_server_2_dbug= `SELECT @@GLOBAL.debug_dbug` + +--connection server_3 +call mtr.add_suppression("reply failed"); +call mtr.add_suppression("Replication event checksum verification"); +call mtr.add_suppression("Relay log write failure"); +call mtr.add_suppression("Failed to kill the active semi-sync connection"); +--let $sav_enabled_server_3=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` +--let $sav_server_3_dbug= `SELECT @@GLOBAL.debug_dbug` + +--connection server_1 +CREATE TABLE t1 (a int); +--save_master_pos + +--let i= 2 +--let slave_last= 3 +while (`SELECT $i <= $slave_last`) +{ + --connection server_$i + --sync_with_master + --inc $i +} + +# Set up the connection used to issue the shutdown +--connect(server_1_con2, localhost, root,,) + + +--echo ############################# +--echo # Test cases +--echo ############################# + +--echo # +--echo # Test Case 1) If both replicas simulate a delay that is within the +--echo # allowed timeout, the primary should delay killing the suspended thread +--echo # until an ACK is received (Rpl_semi_sync_master_yes_tx should be 1). +--echo # +--let server_1_dbug= "" +--let server_2_dbug= "+d,simulate_delay_semisync_slave_reply" +--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" +--let semisync_timeout= 1600 +--let server_2_expect_row_count= 1 +--let server_3_expect_row_count= 1 +--source rpl_semi_sync_shutdown_await_ack.inc + +--echo # +--echo # Test Case 2) If both replicas simulate an error before sending an ACK, +--echo # the primary should delay killing the suspended thread until the +--echo # timeout is reached (Rpl_semi_sync_master_no_tx should be 1). +--echo # +--let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1" +--let server_2_dbug= "+d,corrupt_queue_event" +--let server_3_dbug= "+d,corrupt_queue_event" +--let semisync_timeout= 500 +--let server_2_expect_row_count= 0 +--let server_3_expect_row_count= 0 +--source rpl_semi_sync_shutdown_await_ack.inc + +--echo # +--echo # Test Case 3) If one replica simulates a delay within the allowed +--echo # timeout and the other simulates an error before sending an ACK, the +--echo # primary should delay killing the suspended thread until it receives an +--echo # ACK from the delayed slave (Rpl_semi_sync_master_yes_tx should be 1). +--echo # +--let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1" +--let server_2_dbug= "+d,corrupt_queue_event" +--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" +--let semisync_timeout= 1600 +--let server_2_expect_row_count= 0 +--let server_3_expect_row_count= 1 +--source rpl_semi_sync_shutdown_await_ack.inc + +--echo # +--echo # Test Case 4) If a replica errors before sending an ACK, it will cause +--echo # the IO thread to stop and handle the error. During error handling, if +--echo # semi-sync is active, the replica will form a new connection with the +--echo # primary to kill the active connection. However, if the primary is +--echo # shutting down, it may kill the new connection, thereby leaving the +--echo # active semi-sync connection in-tact. The slave should notice this, and +--echo # not issue a `QUIT` command to the primary, which would otherwise be +--echo # sent to kill an active connection. This test case validates that the +--echo # slave does not send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx +--echo # should be 1 because server_3 will send the ACK within a valid timeout). +--echo # + +# mysqld_delay_kill_threads_phase1 ensures that server_2 will have enough time +# to start a new connection that has the intent to kill the active semi-sync +# connection +--let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1" + +# slave_delay_killing_semisync_connection ensures that the primary has force +# killed its current connection before it is able to issue `KILL` +--let server_2_dbug= "+d,corrupt_queue_event,slave_delay_killing_semisync_connection" +--let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" +--let semisync_timeout= 1600 +--let server_2_expect_row_count= 0 +--let server_3_expect_row_count= 1 +--source rpl_semi_sync_shutdown_await_ack.inc + +--echo ############################# +--echo # Cleanup +--echo ############################# + +--connection server_2 +source include/stop_slave.inc; +source include/start_slave.inc; + +--disable_query_log +--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_server_2 +--eval SET @@GLOBAL.debug_dbug= "$sav_server_2_dbug" +--enable_query_log + +--connection server_3 +source include/stop_slave.inc; +source include/start_slave.inc; + +--disable_query_log +--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_server_3 +--eval SET @@GLOBAL.debug_dbug= "$sav_server_3_dbug" +--enable_query_log + + +--connection server_1 +let $status_var= Rpl_semi_sync_master_clients; +let $status_var_value= 0; +source include/wait_for_status_var.inc; + +--disable_query_log +--eval SET @@GLOBAL.rpl_semi_sync_master_timeout= $sav_master_timeout +--eval SET @@GLOBAL.rpl_semi_sync_master_enabled= $sav_enabled_master +--eval SET @@GLOBAL.debug_dbug= "$sav_master_dbug" +--enable_query_log + +drop table t1; + +--source include/rpl_end.inc diff --git a/sql-common/client.c b/sql-common/client.c index 04ee00d6bea..89de45cfcfc 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -2453,6 +2453,8 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len, mpvio.db= db; mpvio.plugin= auth_plugin; + DBUG_EXECUTE_IF("client_delay_run_plugin_auth", my_sleep(400000);); + res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql); DBUG_PRINT ("info", ("authenticate_user returned %s", res == CR_OK ? "CR_OK" : diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 19b633eb56d..754f0821cd8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1524,11 +1524,15 @@ static void kill_thread(THD *thd) /** First shutdown everything but slave threads and binlog dump connections */ -static my_bool kill_thread_phase_1(THD *thd, void *) +static my_bool kill_thread_phase_1(THD *thd, int *n_threads_awaiting_ack) { DBUG_PRINT("quit", ("Informing thread %ld that it's time to die", (ulong) thd->thread_id)); - if (thd->slave_thread || thd->is_binlog_dump_thread()) + + if (thd->slave_thread || thd->is_binlog_dump_thread() || + (shutdown_wait_for_slaves && + repl_semisync_master.is_thd_awaiting_semisync_ack(thd) && + ++(*n_threads_awaiting_ack))) return 0; if (DBUG_EVALUATE_IF("only_kill_system_threads", !thd->system_thread, 0)) @@ -1546,7 +1550,7 @@ static my_bool kill_thread_phase_1(THD *thd, void *) */ static my_bool kill_thread_phase_2(THD *thd, void *) { - if (shutdown_wait_for_slaves) + if (shutdown_wait_for_slaves && thd->is_binlog_dump_thread()) { thd->set_killed(KILL_SERVER); } @@ -1729,7 +1733,29 @@ static void close_connections(void) This will give the threads some time to gracefully abort their statements and inform their clients that the server is about to die. */ - server_threads.iterate(kill_thread_phase_1); + DBUG_EXECUTE_IF("mysqld_delay_kill_threads_phase_1", my_sleep(200000);); + int n_threads_awaiting_ack= 0; + server_threads.iterate(kill_thread_phase_1, &n_threads_awaiting_ack); + + /* + If we are waiting on any ACKs, delay killing the thread until either an ACK + is received or the timeout is hit. + + Allow at max the number of sessions to await a timeout; however, if all + ACKs have been received in less iterations, then quit early + */ + if (shutdown_wait_for_slaves && repl_semisync_master.get_master_enabled()) + { + int waiting_threads= repl_semisync_master.sync_get_master_wait_sessions(); + if (waiting_threads) + sql_print_information("Delaying shutdown to await semi-sync ACK"); + + while (waiting_threads-- > 0) + repl_semisync_master.await_slave_reply(); + } + + DBUG_EXECUTE_IF("delay_shutdown_phase_2_after_semisync_wait", + my_sleep(500000);); Events::deinit(); slave_prepare_for_shutdown(); @@ -1752,7 +1778,10 @@ static void close_connections(void) */ DBUG_PRINT("info", ("THD_count: %u", THD_count::value())); - for (int i= 0; (THD_count::value() - binlog_dump_thread_count) && i < 1000; i++) + for (int i= 0; (THD_count::value() - binlog_dump_thread_count - + n_threads_awaiting_ack) && + i < 1000; + i++) my_sleep(20000); if (global_system_variables.log_warnings) @@ -1766,9 +1795,12 @@ static void close_connections(void) wsrep_sst_auth_free(); #endif /* All threads has now been aborted */ - DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", THD_count::value())); + DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", + THD_count::value() - binlog_dump_thread_count - + n_threads_awaiting_ack)); - while (THD_count::value() - binlog_dump_thread_count) + while (THD_count::value() - binlog_dump_thread_count - + n_threads_awaiting_ack) my_sleep(1000); /* Kill phase 2 */ diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 0f868d4fc7a..581cf100792 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -463,6 +463,37 @@ void Repl_semi_sync_master::cleanup() delete m_active_tranxs; } +int Repl_semi_sync_master::sync_get_master_wait_sessions() +{ + int wait_sessions; + lock(); + wait_sessions= rpl_semi_sync_master_wait_sessions; + unlock(); + return wait_sessions; +} + +void Repl_semi_sync_master::create_timeout(struct timespec *out, + struct timespec *start_arg) +{ + struct timespec *start_ts; + struct timespec now_ts; + if (!start_arg) + { + set_timespec(now_ts, 0); + start_ts= &now_ts; + } + else + { + start_ts= start_arg; + } + + long diff_secs= (long) (m_wait_timeout / TIME_THOUSAND); + long diff_nsecs= (long) ((m_wait_timeout % TIME_THOUSAND) * TIME_MILLION); + long nsecs= start_ts->tv_nsec + diff_nsecs; + out->tv_sec= start_ts->tv_sec + diff_secs + nsecs / TIME_BILLION; + out->tv_nsec= nsecs % TIME_BILLION; +} + void Repl_semi_sync_master::lock() { mysql_mutex_lock(&LOCK_binlog); @@ -862,13 +893,6 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, m_wait_file_name, (ulong)m_wait_file_pos)); } - /* Calcuate the waiting period. */ - long diff_secs = (long) (m_wait_timeout / TIME_THOUSAND); - long diff_nsecs = (long) ((m_wait_timeout % TIME_THOUSAND) * TIME_MILLION); - long nsecs = start_ts.tv_nsec + diff_nsecs; - abstime.tv_sec = start_ts.tv_sec + diff_secs + nsecs/TIME_BILLION; - abstime.tv_nsec = nsecs % TIME_BILLION; - /* In semi-synchronous replication, we wait until the binlog-dump * thread has received the reply on the relevant binlog segment from the * replication slave. @@ -879,12 +903,20 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, */ rpl_semi_sync_master_wait_sessions++; + /* We keep track of when this thread is awaiting an ack to ensure it is + * not killed while awaiting an ACK if a shutdown is issued. + */ + set_thd_awaiting_semisync_ack(thd, TRUE); + DBUG_PRINT("semisync", ("%s: wait %lu ms for binlog sent (%s, %lu)", "Repl_semi_sync_master::commit_trx", m_wait_timeout, m_wait_file_name, (ulong)m_wait_file_pos)); + create_timeout(&abstime, &start_ts); wait_result = cond_timewait(&abstime); + + set_thd_awaiting_semisync_ack(thd, FALSE); rpl_semi_sync_master_wait_sessions--; if (wait_result != 0) @@ -1320,6 +1352,25 @@ void Repl_semi_sync_master::set_export_stats() unlock(); } +void Repl_semi_sync_master::await_slave_reply() +{ + struct timespec abstime; + + DBUG_ENTER("Repl_semi_sync_master::::await_slave_reply"); + lock(); + + /* Just return if there is nothing to wait for */ + if (!rpl_semi_sync_master_wait_sessions) + goto end; + + create_timeout(&abstime, NULL); + cond_timewait(&abstime); + +end: + unlock(); + DBUG_VOID_RETURN; +} + /* Get the waiting time given the wait's staring time. * * Return: diff --git a/sql/semisync_master.h b/sql/semisync_master.h index 74f6c24c8ea..16cf8a91215 100644 --- a/sql/semisync_master.h +++ b/sql/semisync_master.h @@ -472,6 +472,21 @@ class Repl_semi_sync_master m_wait_timeout = wait_timeout; } + int sync_get_master_wait_sessions(); + + /* + Calculates a timeout that is m_wait_timeout after start_arg and saves it + in out. If start_arg is NULL, the timeout is m_wait_timeout after the + current system time. + */ + void create_timeout(struct timespec *out, struct timespec *start_arg); + + /* + Blocks the calling thread until the ack_receiver either receives an ACK + or times out (from rpl_semi_sync_master_timeout) + */ + void await_slave_reply(); + /*set the ACK point, after binlog sync or after transaction commit*/ void set_wait_point(unsigned long ack_point) { @@ -620,6 +635,30 @@ class Repl_semi_sync_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 + function (indirectly) provides safe access. + */ + my_bool is_thd_awaiting_semisync_ack(THD *thd) + { + lock(); + my_bool ret= thd->is_awaiting_semisync_ack; + unlock(); + return ret; + } + + /* + Update the thread's value for is_awaiting_semisync_ack. LOCK_binlog (from + this class) should be acquired before calling this function. + */ + void set_thd_awaiting_semisync_ack(THD *thd, + my_bool _is_awaiting_semisync_ack) + { + mysql_mutex_assert_owner(&LOCK_binlog); + thd->is_awaiting_semisync_ack= _is_awaiting_semisync_ack; + } + mysql_mutex_t LOCK_rpl_semi_sync_master_enabled; }; diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc index df8baf045ac..8fe3ba3657d 100644 --- a/sql/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -114,10 +114,12 @@ int Repl_semi_sync_slave::slave_start(Master_info *mi) int Repl_semi_sync_slave::slave_stop(Master_info *mi) { - if (rpl_semi_sync_slave_status) - rpl_semi_sync_slave_status= 0; if (get_slave_enabled()) kill_connection(mi->mysql); + + if (rpl_semi_sync_slave_status) + rpl_semi_sync_slave_status= 0; + return 0; } @@ -133,6 +135,8 @@ void Repl_semi_sync_slave::kill_connection(MYSQL *mysql) char kill_buffer[30]; MYSQL *kill_mysql = NULL; + size_t kill_buffer_length; + kill_mysql = mysql_init(kill_mysql); mysql_options(kill_mysql, MYSQL_OPT_CONNECT_TIMEOUT, &m_kill_conn_timeout); mysql_options(kill_mysql, MYSQL_OPT_READ_TIMEOUT, &m_kill_conn_timeout); @@ -144,13 +148,35 @@ void Repl_semi_sync_slave::kill_connection(MYSQL *mysql) { sql_print_information("cannot connect to master to kill slave io_thread's " "connection"); - mysql_close(kill_mysql); - return; + goto failed_graceful_kill; } - size_t kill_buffer_length = my_snprintf(kill_buffer, 30, "KILL %lu", - mysql->thread_id); - mysql_real_query(kill_mysql, kill_buffer, (ulong)kill_buffer_length); + + DBUG_EXECUTE_IF("slave_delay_killing_semisync_connection", my_sleep(400000);); + + kill_buffer_length= my_snprintf(kill_buffer, 30, "KILL %lu", + mysql->thread_id); + if (mysql_real_query(kill_mysql, kill_buffer, (ulong)kill_buffer_length)) + { + sql_print_information( + "Failed to gracefully kill our active semi-sync connection with " + "primary. Silently closing the connection."); + goto failed_graceful_kill; + } + +end: mysql_close(kill_mysql); + return; + +failed_graceful_kill: + /* + If we fail to issue `KILL` on the primary to kill the active semi-sync + connection; we need to locally clean up our side of the connection. This + is because mysql_close will send COM_QUIT on the active semi-sync + connection, causing the primary to error. + */ + net_clear(&(mysql->net), 0); + end_server(mysql); + goto end; } int Repl_semi_sync_slave::request_transmit(Master_info *mi) diff --git a/sql/semisync_slave.h b/sql/semisync_slave.h index d65262f151d..35f93476792 100644 --- a/sql/semisync_slave.h +++ b/sql/semisync_slave.h @@ -23,6 +23,7 @@ #include "sql_priv.h" #include "rpl_mi.h" #include "mysql.h" +#include class Master_info; diff --git a/sql/slave.cc b/sql/slave.cc index edea312c5ea..029fd0f5aaf 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4859,6 +4859,7 @@ Stopping slave I/O thread due to out-of-memory error from master"); 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); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c9e55fd413e..6fb657d3c00 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -640,7 +640,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) #ifdef HAVE_REPLICATION , current_linfo(0), - slave_info(0) + slave_info(0), + is_awaiting_semisync_ack(0) #endif #ifdef WITH_WSREP , diff --git a/sql/sql_class.h b/sql/sql_class.h index 369c58df416..0d1e14b1679 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4838,6 +4838,14 @@ public: bool is_binlog_dump_thread(); #endif + /* + Indicates if this thread is suspended due to awaiting an ACK from a + replica. True if suspended, false otherwise. + + Note that this variable is protected by Repl_semi_sync_master::LOCK_binlog + */ + bool is_awaiting_semisync_ack; + inline ulong wsrep_binlog_format() const { return WSREP_BINLOG_FORMAT(variables.binlog_format); From a7923b37c4554fe6634a583586c1e444bee6118b Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 22 Apr 2022 13:56:08 +1000 Subject: [PATCH 22/94] MDEV-28263 mariadb-tzinfo-to-sql binlog fixes The --skip-write-binlog message was confusing that it only had an effect if the galera was enabled. There are uses beyond galera so we apply SET SESSION SQL_LOG_BIN=0 as implied by the option without being conditional on the wsrep status. Remove wsrep.mysql_tzinfo_to_sql_symlink{,_skip} tests as they offered no additional coverage beyond main.mysql_tzinfo_to_sql_symlink as no server testing was done. Introduced a variant of the galera.mariadb_tzinfo_to_sql as galera.mysql_tzinfo_to_sql, which does testing using the mysql client rather than directly importing into the server via mysqltest. Update man page and mysql_tzinfo_to_sql to having a --skip-write-binlog option. merge notes: 10.4: - conflicts in tztime.cc can revert to this version of --help text. - tztime.cc - merge execute immediate @prep1, and leave %s%s trunc_tables, lock_tables after that. 10.6: - Need to remove the not_embedded.inc in mysql_tzinfo_to_sql.test and replace it with no_protocol.inc - leave both mysql_tzinfo_to_sql.test and mariadb_tzinfo_to_sql.sql tests. - sql/tztime.cc - keep entirely 10.6 version. --- man/mysql_tzinfo_to_sql.1 | 4 + .../r/mysql_tzinfo_to_sql_symlink.result | 23 +++ .../suite/galera/r/mysql_tzinfo_to_sql.result | 152 +++++++++++++++++ .../suite/galera/t/mysql_tzinfo_to_sql.opt | 1 + .../suite/galera/t/mysql_tzinfo_to_sql.test | 156 ++++++++++++++++++ .../r/mysql_tzinfo_to_sql_symlink.result | 150 ----------------- .../r/mysql_tzinfo_to_sql_symlink_skip.result | 78 --------- .../wsrep/t/mysql_tzinfo_to_sql_symlink.opt | 3 - .../wsrep/t/mysql_tzinfo_to_sql_symlink.test | 41 ----- .../t/mysql_tzinfo_to_sql_symlink_skip.opt | 3 - .../t/mysql_tzinfo_to_sql_symlink_skip.test | 41 ----- mysql-test/t/mysql_tzinfo_to_sql_symlink.test | 17 ++ sql/tztime.cc | 8 +- 13 files changed, 357 insertions(+), 320 deletions(-) create mode 100644 mysql-test/suite/galera/r/mysql_tzinfo_to_sql.result create mode 100644 mysql-test/suite/galera/t/mysql_tzinfo_to_sql.opt create mode 100644 mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test delete mode 100644 mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result delete mode 100644 mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result delete mode 100644 mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.opt delete mode 100644 mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test delete mode 100644 mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.opt delete mode 100644 mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test diff --git a/man/mysql_tzinfo_to_sql.1 b/man/mysql_tzinfo_to_sql.1 index 9ab70fbc2e4..1c7de159e75 100644 --- a/man/mysql_tzinfo_to_sql.1 +++ b/man/mysql_tzinfo_to_sql.1 @@ -41,6 +41,7 @@ can be invoked several ways: shell> \fBmysql_tzinfo_to_sql \fR\fB\fItz_dir\fR\fR shell> \fBmysql_tzinfo_to_sql \fR\fB\fItz_file tz_name\fR\fR shell> \fBmysql_tzinfo_to_sql \-\-leap \fR\fB\fItz_file\fR\fR +shell> \fBmysql_tzinfo_to_sql \-\-skip\-write\-binlog \fR\fB\fItz_dir\fR\fR .fi .if n \{\ .RE @@ -100,6 +101,9 @@ shell> \fBmysql_tzinfo_to_sql \-\-leap \fR\fB\fItz_file\fR\fR\fB | mysql \-u roo .RE .\} .PP +Using the \-\-skip\-write\-binlog option prevents writing of changes to the binary log or to other Galera +cluster members. This can be used with any form of running \fBmysql_tzinfo_to_sql\fR. +.PP After running \fBmysql_tzinfo_to_sql\fR, it is best to restart the server so that it does not continue to use any previously cached time zone data\&. .SH "COPYRIGHT" diff --git a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result index f56a2df2012..5753a719769 100644 --- a/mysql-test/r/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/r/mysql_tzinfo_to_sql_symlink.result @@ -149,6 +149,29 @@ ALTER TABLE time_zone_transition_type ENGINE=MyISAM; END IF| \d ; # +# MDEV-28263: mariadb-tzinfo-to-sql improve wsrep and binlog cases +# +# +# Testing --skip-write-binlog +# +set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION WSREP_ON=OFF', 'do 0'); +SET SESSION SQL_LOG_BIN=0; +execute immediate @prep1; +INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); +SET @time_zone_id= LAST_INSERT_ID(); +INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); +INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES + (@time_zone_id, 0, 0, 0, 'GMT') +; +set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION WSREP_ON=OFF', 'do 0'); +SET SESSION SQL_LOG_BIN=0; +execute immediate @prep1; +TRUNCATE TABLE time_zone_leap_second; +ALTER TABLE time_zone_leap_second ORDER BY Transition_time; +# +# End of 10.2 tests +# +# # MDEV-6236 - [PATCH] mysql_tzinfo_to_sql may produce invalid SQL # \d | diff --git a/mysql-test/suite/galera/r/mysql_tzinfo_to_sql.result b/mysql-test/suite/galera/r/mysql_tzinfo_to_sql.result new file mode 100644 index 00000000000..a140f517ac8 --- /dev/null +++ b/mysql-test/suite/galera/r/mysql_tzinfo_to_sql.result @@ -0,0 +1,152 @@ +# +# MDEV-28263: mariadb-tzinfo-to-sql improve wsrep and binlog cases +# + +# On node_1 +connection node_1; +CREATE TABLE time_zone LIKE mysql.time_zone; +CREATE TABLE time_zone_name LIKE mysql.time_zone_name; +CREATE TABLE time_zone_transition LIKE mysql.time_zone_transition; +CREATE TABLE time_zone_transition_type LIKE mysql.time_zone_transition_type; +CREATE TABLE time_zone_leap_second LIKE mysql.time_zone_leap_second; +# +# Run on zoneinfo directory --skip-write-binlog +# + +# Apply on node_1 + +load timezones +'binlog stationary as expected' +SELECT COUNT(*) FROM time_zone; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_name; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_transition; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition_type; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_leap_second; +COUNT(*) +0 + +# On node_2 (not replicated) + +connection node_2; +SELECT COUNT(*) FROM time_zone; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_name; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition_type; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_leap_second; +COUNT(*) +0 +# +# Run on zoneinfo directory without --skip-write-binlog +# + +# Apply on node_1 + +connection node_1; +load timezones +'binlog advanced as expected' +SELECT COUNT(*) FROM time_zone; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_name; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_transition; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition_type; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_leap_second; +COUNT(*) +0 + +# On node_2 (replicated via InnoDB) + +connection node_2; +SELECT COUNT(*) FROM time_zone; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_name; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_transition; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition_type; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_leap_second; +COUNT(*) +0 +TRUNCATE TABLE time_zone; +TRUNCATE TABLE time_zone_name; +TRUNCATE TABLE time_zone_transition; +TRUNCATE TABLE time_zone_transition_type; +TRUNCATE TABLE time_zone_leap_second; + +# Apply on node_1 (with wsrep_on=OFF) + +connection node_1; +SET GLOBAL WSREP_ON=OFF; +load timezones +SET GLOBAL WSREP_ON=ON; +'binlog advanced as expected' +SELECT COUNT(*) FROM time_zone; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_name; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_transition; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition_type; +COUNT(*) +2 +SELECT COUNT(*) FROM time_zone_leap_second; +COUNT(*) +0 + +# On node_2 (Should not have been replicated) + +connection node_2; +SELECT COUNT(*) FROM time_zone; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_name; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_transition_type; +COUNT(*) +0 +SELECT COUNT(*) FROM time_zone_leap_second; +COUNT(*) +0 +connection node_1; +DROP TABLE time_zone; +DROP TABLE time_zone_name; +DROP TABLE time_zone_transition; +DROP TABLE time_zone_transition_type; +DROP TABLE time_zone_leap_second; +# +# End of 10.2 tests +# diff --git a/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.opt b/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.opt new file mode 100644 index 00000000000..beae84b3862 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.opt @@ -0,0 +1 @@ +--log-bin diff --git a/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test b/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test new file mode 100644 index 00000000000..6bfad2f18b5 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql_tzinfo_to_sql.test @@ -0,0 +1,156 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/not_embedded.inc +# merge note: 10.6 change not_embedded.inc to no_protocol.inc + +# Unlike the similar galera.mariadb_tzinfo_to_sql.test in 10.6+, this +# tests that the output can be parsed by the mysql client. +--echo # +--echo # MDEV-28263: mariadb-tzinfo-to-sql improve wsrep and binlog cases +--echo # + +--exec mkdir $MYSQLTEST_VARDIR/zoneinfo +--exec ln -s $MYSQLTEST_VARDIR/zoneinfo $MYSQLTEST_VARDIR/zoneinfo/posix +--copy_file std_data/zoneinfo/GMT $MYSQLTEST_VARDIR/zoneinfo/GMT + +--echo +--echo # On node_1 +--connection node_1 + +CREATE TABLE time_zone LIKE mysql.time_zone; +CREATE TABLE time_zone_name LIKE mysql.time_zone_name; +CREATE TABLE time_zone_transition LIKE mysql.time_zone_transition; +CREATE TABLE time_zone_transition_type LIKE mysql.time_zone_transition_type; +CREATE TABLE time_zone_leap_second LIKE mysql.time_zone_leap_second; + +--echo # +--echo # Run on zoneinfo directory --skip-write-binlog +--echo # + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo 2>/dev/null > $MYSQL_TMP_DIR/tz.sql + +--echo +--echo # Apply on node_1 +--echo +--let $snap_pos= query_get_value(SHOW STATUS LIKE 'binlog_snapshot_position', Value, 1) +--echo load timezones +--exec $MYSQL test < "$MYSQL_TMP_DIR/tz.sql" +--let $new_snap_pos= query_get_value(SHOW STATUS LIKE 'binlog_snapshot_position', Value, 1) + +if ($snap_pos == $new_snap_pos) +{ +--echo 'binlog stationary as expected' +} + +SELECT COUNT(*) FROM time_zone; +SELECT COUNT(*) FROM time_zone_name; +SELECT COUNT(*) FROM time_zone_transition; +SELECT COUNT(*) FROM time_zone_transition_type; +SELECT COUNT(*) FROM time_zone_leap_second; + +--echo +--echo # On node_2 (not replicated) +--echo +--connection node_2 + +SELECT COUNT(*) FROM time_zone; +SELECT COUNT(*) FROM time_zone_name; +SELECT COUNT(*) FROM time_zone_transition; +SELECT COUNT(*) FROM time_zone_transition_type; +SELECT COUNT(*) FROM time_zone_leap_second; + +--echo # +--echo # Run on zoneinfo directory without --skip-write-binlog +--echo # + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL $MYSQLTEST_VARDIR/zoneinfo 2>/dev/null > $MYSQL_TMP_DIR/tz.sql + +--echo +--echo # Apply on node_1 +--echo +--connection node_1 + +--echo load timezones +--exec $MYSQL test < "$MYSQL_TMP_DIR/tz.sql" +--let $new_snap_pos= query_get_value(SHOW STATUS LIKE 'binlog_snapshot_position', Value, 1) + +if ($snap_pos < $new_snap_pos) +{ +--echo 'binlog advanced as expected' +} + +SELECT COUNT(*) FROM time_zone; +SELECT COUNT(*) FROM time_zone_name; +SELECT COUNT(*) FROM time_zone_transition; +SELECT COUNT(*) FROM time_zone_transition_type; +SELECT COUNT(*) FROM time_zone_leap_second; + +--echo +--echo # On node_2 (replicated via InnoDB) +--echo +--connection node_2 + +SELECT COUNT(*) FROM time_zone; +SELECT COUNT(*) FROM time_zone_name; +SELECT COUNT(*) FROM time_zone_transition; +SELECT COUNT(*) FROM time_zone_transition_type; +SELECT COUNT(*) FROM time_zone_leap_second; + +TRUNCATE TABLE time_zone; +TRUNCATE TABLE time_zone_name; +TRUNCATE TABLE time_zone_transition; +TRUNCATE TABLE time_zone_transition_type; +TRUNCATE TABLE time_zone_leap_second; + +--echo +--echo # Apply on node_1 (with wsrep_on=OFF) +--echo +--connection node_1 + +SET GLOBAL WSREP_ON=OFF; +--let $snap_pos= $new_snap_pos +--echo load timezones +--exec $MYSQL test < "$MYSQL_TMP_DIR/tz.sql" +--let $new_snap_pos= query_get_value(SHOW STATUS LIKE 'binlog_snapshot_position', Value, 1) +SET GLOBAL WSREP_ON=ON; + +if ($snap_pos < $new_snap_pos) +{ +--echo 'binlog advanced as expected' +} + +SELECT COUNT(*) FROM time_zone; +SELECT COUNT(*) FROM time_zone_name; +SELECT COUNT(*) FROM time_zone_transition; +SELECT COUNT(*) FROM time_zone_transition_type; +SELECT COUNT(*) FROM time_zone_leap_second; + +--echo +--echo # On node_2 (Should not have been replicated) +--echo +--connection node_2 + +SELECT COUNT(*) FROM time_zone; +SELECT COUNT(*) FROM time_zone_name; +SELECT COUNT(*) FROM time_zone_transition; +SELECT COUNT(*) FROM time_zone_transition_type; +SELECT COUNT(*) FROM time_zone_leap_second; + +# +# Cleanup +# + +--connection node_1 +--remove_file $MYSQL_TMP_DIR/tz.sql +--exec rm -rf $MYSQLTEST_VARDIR/zoneinfo +DROP TABLE time_zone; +DROP TABLE time_zone_name; +DROP TABLE time_zone_transition; +DROP TABLE time_zone_transition_type; +DROP TABLE time_zone_leap_second; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result deleted file mode 100644 index bcd96b86516..00000000000 --- a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result +++ /dev/null @@ -1,150 +0,0 @@ -# -# MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above -# -# Verbose run -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=InnoDB; -ALTER TABLE time_zone_name ENGINE=InnoDB; -ALTER TABLE time_zone_transition ENGINE=InnoDB; -ALTER TABLE time_zone_transition_type ENGINE=InnoDB; -END IF| -\d ; -TRUNCATE TABLE time_zone; -TRUNCATE TABLE time_zone_name; -TRUNCATE TABLE time_zone_transition; -TRUNCATE TABLE time_zone_transition_type; -START TRANSACTION; -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/ignored.tab' as time zone. Skipping it. -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it. -Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. -COMMIT; -ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; -ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=MyISAM; -ALTER TABLE time_zone_name ENGINE=MyISAM; -ALTER TABLE time_zone_transition ENGINE=MyISAM; -ALTER TABLE time_zone_transition_type ENGINE=MyISAM; -END IF| -\d ; -# Silent run -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=InnoDB; -ALTER TABLE time_zone_name ENGINE=InnoDB; -ALTER TABLE time_zone_transition ENGINE=InnoDB; -ALTER TABLE time_zone_transition_type ENGINE=InnoDB; -END IF| -\d ; -TRUNCATE TABLE time_zone; -TRUNCATE TABLE time_zone_name; -TRUNCATE TABLE time_zone_transition; -TRUNCATE TABLE time_zone_transition_type; -START TRANSACTION; -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. -COMMIT; -ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; -ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=MyISAM; -ALTER TABLE time_zone_name ENGINE=MyISAM; -ALTER TABLE time_zone_transition ENGINE=MyISAM; -ALTER TABLE time_zone_transition_type ENGINE=MyISAM; -END IF| -\d ; -# -# Testing with explicit timezonefile -# -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=InnoDB; -ALTER TABLE time_zone_name ENGINE=InnoDB; -ALTER TABLE time_zone_transition ENGINE=InnoDB; -ALTER TABLE time_zone_transition_type ENGINE=InnoDB; -END IF| -\d ; -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=MyISAM; -ALTER TABLE time_zone_name ENGINE=MyISAM; -ALTER TABLE time_zone_transition ENGINE=MyISAM; -ALTER TABLE time_zone_transition_type ENGINE=MyISAM; -END IF| -\d ; -# -# Testing --leap -# -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=InnoDB; -ALTER TABLE time_zone_name ENGINE=InnoDB; -ALTER TABLE time_zone_transition ENGINE=InnoDB; -ALTER TABLE time_zone_transition_type ENGINE=InnoDB; -END IF| -\d ; -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone_leap_second ENGINE=InnoDB; -END IF| -\d ; -TRUNCATE TABLE time_zone_leap_second; -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone_leap_second ENGINE=MyISAM; -END IF| -\d ; -ALTER TABLE time_zone_leap_second ORDER BY Transition_time; -\d | -IF (select count(*) from information_schema.global_variables where -variable_name='wsrep_on' and variable_value='ON') = 1 THEN -ALTER TABLE time_zone ENGINE=MyISAM; -ALTER TABLE time_zone_name ENGINE=MyISAM; -ALTER TABLE time_zone_transition ENGINE=MyISAM; -ALTER TABLE time_zone_transition_type ENGINE=MyISAM; -END IF| -\d ; diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result deleted file mode 100644 index aff02cb413e..00000000000 --- a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result +++ /dev/null @@ -1,78 +0,0 @@ -# -# MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above -# -# Verbose run -set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); -prepare set_wsrep_write_binlog from @prep1; -set @toggle=0; execute set_wsrep_write_binlog using @toggle; -TRUNCATE TABLE time_zone; -TRUNCATE TABLE time_zone_name; -TRUNCATE TABLE time_zone_transition; -TRUNCATE TABLE time_zone_transition_type; -START TRANSACTION; -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/ignored.tab' as time zone. Skipping it. -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it. -Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion. -COMMIT; -ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; -ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -# Silent run -set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); -prepare set_wsrep_write_binlog from @prep1; -set @toggle=0; execute set_wsrep_write_binlog using @toggle; -TRUNCATE TABLE time_zone; -TRUNCATE TABLE time_zone_name; -TRUNCATE TABLE time_zone_transition; -TRUNCATE TABLE time_zone_transition_type; -START TRANSACTION; -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/garbage' as time zone. Skipping it. -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('posix/GMT', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it. -COMMIT; -ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time; -ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id; -# -# Testing with explicit timezonefile -# -set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); -prepare set_wsrep_write_binlog from @prep1; -set @toggle=0; execute set_wsrep_write_binlog using @toggle; -INSERT INTO time_zone (Use_leap_seconds) VALUES ('N'); -SET @time_zone_id= LAST_INSERT_ID(); -INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('XXX', @time_zone_id); -INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset, Is_DST, Abbreviation) VALUES - (@time_zone_id, 0, 0, 0, 'GMT') -; -# -# Testing --leap -# -set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?'); -prepare set_wsrep_write_binlog from @prep1; -set @toggle=0; execute set_wsrep_write_binlog using @toggle; -TRUNCATE TABLE time_zone_leap_second; -ALTER TABLE time_zone_leap_second ORDER BY Transition_time; diff --git a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.opt b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.opt deleted file mode 100644 index 864f7342cc7..00000000000 --- a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.opt +++ /dev/null @@ -1,3 +0,0 @@ ---wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 --binlog_format=ROW - - diff --git a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test deleted file mode 100644 index 87554635666..00000000000 --- a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink.test +++ /dev/null @@ -1,41 +0,0 @@ ---source include/have_wsrep.inc ---source include/have_symlink.inc ---source include/not_windows.inc ---source include/have_innodb.inc - ---echo # ---echo # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above ---echo # - ---exec mkdir $MYSQLTEST_VARDIR/zoneinfo ---exec ln -s $MYSQLTEST_VARDIR/zoneinfo $MYSQLTEST_VARDIR/zoneinfo/posix ---copy_file std_data/zoneinfo/GMT $MYSQLTEST_VARDIR/zoneinfo/GMT ---copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/garbage ---copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/ignored.tab - ---echo # Verbose run ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---exec $MYSQL_TZINFO_TO_SQL --verbose $MYSQLTEST_VARDIR/zoneinfo 2>&1 - ---echo # Silent run ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---exec $MYSQL_TZINFO_TO_SQL $MYSQLTEST_VARDIR/zoneinfo 2>&1 - ---echo # ---echo # Testing with explicit timezonefile ---echo # - ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---exec $MYSQL_TZINFO_TO_SQL $MYSQLTEST_VARDIR/zoneinfo/GMT XXX 2>&1 - ---echo # ---echo # Testing --leap ---echo # - ---exec $MYSQL_TZINFO_TO_SQL --leap $MYSQLTEST_VARDIR/zoneinfo/GMT 2>&1 - -# -# Cleanup -# - ---exec rm -rf $MYSQLTEST_VARDIR/zoneinfo diff --git a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.opt b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.opt deleted file mode 100644 index 864f7342cc7..00000000000 --- a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.opt +++ /dev/null @@ -1,3 +0,0 @@ ---wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 --binlog_format=ROW - - diff --git a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test b/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test deleted file mode 100644 index ab1f94cc1cf..00000000000 --- a/mysql-test/suite/wsrep/t/mysql_tzinfo_to_sql_symlink_skip.test +++ /dev/null @@ -1,41 +0,0 @@ ---source include/have_wsrep.inc ---source include/have_symlink.inc ---source include/not_windows.inc ---source include/have_innodb.inc - ---echo # ---echo # MDEV-5226 mysql_tzinfo_to_sql errors with tzdata 2013f and above ---echo # - ---exec mkdir $MYSQLTEST_VARDIR/zoneinfo ---exec ln -s $MYSQLTEST_VARDIR/zoneinfo $MYSQLTEST_VARDIR/zoneinfo/posix ---copy_file std_data/zoneinfo/GMT $MYSQLTEST_VARDIR/zoneinfo/GMT ---copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/garbage ---copy_file std_data/words.dat $MYSQLTEST_VARDIR/zoneinfo/ignored.tab - ---echo # Verbose run ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---exec $MYSQL_TZINFO_TO_SQL --verbose --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo 2>&1 - ---echo # Silent run ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---exec $MYSQL_TZINFO_TO_SQL --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo 2>&1 - ---echo # ---echo # Testing with explicit timezonefile ---echo # - ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---exec $MYSQL_TZINFO_TO_SQL --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo/GMT XXX 2>&1 - ---echo # ---echo # Testing --leap ---echo # - ---exec $MYSQL_TZINFO_TO_SQL --leap --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo/GMT 2>&1 - -# -# Cleanup -# - ---exec rm -rf $MYSQLTEST_VARDIR/zoneinfo diff --git a/mysql-test/t/mysql_tzinfo_to_sql_symlink.test b/mysql-test/t/mysql_tzinfo_to_sql_symlink.test index 8ca82b87e30..fcb5916c4a2 100644 --- a/mysql-test/t/mysql_tzinfo_to_sql_symlink.test +++ b/mysql-test/t/mysql_tzinfo_to_sql_symlink.test @@ -32,6 +32,23 @@ --exec $MYSQL_TZINFO_TO_SQL --leap $MYSQLTEST_VARDIR/zoneinfo/GMT 2>&1 +--echo # +--echo # MDEV-28263: mariadb-tzinfo-to-sql improve wsrep and binlog cases +--echo # + +--echo # +--echo # Testing --skip-write-binlog +--echo # + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_TZINFO_TO_SQL --skip-write-binlog $MYSQLTEST_VARDIR/zoneinfo/GMT XXX 2>&1 + +--exec $MYSQL_TZINFO_TO_SQL --skip-write-binlog --leap $MYSQLTEST_VARDIR/zoneinfo/GMT 2>&1 + +--echo # +--echo # End of 10.2 tests +--echo # + # # Cleanup # diff --git a/sql/tztime.cc b/sql/tztime.cc index 47bc44f3386..8790673c5a0 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2642,7 +2642,7 @@ static struct my_option my_long_options[] = &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-write-binlog", 'S', "Do not replicate changes to time zone tables to other nodes in a Galera cluster.", + {"skip-write-binlog", 'S', "Do not replicate changes to time zone tables to the binary log, or to other nodes in a Galera cluster.", &opt_skip_write_binlog,&opt_skip_write_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -2738,9 +2738,9 @@ main(int argc, char **argv) sql_log_bin and wsrep_on to avoid Galera replicating below truncate table clauses. This will allow user to set different time zones to nodes in Galera cluster. */ - printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?');\n" - "prepare set_wsrep_write_binlog from @prep1;\n" - "set @toggle=0; execute set_wsrep_write_binlog using @toggle;\n"); + printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION WSREP_ON=OFF', 'do 0');\n" + "SET SESSION SQL_LOG_BIN=0;\n" + "execute immediate @prep1;\n"); } else { From 3b6c04f44c492bc3d0e494c9c7af7e95c682f3da Mon Sep 17 00:00:00 2001 From: Nayuta Yanagisawa Date: Sun, 24 Apr 2022 16:13:00 +0900 Subject: [PATCH 23/94] MDEV-27065 fixup: disable tests under valgrind The server behaves differently on the DATA/INDEX DIRECTORY clause under valgrind because symlink is disabled under valgrind. --- mysql-test/suite/parts/inc/part_alter_values.inc | 2 ++ mysql-test/suite/parts/t/partition_alter_myisam.test | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/parts/inc/part_alter_values.inc b/mysql-test/suite/parts/inc/part_alter_values.inc index 2f16476c78b..ca18faa5758 100644 --- a/mysql-test/suite/parts/inc/part_alter_values.inc +++ b/mysql-test/suite/parts/inc/part_alter_values.inc @@ -1,3 +1,5 @@ +--source include/have_symlink.inc + --echo # --echo # MDEV-14641 Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine --echo # diff --git a/mysql-test/suite/parts/t/partition_alter_myisam.test b/mysql-test/suite/parts/t/partition_alter_myisam.test index 326cf52b018..d3abb8842e1 100644 --- a/mysql-test/suite/parts/t/partition_alter_myisam.test +++ b/mysql-test/suite/parts/t/partition_alter_myisam.test @@ -1,5 +1,4 @@ --source include/have_partition.inc ---source include/have_symlink.inc --let $engine=MyISAM --source inc/part_alter_values.inc From 3fec38d91d852d0762dbcbc60c1d911a68f1509f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 25 Apr 2022 09:08:09 +0400 Subject: [PATCH 24/94] MDEV-28405 main.information_schema_tables fails sporadically with ER_NEED_REPREPARE or extra warning --- mysql-test/t/information_schema_tables.test | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mysql-test/t/information_schema_tables.test b/mysql-test/t/information_schema_tables.test index ebb1e21a65b..bc4f269a3fb 100644 --- a/mysql-test/t/information_schema_tables.test +++ b/mysql-test/t/information_schema_tables.test @@ -24,9 +24,14 @@ LOOP END LOOP $ --delimiter ; --connection default +# Avoid "Prepared statement needs to be re-prepared" +# Note, the code could probably eventually fixed to avoid forcing re-pepare if +# the *temporary* instance of Sp_caches (not the permanent one) was invalidated. +--disable_ps_protocol --disable_warnings SELECT v.* FROM v JOIN INFORMATION_SCHEMA.TABLES WHERE DATA_LENGTH = -1; --enable_warnings +--enable_ps_protocol # Cleanup --replace_result $conid CONID --eval KILL $conid From 907e4c62cec951646e9049dffc41a0a6eeeb821d Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 18 Apr 2022 19:43:25 +0400 Subject: [PATCH 25/94] MDEV-21037 mariabackup does not detect multi-source replication slave --- extra/mariabackup/backup_mysql.cc | 398 ++++++++++++++---- .../include/show_xtrabackup_slave_info.inc | 14 + .../show_xtrabackup_slave_info_out.inc | 20 + .../suite/mariabackup/rpl_slave_info.result | 7 + .../suite/mariabackup/rpl_slave_info.test | 5 + .../suite/mariabackup/slave_info_norpl.result | 59 +++ .../suite/mariabackup/slave_info_norpl.test | 86 ++++ 7 files changed, 510 insertions(+), 79 deletions(-) create mode 100644 mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc create mode 100644 mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info_out.inc create mode 100644 mysql-test/suite/mariabackup/slave_info_norpl.result create mode 100644 mysql-test/suite/mariabackup/slave_info_norpl.test diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index 78af2b7f5ac..bddf069f4e9 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -265,7 +265,8 @@ free_mysql_variables(mysql_variable *vars) static char * -read_mysql_one_value(MYSQL *connection, const char *query) +read_mysql_one_value(MYSQL *connection, const char *query, + uint column, uint expect_columns) { MYSQL_RES *mysql_result; MYSQL_ROW row; @@ -273,10 +274,10 @@ read_mysql_one_value(MYSQL *connection, const char *query) mysql_result = xb_mysql_query(connection, query, true); - ut_ad(mysql_num_fields(mysql_result) == 1); + ut_ad(mysql_num_fields(mysql_result) == expect_columns); if ((row = mysql_fetch_row(mysql_result))) { - result = strdup(row[0]); + result = strdup(row[column]); } mysql_free_result(mysql_result); @@ -284,6 +285,15 @@ read_mysql_one_value(MYSQL *connection, const char *query) return(result); } + +static +char * +read_mysql_one_value(MYSQL *mysql, const char *query) +{ + return read_mysql_one_value(mysql, query, 0/*offset*/, 1/*total columns*/); +} + + static bool check_server_version(unsigned long version_number, @@ -1196,92 +1206,322 @@ cleanup: } +class Var +{ + const char *m_name; + char *m_value; + /* + Disable copying constructors for safety, as the default binary copying + which would be wrong. If we ever want them, the m_value + member should be copied using an strdup()-alike function. + */ + Var(const Var &); // Disabled + Var(Var &); // Disabled +public: + ~Var() + { + free(m_value); + } + Var(const char *name) + :m_name(name), + m_value(NULL) + { } + // Init using a SHOW VARIABLES LIKE 'name' query + Var(const char *name, MYSQL *mysql) + :m_name(name) + { + char buf[128]; + my_snprintf(buf, sizeof(buf), "SHOW VARIABLES LIKE '%s'", m_name); + m_value= read_mysql_one_value(mysql, buf, 1/*offset*/, 2/*total columns*/); + } + /* + Init by name from a result set. + If the variable name is not found in the result set metadata field names, + it's value stays untouched. + */ + bool init(MYSQL_RES *mysql_result, MYSQL_ROW row) + { + MYSQL_FIELD *field= mysql_fetch_fields(mysql_result); + for (uint i= 0; i < mysql_num_fields(mysql_result); i++) + { + if (!strcmp(field[i].name, m_name)) + { + free(m_value); // In case it was initialized earlier + m_value= row[i] ? strdup(row[i]) : NULL; + return false; + } + } + return true; + } + void replace(char from, char to) + { + ut_ad(m_value); + for (char *ptr= strchr(m_value, from); ptr; ptr= strchr(ptr, from)) + *ptr= to; + } + + const char *value() const { return m_value; } + bool eq_value(const char *str, size_t length) const + { + return m_value && !strncmp(m_value, str, length) && m_value[length] == '\0'; + } + bool is_null_or_empty() const { return !m_value || !m_value[0]; } + bool print(String *to) const + { + ut_ad(m_value); + return to->append(m_value); + } + bool print_quoted(String *to) const + { + ut_ad(m_value); + return to->append("'") || to->append(m_value) || to->append("'"); + } + bool print_set_global(String *to) const + { + ut_ad(m_value); + return + to->append("SET GLOBAL ") || + to->append(m_name) || + to->append(" = '") || + to->append(m_value) || + to->append("';\n"); + } +}; + + +class Show_slave_status +{ + Var m_mariadb_connection_name; // MariaDB: e.g. 'master1' + Var m_master; // e.g. 'localhost' + Var m_filename; // e.g. 'source-bin.000002' + Var m_position; // a number + Var m_mysql_gtid_executed; // MySQL56: e.g. single ':1-5" or multiline + // ':1-10,\n:1-20\n:1-30' + Var m_mariadb_using_gtid; // MariaDB: 'No','Slave_Pos','Current_Pos' + +public: + + Show_slave_status() + :m_mariadb_connection_name("Connection_name"), + m_master("Master_Host"), + m_filename("Relay_Master_Log_File"), + m_position("Exec_Master_Log_Pos"), + m_mysql_gtid_executed("Executed_Gtid_Set"), + m_mariadb_using_gtid("Using_Gtid") + { } + + void init(MYSQL_RES *res, MYSQL_ROW row) + { + m_mariadb_connection_name.init(res, row); + m_master.init(res, row); + m_filename.init(res, row); + m_position.init(res, row); + m_mysql_gtid_executed.init(res, row); + m_mariadb_using_gtid.init(res, row); + // Normalize + if (m_mysql_gtid_executed.value()) + m_mysql_gtid_executed.replace('\n', ' '); + } + + static void msg_is_not_slave() + { + msg("Failed to get master binlog coordinates " + "from SHOW SLAVE STATUS.This means that the server is not a " + "replication slave. Ignoring the --slave-info option"); + } + + bool is_mariadb_using_gtid() const + { + return !m_mariadb_using_gtid.eq_value("No", 2); + } + + static bool start_comment_chunk(String *to) + { + return to->length() ? to->append("; ") : false; + } + + bool print_connection_name_if_set(String *to) const + { + if (!m_mariadb_connection_name.is_null_or_empty()) + return m_mariadb_connection_name.print_quoted(to) || to->append(' '); + return false; + } + + bool print_comment_master_identity(String *comment) const + { + if (comment->append("master ")) + return true; + if (!m_mariadb_connection_name.is_null_or_empty()) + return m_mariadb_connection_name.print_quoted(comment); + return comment->append("''"); // Default not named master + } + + bool print_using_master_log_pos(String *sql, String *comment) const + { + return + sql->append("CHANGE MASTER ") || + print_connection_name_if_set(sql) || + sql->append("TO MASTER_LOG_FILE=") || m_filename.print_quoted(sql) || + sql->append(", MASTER_LOG_POS=") || m_position.print(sql) || + sql->append(";\n") || + print_comment_master_identity(comment) || + comment->append(" filename ") || m_filename.print_quoted(comment) || + comment->append(" position ") || m_position.print_quoted(comment); + } + + bool print_mysql56(String *sql, String *comment) const + { + /* + SET @@GLOBAL.gtid_purged = '2174B383-5441-11E8-B90A-C80AA9429562:1-1029, ' + '224DA167-0C0C-11E8-8442-00059A3C7B00:1-2695'; + CHANGE MASTER TO MASTER_AUTO_POSITION=1; + */ + return + sql->append("SET GLOBAL gtid_purged=") || + m_mysql_gtid_executed.print_quoted(sql) || + sql->append(";\n") || + sql->append("CHANGE MASTER TO MASTER_AUTO_POSITION=1;\n") || + print_comment_master_identity(comment) || + comment->append(" purge list ") || + m_mysql_gtid_executed.print_quoted(comment); + } + + bool print_mariadb10_using_gtid(String *sql, String *comment) const + { + return + sql->append("CHANGE MASTER ") || + print_connection_name_if_set(sql) || + sql->append("TO master_use_gtid = slave_pos;\n") || + print_comment_master_identity(comment) || + comment->append(" master_use_gtid = slave_pos"); + } + + bool print(String *sql, String *comment, const Var >id_slave_pos) const + { + if (!m_mysql_gtid_executed.is_null_or_empty()) + { + /* MySQL >= 5.6 with GTID enabled */ + return print_mysql56(sql, comment); + } + + if (!gtid_slave_pos.is_null_or_empty() && is_mariadb_using_gtid()) + { + /* MariaDB >= 10.0 with GTID enabled */ + return print_mariadb10_using_gtid(sql, comment); + } + + return print_using_master_log_pos(sql, comment); + } + + /* + Get master info into strings "sql" and "comment" from a MYSQL_RES. + @return false on success + @return true on error + */ + static bool get_slave_info(MYSQL_RES *show_slave_info_result, + const Var >id_slave_pos, + String *sql, String *comment) + { + if (!gtid_slave_pos.is_null_or_empty()) + { + // Print gtid_slave_pos if any of the masters really needs it. + while (MYSQL_ROW row= mysql_fetch_row(show_slave_info_result)) + { + Show_slave_status status; + status.init(show_slave_info_result, row); + if (status.is_mariadb_using_gtid()) + { + if (gtid_slave_pos.print_set_global(sql) || + comment->append("gtid_slave_pos ") || + gtid_slave_pos.print_quoted(comment)) + return true; // Error + break; + } + } + } + + // Print the list of masters + mysql_data_seek(show_slave_info_result, 0); + while (MYSQL_ROW row= mysql_fetch_row(show_slave_info_result)) + { + Show_slave_status status; + status.init(show_slave_info_result, row); + if (start_comment_chunk(comment) || + status.print(sql, comment, gtid_slave_pos)) + return true; // Error + } + return false; // Success + } + + /* + Get master info into strings "sql" and "comment". + @return false on success + @return true on error + */ + static bool get_slave_info(MYSQL *mysql, bool show_all_slave_status, + String *sql, String *comment) + { + bool rc= false; // Success + // gtid_slave_pos - MariaDB variable : e.g. "0-1-1" or "1-10-100,2-20-500" + Var gtid_slave_pos("gtid_slave_pos", mysql); + const char *query= show_all_slave_status ? "SHOW ALL SLAVES STATUS" : + "SHOW SLAVE STATUS"; + MYSQL_RES *mysql_result= xb_mysql_query(mysql, query, true); + if (!mysql_num_rows(mysql_result)) + { + msg_is_not_slave(); + // Don't change rc, we still want to continue the backup + } + else + { + rc= get_slave_info(mysql_result, gtid_slave_pos, sql, comment); + } + mysql_free_result(mysql_result); + return rc; + } +}; + + + /*********************************************************************//** Retrieves MySQL binlog position of the master server in a replication setup and saves it in a file. It also saves it in mysql_slave_position -variable. */ +variable. +@returns false on error +@returns true on success +*/ bool write_slave_info(MYSQL *connection) { - char *master = NULL; - char *filename = NULL; - char *gtid_executed = NULL; - char *using_gtid = NULL; - char *position = NULL; - char *gtid_slave_pos = NULL; - char *ptr; - bool result = false; + String sql, comment; + bool show_all_slaves_status= false; - mysql_variable status[] = { - {"Master_Host", &master}, - {"Relay_Master_Log_File", &filename}, - {"Exec_Master_Log_Pos", &position}, - {"Executed_Gtid_Set", >id_executed}, - {"Using_Gtid", &using_gtid}, - {NULL, NULL} - }; + switch (server_flavor) + { + case FLAVOR_MARIADB: + show_all_slaves_status= mysql_server_version >= 100000; + break; + case FLAVOR_UNKNOWN: + case FLAVOR_MYSQL: + case FLAVOR_PERCONA_SERVER: + break; + } - mysql_variable variables[] = { - {"gtid_slave_pos", >id_slave_pos}, - {NULL, NULL} - }; + if (Show_slave_status::get_slave_info(connection, show_all_slaves_status, + &sql, &comment)) + return false; // Error - read_mysql_variables(connection, "SHOW SLAVE STATUS", status, false); - read_mysql_variables(connection, "SHOW VARIABLES", variables, true); + if (!sql.length()) + { + /* + SHOW [ALL] SLAVE STATUS returned no rows. + Don't create the file, but return success to continue the backup. + */ + return true; // Success + } - if (master == NULL || filename == NULL || position == NULL) { - msg("Failed to get master binlog coordinates " - "from SHOW SLAVE STATUS.This means that the server is not a " - "replication slave. Ignoring the --slave-info option"); - /* we still want to continue the backup */ - result = true; - goto cleanup; - } - - /* Print slave status to a file. - If GTID mode is used, construct a CHANGE MASTER statement with - MASTER_AUTO_POSITION and correct a gtid_purged value. */ - if (gtid_executed != NULL && *gtid_executed) { - /* MySQL >= 5.6 with GTID enabled */ - - for (ptr = strchr(gtid_executed, '\n'); - ptr; - ptr = strchr(ptr, '\n')) { - *ptr = ' '; - } - - result = backup_file_printf(XTRABACKUP_SLAVE_INFO, - "SET GLOBAL gtid_purged='%s';\n" - "CHANGE MASTER TO MASTER_AUTO_POSITION=1\n", - gtid_executed); - - ut_a(asprintf(&mysql_slave_position, - "master host '%s', purge list '%s'", - master, gtid_executed) != -1); - } else if (gtid_slave_pos && *gtid_slave_pos && - !(using_gtid && !strncmp(using_gtid, "No", 2))) { - /* MariaDB >= 10.0 with GTID enabled */ - result = backup_file_printf(XTRABACKUP_SLAVE_INFO, - "SET GLOBAL gtid_slave_pos = '%s';\n" - "CHANGE MASTER TO master_use_gtid = slave_pos\n", - gtid_slave_pos); - ut_a(asprintf(&mysql_slave_position, - "master host '%s', gtid_slave_pos %s", - master, gtid_slave_pos) != -1); - } else { - result = backup_file_printf(XTRABACKUP_SLAVE_INFO, - "CHANGE MASTER TO MASTER_LOG_FILE='%s', " - "MASTER_LOG_POS=%s\n", filename, position); - ut_a(asprintf(&mysql_slave_position, - "master host '%s', filename '%s', position '%s'", - master, filename, position) != -1); - } - -cleanup: - free_mysql_variables(status); - free_mysql_variables(variables); - - return(result); + mysql_slave_position= strdup(comment.c_ptr()); + return backup_file_print_buf(XTRABACKUP_SLAVE_INFO, sql.ptr(), sql.length()); } diff --git a/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc b/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc new file mode 100644 index 00000000000..4a83c9c394e --- /dev/null +++ b/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info.inc @@ -0,0 +1,14 @@ +--disable_query_log +--file_exists $targetdir/xtrabackup_slave_info +CREATE TEMPORARY TABLE tmp_slave_info(lineno SERIAL, line TEXT); +--replace_result $targetdir TARGETDIR +--eval LOAD DATA LOCAL INFILE '$targetdir/xtrabackup_slave_info' INTO TABLE tmp_slave_info (line); +SELECT + lineno, + regexp_replace( + regexp_replace(line, '(?<=MASTER_LOG_POS=)[0-9]+', ''), + '[0-9]+-[0-9]+-[0-9]+', '') + AS line +FROM tmp_slave_info ORDER BY lineno; +DROP TEMPORARY TABLE tmp_slave_info; +--enable_query_log diff --git a/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info_out.inc b/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info_out.inc new file mode 100644 index 00000000000..90b2d00b61d --- /dev/null +++ b/mysql-test/suite/mariabackup/include/show_xtrabackup_slave_info_out.inc @@ -0,0 +1,20 @@ +--disable_query_log +--file_exists $XTRABACKUP_OUT +CREATE TEMPORARY TABLE tmp_slave_info_out(lineno SERIAL, line TEXT); +--replace_result $targetdir TARGETDIR +--eval LOAD DATA LOCAL INFILE '$XTRABACKUP_OUT' INTO TABLE tmp_slave_info_out (line); +SELECT + replace( + regexp_replace( + regexp_replace(line, + '[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]', + 'YYYY-MM-DD hh:mm:ss'), + '[0-9]+-[0-9]+-[0-9]+', ''), + '\r','' /* Remove CR on Windows */) + AS line +FROM tmp_slave_info_out +WHERE line LIKE '%MySQL slave binlog position%' + OR line LIKE '%Failed to get master binlog coordinates%' +ORDER BY lineno; +DROP TEMPORARY TABLE tmp_slave_info_out; +--enable_query_log diff --git a/mysql-test/suite/mariabackup/rpl_slave_info.result b/mysql-test/suite/mariabackup/rpl_slave_info.result index 13044fd6c39..ec27166ecfb 100644 --- a/mysql-test/suite/mariabackup/rpl_slave_info.result +++ b/mysql-test/suite/mariabackup/rpl_slave_info.result @@ -13,6 +13,9 @@ connection slave; "using_gtid: Slave_Pos" FOUND 1 /gtid_slave_pos/ in xtrabackup_slave_info NOT FOUND /MASTER_LOG_FILE/ in xtrabackup_slave_info +lineno line +1 SET GLOBAL gtid_slave_pos = ''; +2 CHANGE MASTER TO master_use_gtid = slave_pos; ############### # If Using_Gtid != 'No' and !gtid_slave_pos, backup master position ######################## @@ -20,6 +23,8 @@ include/stop_slave.inc SET GLOBAL gtid_slave_pos=""; NOT FOUND /gtid_slave_pos/ in xtrabackup_slave_info FOUND 1 /MASTER_LOG_FILE/ in xtrabackup_slave_info +lineno line +1 CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=; ############### # If Using_Gtid == 'No', backup Exec_Master_Log_Pos ######################## @@ -31,6 +36,8 @@ connection slave; "using_gtid: No" NOT FOUND /gtid_slave_pos/ in xtrabackup_slave_info FOUND 1 /MASTER_LOG_FILE/ in xtrabackup_slave_info +lineno line +1 CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=; connection master; DROP TABLE t; connection slave; diff --git a/mysql-test/suite/mariabackup/rpl_slave_info.test b/mysql-test/suite/mariabackup/rpl_slave_info.test index ca7682d8af9..1c5dd89acc9 100644 --- a/mysql-test/suite/mariabackup/rpl_slave_info.test +++ b/mysql-test/suite/mariabackup/rpl_slave_info.test @@ -27,6 +27,7 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffi --source include/search_pattern_in_file.inc --let SEARCH_PATTERN=MASTER_LOG_FILE --source include/search_pattern_in_file.inc +--source include/show_xtrabackup_slave_info.inc rmdir $targetdir; @@ -35,7 +36,9 @@ rmdir $targetdir; --echo ######################## --source include/stop_slave.inc +--disable_warnings SET GLOBAL gtid_slave_pos=""; +--enable_warnings --let $targetdir=$MYSQLTEST_VARDIR/tmp/backup --disable_result_log @@ -47,6 +50,7 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffi --source include/search_pattern_in_file.inc --let SEARCH_PATTERN=MASTER_LOG_FILE --source include/search_pattern_in_file.inc +--source include/show_xtrabackup_slave_info.inc rmdir $targetdir; @@ -74,6 +78,7 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffi --source include/search_pattern_in_file.inc --let SEARCH_PATTERN=MASTER_LOG_FILE --source include/search_pattern_in_file.inc +--source include/show_xtrabackup_slave_info.inc rmdir $targetdir; diff --git a/mysql-test/suite/mariabackup/slave_info_norpl.result b/mysql-test/suite/mariabackup/slave_info_norpl.result new file mode 100644 index 00000000000..9fcd67a8916 --- /dev/null +++ b/mysql-test/suite/mariabackup/slave_info_norpl.result @@ -0,0 +1,59 @@ +# +# Start of 10.2 tests +# +# +# MDEV-21037 mariabackup does not detect multi-source replication slave +# +SELECT @@global.gtid_slave_pos; +@@global.gtid_slave_pos + + +# Without any masters the file xtrabackup_slave_info is not created +line +[00] YYYY-MM-DD hh:mm:ss Failed to get master binlog coordinates from SHOW SLAVE STATUS.This means that the server is not a replication slave. Ignoring the --slave-info option + +CHANGE MASTER TO MASTER_HOST='localhost', MASTER_PORT=10000; +lineno line +1 CHANGE MASTER TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +line +[00] YYYY-MM-DD hh:mm:ss MySQL slave binlog position: master '' filename '' position '0' + +CHANGE MASTER 'master2' TO MASTER_HOST='localhost', MASTER_PORT=10002; +lineno line +1 CHANGE MASTER TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +2 CHANGE MASTER 'master2' TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +line +[00] YYYY-MM-DD hh:mm:ss MySQL slave binlog position: master '' filename '' position '0'; master 'master2' filename '' position '0' + +SET GLOBAL gtid_slave_pos='1-1-1,2-2-2'; +CHANGE MASTER 'master3' TO MASTER_HOST='localhost', MASTER_PORT=10003, MASTER_USE_GTID=slave_pos; +CHANGE MASTER 'master4' TO MASTER_HOST='localhost', MASTER_PORT=10004, MASTER_USE_GTID=no; +CHANGE MASTER 'master5' TO MASTER_HOST='localhost', MASTER_PORT=10005, MASTER_USE_GTID=slave_pos; +lineno line +1 SET GLOBAL gtid_slave_pos = ','; +2 CHANGE MASTER TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +3 CHANGE MASTER 'master2' TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +4 CHANGE MASTER 'master3' TO master_use_gtid = slave_pos; +5 CHANGE MASTER 'master4' TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +6 CHANGE MASTER 'master5' TO master_use_gtid = slave_pos; +line +[00] YYYY-MM-DD hh:mm:ss MySQL slave binlog position: gtid_slave_pos ','; master '' filename '' position '0'; master 'master2' filename '' position '0'; master 'master3' master_use_gtid = slave_pos; master 'master4' filename '' position '0'; master 'master5' master_use_gtid = slave_pos + +CHANGE MASTER TO MASTER_HOST='localhost', MASTER_PORT=10000, MASTER_USE_GTID=slave_pos; +lineno line +1 SET GLOBAL gtid_slave_pos = ','; +2 CHANGE MASTER TO master_use_gtid = slave_pos; +3 CHANGE MASTER 'master2' TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +4 CHANGE MASTER 'master3' TO master_use_gtid = slave_pos; +5 CHANGE MASTER 'master4' TO MASTER_LOG_FILE='', MASTER_LOG_POS=; +6 CHANGE MASTER 'master5' TO master_use_gtid = slave_pos; +line +[00] YYYY-MM-DD hh:mm:ss MySQL slave binlog position: gtid_slave_pos ','; master '' master_use_gtid = slave_pos; master 'master2' filename '' position '0'; master 'master3' master_use_gtid = slave_pos; master 'master4' filename '' position '0'; master 'master5' master_use_gtid = slave_pos +RESET SLAVE ALL; +RESET SLAVE 'master2' ALL; +RESET SLAVE 'master3' ALL; +RESET SLAVE 'master4' ALL; +RESET SLAVE 'master5' ALL; +# +# End of 10.2 tests +# diff --git a/mysql-test/suite/mariabackup/slave_info_norpl.test b/mysql-test/suite/mariabackup/slave_info_norpl.test new file mode 100644 index 00000000000..0d2d2ed4861 --- /dev/null +++ b/mysql-test/suite/mariabackup/slave_info_norpl.test @@ -0,0 +1,86 @@ +# +# "mariabackup --slave-info" tests that can be run without +# actually starting the replication. +# + +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-21037 mariabackup does not detect multi-source replication slave +--echo # + +--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup +--let $XTRABACKUP_ARGS=--defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 --slave-info --backup --databases=test --target-dir=$targetdir +--let $XTRABACKUP_OUT=$MYSQLTEST_VARDIR/tmp/xtrabackup_out + +# Should be empty by default +SELECT @@global.gtid_slave_pos; + +--echo +--echo # Without any masters the file xtrabackup_slave_info is not created + +--disable_result_log +exec $XTRABACKUP $XTRABACKUP_ARGS >$XTRABACKUP_OUT; +--enable_result_log +--error 1 +--file_exists $targetdir/xtrabackup_slave_info +--source include/show_xtrabackup_slave_info_out.inc +--remove_file $XTRABACKUP_OUT +rmdir $targetdir; + +--echo +CHANGE MASTER TO MASTER_HOST='localhost', MASTER_PORT=10000; +--disable_result_log +exec $XTRABACKUP $XTRABACKUP_ARGS >$XTRABACKUP_OUT; +--enable_result_log +--source include/show_xtrabackup_slave_info.inc +--source include/show_xtrabackup_slave_info_out.inc +--remove_file $XTRABACKUP_OUT +rmdir $targetdir; + +--echo +CHANGE MASTER 'master2' TO MASTER_HOST='localhost', MASTER_PORT=10002; +--disable_result_log +exec $XTRABACKUP $XTRABACKUP_ARGS >$XTRABACKUP_OUT; +--enable_result_log +--source include/show_xtrabackup_slave_info.inc +--source include/show_xtrabackup_slave_info_out.inc +--remove_file $XTRABACKUP_OUT +rmdir $targetdir; + +--echo +SET GLOBAL gtid_slave_pos='1-1-1,2-2-2'; +CHANGE MASTER 'master3' TO MASTER_HOST='localhost', MASTER_PORT=10003, MASTER_USE_GTID=slave_pos; +CHANGE MASTER 'master4' TO MASTER_HOST='localhost', MASTER_PORT=10004, MASTER_USE_GTID=no; +CHANGE MASTER 'master5' TO MASTER_HOST='localhost', MASTER_PORT=10005, MASTER_USE_GTID=slave_pos; + +--disable_result_log +exec $XTRABACKUP $XTRABACKUP_ARGS >$XTRABACKUP_OUT; +--enable_result_log +--source include/show_xtrabackup_slave_info.inc +--source include/show_xtrabackup_slave_info_out.inc +--remove_file $XTRABACKUP_OUT +rmdir $targetdir; + +--echo +CHANGE MASTER TO MASTER_HOST='localhost', MASTER_PORT=10000, MASTER_USE_GTID=slave_pos; +--disable_result_log +exec $XTRABACKUP $XTRABACKUP_ARGS >$XTRABACKUP_OUT; +--enable_result_log +--source include/show_xtrabackup_slave_info.inc +--source include/show_xtrabackup_slave_info_out.inc +--remove_file $XTRABACKUP_OUT +rmdir $targetdir; + +RESET SLAVE ALL; +RESET SLAVE 'master2' ALL; +RESET SLAVE 'master3' ALL; +RESET SLAVE 'master4' ALL; +RESET SLAVE 'master5' ALL; + + +--echo # +--echo # End of 10.2 tests +--echo # From b208030ef5b4274fd66cc9667a2dc96f6e63db81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 25 Apr 2022 14:14:02 +0300 Subject: [PATCH 26/94] MDEV-11415 merge fixup: Remove a redundant call In merge commit 921c5e931452301a09c84c53ffe35b81e6a1c71a the call log_free_check() was accidentally duplicated, causing a small performance regression on INSERT. --- storage/innobase/row/row0ins.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index d3ef1c89c4a..8cfad511d06 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2021, MariaDB Corporation. +Copyright (c) 2016, 2022, 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 @@ -3194,9 +3194,6 @@ row_ins_clust_index_entry( ? BTR_NO_LOCKING_FLAG : 0; const ulint orig_n_fields = entry->n_fields; - /* Try first optimistic descent to the B-tree */ - log_free_check(); - /* For intermediate table during copy alter table, skip the undo log and record lock checking for insertion operation. From 1bcdc3e9eb1a393fd07403c874ac7d7edc6d8a0a Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 14 Apr 2022 18:59:24 +0300 Subject: [PATCH 27/94] MDEV-27697 slave must recognize incomplete replication event group In cases of a faulty master or an incorrect binlog event producer, that slave is working with, sends an incomplete group of events slave must react with an error to not to log into the relay-log any new events that do not belong to the incomplete group. Fixed with extending received event properties check when slave connects to master in gtid mode. Specifically for the event that can be a part of a group its relay-logging is permitted only when its position within the group is validated. Otherwise slave IO thread stops with ER_SLAVE_RELAY_LOG_WRITE_FAILURE. --- mysql-test/extra/rpl_tests/rpl_parallel.inc | 1 + .../suite/rpl/r/rpl_gtid_grouping.result | 54 ++++++ mysql-test/suite/rpl/r/rpl_parallel.result | 1 + mysql-test/suite/rpl/t/rpl_gtid_grouping.test | 97 +++++++++++ sql/rpl_gtid.h | 1 + sql/slave.cc | 164 +++++++++++++++--- 6 files changed, 292 insertions(+), 26 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_gtid_grouping.result create mode 100644 mysql-test/suite/rpl/t/rpl_gtid_grouping.test diff --git a/mysql-test/extra/rpl_tests/rpl_parallel.inc b/mysql-test/extra/rpl_tests/rpl_parallel.inc index b88d2126d4d..9ba7a30f2eb 100644 --- a/mysql-test/extra/rpl_tests/rpl_parallel.inc +++ b/mysql-test/extra/rpl_tests/rpl_parallel.inc @@ -1872,6 +1872,7 @@ SET GLOBAL slave_parallel_threads=10; SET GLOBAL slave_parallel_threads=1; SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000"; +CALL mtr.add_suppression("Unexpected break of being relay-logged GTID"); --connection server_1 INSERT INTO t2 VALUES (101); diff --git a/mysql-test/suite/rpl/r/rpl_gtid_grouping.result b/mysql-test/suite/rpl/r/rpl_gtid_grouping.result new file mode 100644 index 00000000000..ad7d6116c49 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gtid_grouping.result @@ -0,0 +1,54 @@ +include/master-slave.inc +[connection master] +connection slave; +call mtr.add_suppression("Unexpected break of being relay-logged GTID 0-27697-1000"); +call mtr.add_suppression("Relay log write failure: could not queue event from master"); +call mtr.add_suppression("The current group of events starts with a non-GTID"); +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +include/start_slave.inc +connection master; +CREATE TABLE t (a INT) ENGINE=innodb; +INSERT INTO t VALUES(1); +### A. Simulate an unnoticeable loss of Xid event +connection slave; +SET @@global.debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000"; +connection master; +SET @@gtid_seq_no=1000; +set @@server_id=27697; +INSERT INTO t VALUES(1000); +set @@server_id=default; +INSERT INTO t VALUES(1001); +## Prove the error occurs. +connection slave; +include/wait_for_slave_io_error.inc [errno=1595] +## Prove the slave recovers after the simulation condtion is lifted. +SET @@global.debug_dbug=default; +include/start_slave.inc +### B. Do the same to GTID event. +connection slave; +SET @@global.debug_dbug="+d,slave_discard_gtid_0_x_1002"; +connection master; +SET @@gtid_seq_no=1002; +set @@server_id=27697; +INSERT INTO t VALUES(1002); +set @@server_id=default; +INSERT INTO t VALUES(1003); +## Prove the error occurs. +connection slave; +include/wait_for_slave_io_error.inc [errno=1595] +## Prove the slave recovers after the simulation condtion is lifted. +SET @@global.debug_dbug=default; +include/start_slave.inc +connection master; +connection slave; +include/diff_tables.inc [master:t,slave:t] +"===== Clean up =====" +connection slave; +include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +include/start_slave.inc +connection master; +DROP TABLE t; +SET GLOBAL LOG_WARNINGS=default; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result index 657b3ba7448..2601b30279e 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel.result +++ b/mysql-test/suite/rpl/r/rpl_parallel.result @@ -1378,6 +1378,7 @@ include/stop_slave.inc SET GLOBAL slave_parallel_threads=1; SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000"; +CALL mtr.add_suppression("Unexpected break of being relay-logged GTID"); connection server_1; INSERT INTO t2 VALUES (101); INSERT INTO t2 VALUES (102); diff --git a/mysql-test/suite/rpl/t/rpl_gtid_grouping.test b/mysql-test/suite/rpl/t/rpl_gtid_grouping.test new file mode 100644 index 00000000000..66448c4f96c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_grouping.test @@ -0,0 +1,97 @@ +# ==== Purpose ==== +# +# Test verifies that replicated transaction boundaries are set properly +# at receiving from master time. +# +# ==== Implementation ==== +# +# A. Simulate an unnoticeable loss of Xid event to observe a slave error, +# then restart slave to recover from the failure. +# B. Do the same to GTID event. +# +# ==== References ==== +# +# MDEV-27697 slave must recognize incomplete replication event group +# +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/master-slave.inc + +--connection slave +call mtr.add_suppression("Unexpected break of being relay-logged GTID 0-27697-1000"); +call mtr.add_suppression("Relay log write failure: could not queue event from master"); +call mtr.add_suppression("The current group of events starts with a non-GTID"); + +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +--connection master +CREATE TABLE t (a INT) ENGINE=innodb; +INSERT INTO t VALUES(1); +save_master_pos; + +--echo ### A. Simulate an unnoticeable loss of Xid event +--sync_slave_with_master +SET @@global.debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000"; + +--connection master +SET @@gtid_seq_no=1000; +set @@server_id=27697; +INSERT INTO t VALUES(1000); +set @@server_id=default; +INSERT INTO t VALUES(1001); + +--echo ## Prove the error occurs. +--connection slave +# ER_SLAVE_RELAY_LOG_WRITE_FAILURE +--let $slave_io_errno = 1595 +--source include/wait_for_slave_io_error.inc +## EOP + +--echo ## Prove the slave recovers after the simulation condtion is lifted. +SET @@global.debug_dbug=default; +--source include/start_slave.inc + +--echo ### B. Do the same to GTID event. +--connection slave +SET @@global.debug_dbug="+d,slave_discard_gtid_0_x_1002"; + +--connection master +SET @@gtid_seq_no=1002; +set @@server_id=27697; +INSERT INTO t VALUES(1002); +set @@server_id=default; +INSERT INTO t VALUES(1003); + +--echo ## Prove the error occurs. +--connection slave +# ER_SLAVE_RELAY_LOG_WRITE_FAILURE +--let $slave_io_errno = 1595 +--source include/wait_for_slave_io_error.inc +## EOP + +--echo ## Prove the slave recovers after the simulation condtion is lifted. +SET @@global.debug_dbug=default; +--source include/start_slave.inc + +--connection master +save_master_pos; + +--sync_slave_with_master +## EOP + +--let $diff_tables=master:t,slave:t +--source include/diff_tables.inc + +--echo "===== Clean up =====" +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +--source include/start_slave.inc + +--connection master +DROP TABLE t; +SET GLOBAL LOG_WARNINGS=default; +--source include/rpl_end.inc diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index e4949ff0d39..bb171f3d95d 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -26,6 +26,7 @@ extern const LEX_STRING rpl_gtid_slave_state_table_name; class String; +#define PARAM_GTID(G) G.domain_id, G.server_id, G.seq_no struct rpl_gtid { diff --git a/sql/slave.cc b/sql/slave.cc index 2ff1a0490e9..31e50753c9e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -6196,23 +6196,75 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) } } - if (unlikely(mi->gtid_reconnect_event_skip_count)) - { - goto default_action; - } - /* - We have successfully queued to relay log everything before this GTID, so + Unless the previous group is malformed, + we have successfully queued to relay log everything before this GTID, so in case of reconnect we can start from after any previous GTID. - (Normally we would have updated gtid_current_pos earlier at the end of - the previous event group, but better leave an extra check here for - safety). + (We must have updated gtid_current_pos earlier at the end of + the previous event group. Unless ...) */ - if (mi->events_queued_since_last_gtid) + if (unlikely(mi->events_queued_since_last_gtid > + mi->gtid_reconnect_event_skip_count)) { - mi->gtid_current_pos.update(&mi->last_queued_gtid); - mi->events_queued_since_last_gtid= 0; + /* + ...unless the last group has not been completed. An assert below + can be satisfied only with the strict mode that ensures + against "genuine" gtid duplicates. + */ + rpl_gtid *gtid_in_slave_state= + mi->gtid_current_pos.find(mi->last_queued_gtid.domain_id); + + // Slave gtid state must not have updated yet to the last received gtid. + DBUG_ASSERT((mi->using_gtid == Master_info::USE_GTID_NO || + !opt_gtid_strict_mode) || + (!gtid_in_slave_state || + !(*gtid_in_slave_state == mi->last_queued_gtid))); + + DBUG_EXECUTE_IF("slave_discard_xid_for_gtid_0_x_1000", + { + /* Inject an event group that is missing its XID commit event. */ + if (mi->last_queued_gtid.domain_id == 0 && + mi->last_queued_gtid.seq_no == 1000) + { + sql_print_warning( + "Unexpected break of being relay-logged GTID %u-%u-%llu " + "event group by the current GTID event %u-%u-%llu", + PARAM_GTID(mi->last_queued_gtid),PARAM_GTID(event_gtid)); + DBUG_SET("-d,slave_discard_xid_for_gtid_0_x_1000"); + goto dbug_gtid_accept; + } + }); + error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; + sql_print_error("Unexpected break of being relay-logged GTID %u-%u-%llu " + "event group by the current GTID event %u-%u-%llu", + PARAM_GTID(mi->last_queued_gtid),PARAM_GTID(event_gtid)); + goto err; } + else if (unlikely(mi->gtid_reconnect_event_skip_count > 0)) + { + if (mi->gtid_reconnect_event_skip_count == + mi->events_queued_since_last_gtid) + { + DBUG_ASSERT(event_gtid == mi->last_queued_gtid); + + goto default_action; + } + + DBUG_ASSERT(0); + } + // else_likely{... +#ifndef DBUG_OFF +dbug_gtid_accept: + DBUG_EXECUTE_IF("slave_discard_gtid_0_x_1002", + { + if (mi->last_queued_gtid.server_id == 27697 && + mi->last_queued_gtid.seq_no == 1002) + { + DBUG_SET("-d,slave_discard_gtid_0_x_1002"); + goto skip_relay_logging; + } + }); +#endif mi->last_queued_gtid= event_gtid; mi->last_queued_gtid_standalone= (gtid_flag & Gtid_log_event::FL_STANDALONE) != 0; @@ -6222,6 +6274,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) ++mi->events_queued_since_last_gtid; inc_pos= event_len; + // ...} eof else_likely } break; /* @@ -6274,6 +6327,12 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) case XID_EVENT: DBUG_EXECUTE_IF("slave_discard_xid_for_gtid_0_x_1000", { + if (mi->last_queued_gtid.server_id == 27697 && + mi->last_queued_gtid.seq_no == 1000) + { + DBUG_SET("-d,slave_discard_xid_for_gtid_0_x_1000"); + goto skip_relay_logging; + } /* Inject an event group that is missing its XID commit event. */ if (mi->last_queued_gtid.domain_id == 0 && mi->last_queued_gtid.seq_no == 1000) @@ -6319,15 +6378,48 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) } };); - if (mi->using_gtid != Master_info::USE_GTID_NO && mi->gtid_event_seen) + if (mi->using_gtid != Master_info::USE_GTID_NO) { - if (unlikely(mi->gtid_reconnect_event_skip_count)) + if (likely(mi->gtid_event_seen)) { - --mi->gtid_reconnect_event_skip_count; - gtid_skip_enqueue= true; + if (unlikely(mi->gtid_reconnect_event_skip_count)) + { + if (!got_gtid_event && + mi->gtid_reconnect_event_skip_count == + mi->events_queued_since_last_gtid) + goto gtid_not_start; // the 1st re-sent must be gtid + + --mi->gtid_reconnect_event_skip_count; + gtid_skip_enqueue= true; + } + else if (likely(mi->events_queued_since_last_gtid)) + { + DBUG_ASSERT(!got_gtid_event); + + ++mi->events_queued_since_last_gtid; + } + else if (Log_event::is_group_event((Log_event_type) (uchar) + buf[EVENT_TYPE_OFFSET])) + { + goto gtid_not_start; // no first gtid event in this group + } + } + else if (Log_event::is_group_event((Log_event_type) (uchar) + buf[EVENT_TYPE_OFFSET])) + { + gtid_not_start: + + DBUG_ASSERT(!got_gtid_event); + + error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; + sql_print_error("The current group of events starts with " + "a non-GTID %s event; " + "the last seen GTID is %u-%u-%llu", + Log_event::get_type_str((Log_event_type) (uchar) + buf[EVENT_TYPE_OFFSET]), + mi->last_queued_gtid); + goto err; } - else if (mi->events_queued_since_last_gtid) - ++mi->events_queued_since_last_gtid; } if (!is_compress_event) @@ -6500,15 +6592,35 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) Query_log_event::peek_is_commit_rollback(buf, event_len, checksum_alg)))))) { - /* - The whole of the current event group is queued. So in case of - reconnect we can start from after the current GTID. - */ - mi->gtid_current_pos.update(&mi->last_queued_gtid); - mi->events_queued_since_last_gtid= 0; + DBUG_ASSERT(mi->events_queued_since_last_gtid > 1); - /* Reset the domain_id_filter flag. */ - mi->domain_id_filter.reset_filter(); + if (unlikely(gtid_skip_enqueue)) + { + error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; + sql_print_error("Recieved a group closing %s event " + "at %llu position in the group while there are " + "still %llu events to skip upon reconnecting; " + "the last seen GTID is %u-%u-%llu", + Log_event::get_type_str((Log_event_type) (uchar) + buf[EVENT_TYPE_OFFSET]), + (mi->events_queued_since_last_gtid - + mi->gtid_reconnect_event_skip_count), + mi->events_queued_since_last_gtid, + mi->last_queued_gtid); + goto err; + } + else + { + /* + The whole of the current event group is queued. So in case of + reconnect we can start from after the current GTID. + */ + mi->gtid_current_pos.update(&mi->last_queued_gtid); + mi->events_queued_since_last_gtid= 0; + + /* Reset the domain_id_filter flag. */ + mi->domain_id_filter.reset_filter(); + } } skip_relay_logging: From d16c3aca3c3ecd1050b2527c213f4fdf1959d9e2 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 13 Apr 2022 12:45:50 -0600 Subject: [PATCH 28/94] MDEV-26473: mysqld got exception 0xc0000005 (rpl_slave_state/rpl_load_gtid_slave_state) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: ======== During mysqld initialization, if the number of GTIDs added since that last purge of the mysql.gtid_slave_pos tables is greater than or equal to the –-gtid-cleanup-batch-size value, a race condition can occur. Specifically, the binlog background thread will submit the bg_gtid_delete_pending job to the mysql handle manager; however, the mysql handle manager may not be initialized, leading to crashes. Solution: ======== Force the mysql handle manager to initialize/start before the binlog background thread is created. Reviewed By: ============ Andrei Elkin --- .../r/rpl_mysql_manager_race_condition.result | 27 ++++++++ ...rpl_mysql_manager_race_condition-slave.opt | 1 + .../t/rpl_mysql_manager_race_condition.test | 67 +++++++++++++++++++ sql/mysqld.cc | 2 +- sql/sql_manager.cc | 1 + 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result create mode 100644 mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt create mode 100644 mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test diff --git a/mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result b/mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result new file mode 100644 index 00000000000..1172d8e39a9 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result @@ -0,0 +1,27 @@ +include/master-slave.inc +[connection master] +connection master; +# Create a GTID event so the binlog background thread will submit a +# mysql handler job the next time mysqld is restarted. +create table t1 (a int); +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +# Set a debug point that forces the main mysqld thread to sleep before +# anything is initialized for the mysql handle manager +# Restart the slave mysqld instance so it re-initializes with the +# binlog background thread submitting a mysql handler job and the +# mysql handler initialization suspending for a second. Without the fix +# associated with this test/patch, the following restart will error +# with a failed assertion. +include/rpl_restart_server.inc [server_number=2 parameters: --debug_dbug="+d,delay_start_handle_manager"] +include/start_slave.inc +# +# Cleanup +# +connection master; +drop table t1; +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt new file mode 100644 index 00000000000..d127ef62043 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition-slave.opt @@ -0,0 +1 @@ +--gtid-cleanup-batch-size=1 diff --git a/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test new file mode 100644 index 00000000000..751da3158b7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test @@ -0,0 +1,67 @@ +# +# Purpose: +# This test ensures that, during mysqld initialization, the mysql handle +# manager starts before the binlog background thread. This is because the +# binlog background thread uses the mysql handle manager, and if the background +# thread tries to submit a job to the handle manager before it is +# initialized/started, mysqld can crash (the actual behavior is undefined). +# This race condition lead to the problem described in MDEV-26473. +# +# Methodology: +# This test ensures that the binlog background thread cannot be started +# before the mysql manager is started. Specifically, it forces a path in +# the binlog background thread to call mysql_manager_submit() by reducing +# --gtid-cleanup-batch-size to be 1 (which submits a job to delete unused rows +# from the mysql.gtid_slave_pos* tables). With this path forced, the main +# mysqld thread is suspended just before its handle manager initialization to +# allow time for the binlog thread to call mysql_manager_submit. The fix +# associated with this test should enforce that the binlog background thread is +# not created before the handle manager is initialized. +# +# References: +# MDEV-26473 mysqld got exception 0xc0000005 (rpl_slave_state/rpl_load_gtid_slave_state) +# + +--source include/have_debug.inc +--source include/master-slave.inc + +# The race condition discovered from MDEV-26473 is binlog format independent. +# We use ROW format though because it was used by the reporter. +--source include/have_binlog_format_row.inc + +--connection master + +--echo # Create a GTID event so the binlog background thread will submit a +--echo # mysql handler job the next time mysqld is restarted. +create table t1 (a int); +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc + +--echo # Set a debug point that forces the main mysqld thread to sleep before +--echo # anything is initialized for the mysql handle manager +--let $rpl_server_parameters=--debug_dbug="+d,delay_start_handle_manager" + + +--echo # Restart the slave mysqld instance so it re-initializes with the +--echo # binlog background thread submitting a mysql handler job and the +--echo # mysql handler initialization suspending for a second. Without the fix +--echo # associated with this test/patch, the following restart will error +--echo # with a failed assertion. +--source include/rpl_restart_server.inc +--source include/start_slave.inc + + +--echo # +--echo # Cleanup +--echo # + +--connection master +drop table t1; +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc + +--source include/rpl_end.inc diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 754f0821cd8..fb3bee9db1a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5405,6 +5405,7 @@ static int init_server_components() unireg_abort(1); } + start_handle_manager(); if (opt_bin_log) { int error; @@ -5864,7 +5865,6 @@ int mysqld_main(int argc, char **argv) } create_shutdown_event(); - start_handle_manager(); /* Copy default global rpl_filter to global_rpl_filter */ copy_filter_setting(global_rpl_filter, get_or_create_rpl_filter("", 0)); diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index b08e43e8af2..97f525ea3a6 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -133,6 +133,7 @@ void start_handle_manager() { pthread_t hThread; int err; + DBUG_EXECUTE_IF("delay_start_handle_manager", my_sleep(1000);); manager_thread_in_use = 1; mysql_cond_init(key_COND_manager, &COND_manager,NULL); mysql_mutex_init(key_LOCK_manager, &LOCK_manager, NULL); From c5e68b6dcddbb6325c7684bfb4fba28e1c13e1ae Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 22 Apr 2022 07:53:16 -0700 Subject: [PATCH 29/94] MDEV-27212 Crash in Item_equal::sort on second execution of stored procedure This bug could cause a crash of the server at the second call of a stored procedure when it executed a query containing a mergeable derived table / view whose specification used another mergeable derived_table or view and a subquery with outer reference in the select list of the specification. Such queries could cause the same problem when they were executed for the second time in a prepared mode. The problem appeared due to a typo mistake in the legacy code of the function create_view_field() that prevented building Item_direct_view_ref wrapper for the mentioned outer reference at the second execution of the query and setting the depended_from field for the outer reference. Approved by Oleksandr Byelkin --- mysql-test/r/derived_view.result | 60 ++++++++++++++++++++++++++++++++ mysql-test/t/derived_view.test | 52 +++++++++++++++++++++++++++ sql/table.cc | 2 +- 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 0c045e39271..31a92207442 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -3586,4 +3586,64 @@ f2 f3 DROP PROCEDURE p1; DROP VIEW v1,v2,v3; DROP TABLE t1; +# +# MDEV-27212: 2-nd execution of PS for select with embedded derived tables +# and correlated subquery in select list of outer derived +# +create table t1 ( id int, id2 int ) engine=myisam; +create table t2 ( x3 int , x1 int , x2 int, a1 int) engine=myisam; +insert into t1 values (3, 2), (4, 2), (3, 4); +insert into t2 values (1, 2, 2, 1), (1, 3, 3, 2), (2, 3, 3, 1); +prepare stmt from "select id from t1 +join +( select dt2.x1, +( select sum(a1) from t2 where t2.x1 = dt2.x1 ) m +from ( select x1 from t2 u where x3 = 1 ) dt2 +) dt +on t1.id = dt.x1 +where t1.id2 < dt.m"; +execute stmt; +id +3 +execute stmt; +id +3 +deallocate prepare stmt; +create procedure sp1() select id from t1 +join +( select dt2.x1, +( select sum(a1) from t2 where t2.x1 = dt2.x1 ) m +from ( select x1 from t2 u where x3 = 1 ) dt2 +) dt +on t1.id = dt.x1 +where t1.id2 < dt.m; +call sp1(); +id +3 +call sp1(); +id +3 +create view v2 as select x1 from t2 u where x3 = 1; +create view v as +select v2.x1, +( select sum(a1) from t2 where t2.x1 = v2.x1 ) m from v2; +prepare stmt from "select id from t1 join v on t1.id = v.x1 where t1.id2 < v.m"; +execute stmt; +id +3 +execute stmt; +id +3 +deallocate prepare stmt; +create procedure sp2() select id from t1 join v on t1.id = v.x1 where t1.id2 < v.m; +call sp2(); +id +3 +call sp2(); +id +3 +drop procedure sp1; +drop procedure sp2; +drop view v, v2; +drop table t1,t2; # End of 10.2 tests diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index 0f3d9b224ba..f36401271cc 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -2376,4 +2376,56 @@ DROP PROCEDURE p1; DROP VIEW v1,v2,v3; DROP TABLE t1; +--echo # +--echo # MDEV-27212: 2-nd execution of PS for select with embedded derived tables +--echo # and correlated subquery in select list of outer derived +--echo # +create table t1 ( id int, id2 int ) engine=myisam; +create table t2 ( x3 int , x1 int , x2 int, a1 int) engine=myisam; +insert into t1 values (3, 2), (4, 2), (3, 4); +insert into t2 values (1, 2, 2, 1), (1, 3, 3, 2), (2, 3, 3, 1); + +let $q= +select id from t1 + join + ( select dt2.x1, + ( select sum(a1) from t2 where t2.x1 = dt2.x1 ) m + from ( select x1 from t2 u where x3 = 1 ) dt2 + ) dt + on t1.id = dt.x1 +where t1.id2 < dt.m; + +eval prepare stmt from "$q"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +eval create procedure sp1() $q; +call sp1(); +call sp1(); + +create view v2 as select x1 from t2 u where x3 = 1; +create view v as +select v2.x1, + ( select sum(a1) from t2 where t2.x1 = v2.x1 ) m from v2; + +let $q= +select id from t1 join v on t1.id = v.x1 where t1.id2 < v.m; + +eval prepare stmt from "$q"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +eval create procedure sp2() $q; +call sp2(); +call sp2(); + +drop procedure sp1; +drop procedure sp2; + +drop view v, v2; + +drop table t1,t2; + --echo # End of 10.2 tests diff --git a/sql/table.cc b/sql/table.cc index a5f1a5d96cf..605a2e0ddbf 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5984,7 +5984,7 @@ Item *Field_iterator_view::create_item(THD *thd) Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, const char *name) { - bool save_wrapper= thd->lex->select_lex.no_wrap_view_item; + bool save_wrapper= thd->lex->current_select->no_wrap_view_item; Item *field= *field_ref; DBUG_ENTER("create_view_field"); From 9b7886bbf1eeb80136f0c208ef74fcc300514f50 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 24 Apr 2022 15:16:07 +0200 Subject: [PATCH 30/94] MDEV-28403 ASAN heap-use-after-free in String::copy / get_field_default_value This reverts commit 5ba77222e9fe7af8ff403816b5338b18b342053c but keeps the test. A different fix for MDEV-21028 Server crashes in Query_arena::set_query_arena upon SELECT from view internal temporary tables should use THD as expr_area --- mysql-test/r/func_default.result | 21 +++++++++++++++++---- mysql-test/t/func_default.test | 11 +++++++++++ sql/sql_select.cc | 4 ++-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/func_default.result b/mysql-test/r/func_default.result index 2b5c869ee66..8e4a647ff8e 100644 --- a/mysql-test/r/func_default.result +++ b/mysql-test/r/func_default.result @@ -167,8 +167,8 @@ create algorithm=temptable view v1 as select * from t1; create algorithm=merge view v2 as select * from t1; select default(a) = now() from v1; default(a) = now() -NULL -NULL +1 +1 select default(a) = now() from v2; default(a) = now() 1 @@ -191,16 +191,29 @@ default(v1) 2001-01-01 10:20:30 select default(v1) from (select v1 from t1 group by v1) dt; default(v1) -0000-00-00 00:00:00 +2001-01-01 10:20:30 drop table t1; create table t1 (a text default ''); create algorithm=temptable view v1 as select * from t1; insert into t1 values ('a'); select default(a) from v1; default(a) -NULL + drop view v1; drop table t1; # +# MDEV-28403 ASAN heap-use-after-free in String::copy / get_field_default_value +# +create table t (a blob default 'x'); +create view v as select * from t; +insert into t () values (); +update t set a = default; +select table_name,column_name,column_default from information_schema.columns where table_name = 'v'; +table_name v +column_name a +column_default 'x' +drop view v; +drop table t; +# # End of 10.2 tests # diff --git a/mysql-test/t/func_default.test b/mysql-test/t/func_default.test index f542a279478..53cd94e58c4 100644 --- a/mysql-test/t/func_default.test +++ b/mysql-test/t/func_default.test @@ -165,6 +165,17 @@ select default(a) from v1; drop view v1; drop table t1; +--echo # +--echo # MDEV-28403 ASAN heap-use-after-free in String::copy / get_field_default_value +--echo # +create table t (a blob default 'x'); +create view v as select * from t; +insert into t () values (); +update t set a = default; +query_vertical select table_name,column_name,column_default from information_schema.columns where table_name = 'v'; +drop view v; +drop table t; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d2186f60709..e9d81417ee6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16333,8 +16333,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, table->s->db_create_options|= HA_OPTION_PACK_RECORD; else if (org_field->type() == FIELD_TYPE_DOUBLE) ((Field_double *) new_field)->not_fixed= TRUE; - new_field->vcol_info= new_field->default_value= - new_field->check_constraint= 0; + new_field->vcol_info= 0; new_field->cond_selectivity= 1.0; new_field->next_equal_field= NULL; new_field->option_list= NULL; @@ -16901,6 +16900,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List &fields, table->intersect_keys.init(); table->keys_in_use_for_query.init(); table->no_rows_with_nulls= param->force_not_null_cols; + table->expr_arena= thd; table->s= share; init_tmp_table_share(thd, share, "", 0, "(temporary)", tmpname); From 1a94d2fdb13a7a49471a2bb00a6bc6e596752aeb Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 23 Apr 2022 11:44:45 +0200 Subject: [PATCH 31/94] cleanup: main.create_select test --- ...select_tmp.result => create_select.result} | 8 ++++- ...ate_select_tmp.test => create_select.test} | 34 +++++++++---------- 2 files changed, 24 insertions(+), 18 deletions(-) rename mysql-test/r/{create_select_tmp.result => create_select.result} (82%) rename mysql-test/t/{create_select_tmp.test => create_select.test} (82%) diff --git a/mysql-test/r/create_select_tmp.result b/mysql-test/r/create_select.result similarity index 82% rename from mysql-test/r/create_select_tmp.result rename to mysql-test/r/create_select.result index f499e539baf..ef400c1cad9 100644 --- a/mysql-test/r/create_select_tmp.result +++ b/mysql-test/r/create_select.result @@ -1,4 +1,7 @@ -drop table if exists t1, t2; +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +# +# Testcase for BUG#4551 +# CREATE TABLE t1 ( a int ); INSERT INTO t1 VALUES (1),(2),(1); CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1; @@ -18,3 +21,6 @@ ERROR 23000: Duplicate entry '1' for key 'PRIMARY' select * from t2; ERROR 42S02: Table 'test.t2' doesn't exist drop table t1; +# +# End of 4.1 tests +# diff --git a/mysql-test/t/create_select_tmp.test b/mysql-test/t/create_select.test similarity index 82% rename from mysql-test/t/create_select_tmp.test rename to mysql-test/t/create_select.test index ef3315aed97..c97624eae7e 100644 --- a/mysql-test/t/create_select_tmp.test +++ b/mysql-test/t/create_select.test @@ -1,39 +1,39 @@ -# Testcase for BUG#4551 +# This does not work for RBR yet. +--source include/have_innodb.inc +--source include/have_binlog_format_mixed_or_statement.inc + +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +--echo # +--echo # Testcase for BUG#4551 +--echo # + # The bug was that when the table was TEMPORARY, it was not deleted if # the CREATE SELECT failed (the code intended too, but it actually # didn't). And as the CREATE TEMPORARY TABLE was not written to the # binlog if it was a transactional table, it resulted in an # inconsistency between binlog and the internal list of temp tables. -# This does not work for RBR yet. ---source include/have_binlog_format_mixed_or_statement.inc - ---disable_query_log -CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); ---enable_query_log - --- source include/have_innodb.inc ---disable_warnings -drop table if exists t1, t2; ---enable_warnings CREATE TABLE t1 ( a int ); INSERT INTO t1 VALUES (1),(2),(1); --error ER_DUP_ENTRY CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1; ---error 1146 +--error ER_NO_SUCH_TABLE select * from t2; --error ER_DUP_ENTRY CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1; ---error 1146 +--error ER_NO_SUCH_TABLE select * from t2; --error ER_DUP_ENTRY CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1; ---error 1146 +--error ER_NO_SUCH_TABLE select * from t2; --error ER_DUP_ENTRY CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1; ---error 1146 +--error ER_NO_SUCH_TABLE select * from t2; drop table t1; -# End of 4.1 tests +--echo # +--echo # End of 4.1 tests +--echo # From 7753eae1c06044d998318fa3a1dbb98f5a310c57 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 23 Apr 2022 12:21:08 +0200 Subject: [PATCH 32/94] MDEV-28393 Server crashes in TABLE::mark_default_fields_for_write test only --- mysql-test/r/create_select.result | 11 +++++++++++ mysql-test/t/create_select.test | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/mysql-test/r/create_select.result b/mysql-test/r/create_select.result index ef400c1cad9..6c6ab77522d 100644 --- a/mysql-test/r/create_select.result +++ b/mysql-test/r/create_select.result @@ -24,3 +24,14 @@ drop table t1; # # End of 4.1 tests # +# +# MDEV-28393 Server crashes in TABLE::mark_default_fields_for_write +# +create table t1 (a int, b text not null default ''); +alter table t1 character set = utf8; +create table t2 select * from t1; +insert into t1 values (1,''); +drop table t1, t2; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/create_select.test b/mysql-test/t/create_select.test index c97624eae7e..170bbba31d4 100644 --- a/mysql-test/t/create_select.test +++ b/mysql-test/t/create_select.test @@ -37,3 +37,16 @@ drop table t1; --echo # --echo # End of 4.1 tests --echo # + +--echo # +--echo # MDEV-28393 Server crashes in TABLE::mark_default_fields_for_write +--echo # +create table t1 (a int, b text not null default ''); +alter table t1 character set = utf8; +create table t2 select * from t1; +insert into t1 values (1,''); +drop table t1, t2; + +--echo # +--echo # End of 10.2 tests +--echo # From 3988dfff6234581e80bdeb768058b9ac47078681 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 21 Apr 2022 17:34:30 +0200 Subject: [PATCH 33/94] MDEV-6899 extra semicolon in show create event syntax to detect the end of SP definition correctly we need to know where the parser stopped parsing the SP. lip->get_cpp_ptr() shows the current parsing position, lip->get_cpp_tok_start() shows the start of the last parsed token. The actual value depends on whether the parser has performed a look-ahead. For example, in CREATE PROCEDURE ... BEGIN ... END ; the parser reads 'END' and knows that this ends the procedure definition, it does not need to read the next token for this. But in CREATE PROCEDURE ... SELECT 1 ; the parser cannot know that the procedure ends at '1'. It has to read the semicolon first (it could be '1 + 2' for example). In the first case, the "current parsing position" is after END, before the semicolon, in the second case it's *after* the semicolon. Note that SP definition in both cases ends before the semicolon. To be able to detect the end of SP deterministically, we need the parser to do the look-ahead always or never. The bug fix introduces a new parser token FORCE_LOOKAHEAD. Lexer never returns it, so this token can never match. But the parser cannot know it so it will have to perform a look-ahead to determine that the next token is not FORCE_LOOKAHEAD. This way we deterministically end SP parsing with a look-ahead. --- mysql-test/r/parser.result | 42 +++++++++++++++++++++++++ mysql-test/r/parser_not_embedded.result | 20 ++++++++++++ mysql-test/t/parser.test | 24 ++++++++++++++ mysql-test/t/parser_not_embedded.test | 15 +++++++++ sql/sp_head.cc | 2 +- sql/sql_yacc.yy | 18 ++++++----- 6 files changed, 113 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 9e091688e1d..e8bf9d12a33 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -1367,5 +1367,47 @@ SELECT tmp 1.e.test FROM scientific_notation AS tmp; 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 '1.e.test FROM scientific_notation AS tmp' at line 1 DROP TABLE scientific_notation; # +# MDEV-6899 extra semicolon in show create event syntax +# +set timestamp=unix_timestamp('2020-10-10 5:5:5'); +create table t1 (a int); +create trigger a before insert on t1 for each row set @a:=1;select 2$ +2 +2 +show create trigger a; +Trigger a +sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION +SQL Original Statement CREATE DEFINER=`root`@`localhost` trigger a before insert on t1 for each row set @a:=1 +character_set_client latin1 +collation_connection latin1_swedish_ci +Database Collation latin1_swedish_ci +Created 2020-10-10 05:05:05.00 +drop table t1; +create procedure a() select 1;select 2$ +2 +2 +show create procedure a; +Procedure a +sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION +Create Procedure CREATE DEFINER=`root`@`localhost` PROCEDURE `a`() +select 1 +character_set_client latin1 +collation_connection latin1_swedish_ci +Database Collation latin1_swedish_ci +drop procedure a; +create function a() returns int return 1;select 2$ +2 +2 +show create function a; +Function a +sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION +Create Function CREATE DEFINER=`root`@`localhost` FUNCTION `a`() RETURNS int(11) +return 1 +character_set_client latin1 +collation_connection latin1_swedish_ci +Database Collation latin1_swedish_ci +drop function a; +set timestamp=default; +# # End of 10.2 tests # diff --git a/mysql-test/r/parser_not_embedded.result b/mysql-test/r/parser_not_embedded.result index 25349e51577..2147e25b3b1 100644 --- a/mysql-test/r/parser_not_embedded.result +++ b/mysql-test/r/parser_not_embedded.result @@ -102,3 +102,23 @@ ROLLBACK AND NO CHAIN NO RELEASE; # # End of 5.5 tests # +# +# MDEV-6899 extra semicolon in show create event syntax +# +set timestamp=unix_timestamp('2020-10-10 5:5:5'); +create event a on schedule every 1 day do set @a:=1;select 2$ +2 +2 +show create event a; +Event a +sql_mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION +time_zone SYSTEM +Create Event CREATE DEFINER=`root`@`localhost` EVENT `a` ON SCHEDULE EVERY 1 DAY STARTS '2020-10-10 05:05:05' ON COMPLETION NOT PRESERVE ENABLE DO set @a:=1 +character_set_client latin1 +collation_connection latin1_swedish_ci +Database Collation latin1_swedish_ci +drop event a; +set timestamp=default; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index efb936d8ea4..095d274724b 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -1408,6 +1408,30 @@ SELECT tmp 1.e.test FROM scientific_notation AS tmp; DROP TABLE scientific_notation; +--echo # +--echo # MDEV-6899 extra semicolon in show create event syntax +--echo # +set timestamp=unix_timestamp('2020-10-10 5:5:5'); +create table t1 (a int); +delimiter $; +create trigger a before insert on t1 for each row set @a:=1;select 2$ +delimiter ;$ +query_vertical show create trigger a; +drop table t1; + +delimiter $; +create procedure a() select 1;select 2$ +delimiter ;$ +query_vertical show create procedure a; +drop procedure a; + +delimiter $; +create function a() returns int return 1;select 2$ +delimiter ;$ +query_vertical show create function a; +drop function a; +set timestamp=default; + --echo # --echo # End of 10.2 tests --echo # diff --git a/mysql-test/t/parser_not_embedded.test b/mysql-test/t/parser_not_embedded.test index 3af1260f4ad..270573ece93 100644 --- a/mysql-test/t/parser_not_embedded.test +++ b/mysql-test/t/parser_not_embedded.test @@ -99,3 +99,18 @@ ROLLBACK AND NO CHAIN NO RELEASE; --echo # --echo # End of 5.5 tests --echo # + +--echo # +--echo # MDEV-6899 extra semicolon in show create event syntax +--echo # +set timestamp=unix_timestamp('2020-10-10 5:5:5'); +delimiter $; +create event a on schedule every 1 day do set @a:=1;select 2$ +delimiter ;$ +query_vertical show create event a; +drop event a; +set timestamp=default; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/sp_head.cc b/sql/sp_head.cc index cb5348cd110..66df02d99fb 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -700,7 +700,7 @@ void sp_head::set_stmt_end(THD *thd) { Lex_input_stream *lip= & thd->m_parser_state->m_lip; /* shortcut */ - const char *end_ptr= lip->get_cpp_ptr(); /* shortcut */ + const char *end_ptr= lip->get_cpp_tok_start(); /* shortcut */ uint not_used; /* Make the string of parameters. */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 528d4ee4bdc..bade0bd3752 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1035,10 +1035,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 98 shift/reduce conflicts. + Currently there are 119 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 115 +%expect 119 /* Comments for TOKENS. @@ -1258,6 +1258,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token FOLLOWS_SYM /* MYSQL trigger*/ %token FOLLOWING_SYM /* SQL-2011-N */ %token FORCE_SYM +%token FORCE_LOOKAHEAD /* INTERNAL never returned by the lexer */ %token FOREIGN /* SQL-2003-R */ %token FOR_SYM /* SQL-2003-R */ %token FORMAT_SYM @@ -2710,6 +2711,9 @@ server_option: } ; +/* this rule is used to force look-ahead in the parser */ +force_lookahead: {} | FORCE_LOOKAHEAD {} ; + event_tail: remember_name EVENT_SYM opt_if_not_exists sp_name { @@ -2854,7 +2858,7 @@ ev_sql_stmt: lex->sp_chistics.suid= SP_IS_SUID; //always the definer! lex->sphead->set_body_start(thd, lip->get_cpp_ptr()); } - sp_proc_stmt + sp_proc_stmt force_lookahead { LEX *lex= thd->lex; @@ -16838,8 +16842,8 @@ trigger_tail: lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); } - sp_proc_stmt /* $20 */ - { /* $21 */ + sp_proc_stmt force_lookahead + { LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -16939,7 +16943,7 @@ sf_tail: lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); } - sp_proc_stmt_in_returns_clause /* $15 */ + sp_proc_stmt_in_returns_clause /* $15 */ force_lookahead { LEX *lex= thd->lex; sp_head *sp= lex->sphead; @@ -17020,7 +17024,7 @@ sp_tail: { Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start()); } - sp_proc_stmt + sp_proc_stmt force_lookahead { LEX *lex= Lex; sp_head *sp= lex->sphead; From 551e7814ed0cde2d8696ce228c7e9c6ee1a64696 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 26 Apr 2022 12:24:56 +1000 Subject: [PATCH 34/94] MDEV-28227 Chinese translation postfix Add chinese language to missing sql/share/CMakeLists.txt that results in installed files. Also add bulgarian=bgn which has existing for a long time. Sort both lists properly. Append both to debian/mariadb-server-core-10.4 too. --- debian/mariadb-server-core-10.4.install | 2 ++ sql/share/CMakeLists.txt | 30 +++++++++++++------------ sql/share/errmsg-utf8.txt | 2 +- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/debian/mariadb-server-core-10.4.install b/debian/mariadb-server-core-10.4.install index 9139949a24e..36c62a29895 100644 --- a/debian/mariadb-server-core-10.4.install +++ b/debian/mariadb-server-core-10.4.install @@ -9,6 +9,8 @@ usr/share/man/man1/mysql_install_db.1 usr/share/man/man1/mysql_upgrade.1 usr/share/man/man8/mariadbd.8 usr/share/man/man8/mysqld.8 +usr/share/mysql/bulgarian +usr/share/mysql/chinese usr/share/mysql/charsets usr/share/mysql/czech usr/share/mysql/danish diff --git a/sql/share/CMakeLists.txt b/sql/share/CMakeLists.txt index 55f39e5e22b..ddb813057ab 100644 --- a/sql/share/CMakeLists.txt +++ b/sql/share/CMakeLists.txt @@ -15,30 +15,32 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA SET (dirs +bulgarian +chinese +czech danish -german -slovak dutch -greek -norwegian -spanish english +estonian +french +german +greek +hindi hungarian -norwegian-ny -swedish italian -polish -ukrainian japanese +korean +norwegian-ny +norwegian +polish portuguese romanian -estonian -korean russian -czech -french serbian -hindi +slovak +spanish +swedish +ukrainian ) SET(files diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 4fe847fd4bb..ebebb4824cd 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1,4 +1,4 @@ -languages chinese=chi gbk, czech=cze latin2, danish=dan latin1, dutch=nla latin1, english=eng latin1, estonian=est latin7, french=fre latin1, german=ger latin1, greek=greek greek, hungarian=hun latin2, italian=ita latin1, japanese=jpn ujis, korean=kor euckr, norwegian-ny=norwegian-ny latin1, norwegian=nor latin1, polish=pol latin2, portuguese=por latin1, romanian=rum latin2, russian=rus koi8r, serbian=serbian cp1250, slovak=slo latin2, spanish=spa latin1, swedish=swe latin1, ukrainian=ukr koi8u, bulgarian=bgn cp1251, hindi=hindi utf8; +languages bulgarian=bgn cp1251, chinese=chi gbk, czech=cze latin2, danish=dan latin1, dutch=nla latin1, english=eng latin1, estonian=est latin7, french=fre latin1, german=ger latin1, greek=greek greek, hindi=hindi utf8, hungarian=hun latin2, italian=ita latin1, japanese=jpn ujis, korean=kor euckr, norwegian-ny=norwegian-ny latin1, norwegian=nor latin1, polish=pol latin2, portuguese=por latin1, romanian=rum latin2, russian=rus koi8r, serbian=serbian cp1250, slovak=slo latin2, spanish=spa latin1, swedish=swe latin1, ukrainian=ukr koi8u; default-language eng From 25ccf8f6dcfa23ba07a46efe5e85787689571b17 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 25 Apr 2022 15:47:33 +0200 Subject: [PATCH 35/94] New CC version --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index f6c3d9fd2af..f33017c19a5 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit f6c3d9fd2af5d17db64cc996574aa312efd70fcf +Subproject commit f33017c19a5b02394de5d0816513d2e2c9d1767c From 9b2d36660bbb4f93c6b9e0761c91d57d47f59196 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Thu, 27 Jan 2022 01:03:52 +0530 Subject: [PATCH 36/94] MDEV-20207: Assertion ! is_set() failed in Diagnostics_area::set_eof_status upon HANDLER READ Analysis: The error state is not stored while checking condition and key name. Fix: Return true while checking condition and key name if error is reported because geometry object can't be created from the data in the index value for HANDLER READ. --- mysql-test/suite/handler/aria.result | 16 ++++++++++++++++ mysql-test/suite/handler/aria.test | 20 ++++++++++++++++++++ mysql-test/suite/handler/innodb.result | 16 ++++++++++++++++ mysql-test/suite/handler/innodb.test | 20 ++++++++++++++++++++ mysql-test/suite/handler/interface.result | 16 ++++++++++++++++ mysql-test/suite/handler/interface.test | 20 ++++++++++++++++++++ mysql-test/suite/handler/myisam.result | 14 ++++++++++++++ mysql-test/suite/handler/myisam.test | 20 ++++++++++++++++++++ sql/sql_handler.cc | 4 +++- 9 files changed, 145 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/handler/aria.result b/mysql-test/suite/handler/aria.result index 6b02ac9b085..433a8a7008e 100644 --- a/mysql-test/suite/handler/aria.result +++ b/mysql-test/suite/handler/aria.result @@ -1845,3 +1845,19 @@ a b HANDLER t1 CLOSE; DROP TABLE t1; End of 5.1 tests +# +# 10.2 Test +# +# MDEV-20207: Assertion `! is_set()' failed in +# Diagnostics_area::set_eof_status upon HANDLER READ +# +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 'test.t1' +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; +HANDLER h READ a = (0); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +HANDLER h CLOSE; +DROP TABLE t1; +# End of 10.2 Test diff --git a/mysql-test/suite/handler/aria.test b/mysql-test/suite/handler/aria.test index 1913d2b791c..912a9e89721 100644 --- a/mysql-test/suite/handler/aria.test +++ b/mysql-test/suite/handler/aria.test @@ -80,3 +80,23 @@ HANDLER t1 CLOSE; DROP TABLE t1; --echo End of 5.1 tests + +--echo # +--echo # 10.2 Test +--echo # +--echo # MDEV-20207: Assertion `! is_set()' failed in +--echo # Diagnostics_area::set_eof_status upon HANDLER READ +--echo # + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; + +--error ER_CANT_CREATE_GEOMETRY_OBJECT +HANDLER h READ a = (0); + +HANDLER h CLOSE; +DROP TABLE t1; + +--echo # End of 10.2 Test diff --git a/mysql-test/suite/handler/innodb.result b/mysql-test/suite/handler/innodb.result index 80e8ed679a9..7f9995c9e84 100644 --- a/mysql-test/suite/handler/innodb.result +++ b/mysql-test/suite/handler/innodb.result @@ -1748,3 +1748,19 @@ HANDLER t1 READ `PRIMARY` PREV; f1 f2 3 3 DROP TABLE t1; +# +# 10.2 Test +# +# MDEV-20207: Assertion `! is_set()' failed in +# Diagnostics_area::set_eof_status upon HANDLER READ +# +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 'test.t1' +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; +HANDLER h READ a = (0); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +HANDLER h CLOSE; +DROP TABLE t1; +# End of 10.2 Test diff --git a/mysql-test/suite/handler/innodb.test b/mysql-test/suite/handler/innodb.test index d752da7dc31..74b0a650c25 100644 --- a/mysql-test/suite/handler/innodb.test +++ b/mysql-test/suite/handler/innodb.test @@ -31,3 +31,23 @@ HANDLER t1 OPEN; HANDLER t1 READ FIRST WHERE f2 <= 1; HANDLER t1 READ `PRIMARY` PREV; DROP TABLE t1; + +--echo # +--echo # 10.2 Test +--echo # +--echo # MDEV-20207: Assertion `! is_set()' failed in +--echo # Diagnostics_area::set_eof_status upon HANDLER READ +--echo # + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; + +--error ER_CANT_CREATE_GEOMETRY_OBJECT +HANDLER h READ a = (0); + +HANDLER h CLOSE; +DROP TABLE t1; + +--echo # End of 10.2 Test diff --git a/mysql-test/suite/handler/interface.result b/mysql-test/suite/handler/interface.result index a4ac32c16b4..1b0d08635f9 100644 --- a/mysql-test/suite/handler/interface.result +++ b/mysql-test/suite/handler/interface.result @@ -312,3 +312,19 @@ Note 1050 Table 'v' already exists handler v read next; ERROR 42S02: Unknown table 'v' in HANDLER drop view v; +# +# 10.2 Test +# +# MDEV-20207: Assertion `! is_set()' failed in +# Diagnostics_area::set_eof_status upon HANDLER READ +# +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 'test.t1' +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; +HANDLER h READ a = (0); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +HANDLER h CLOSE; +DROP TABLE t1; +# End of 10.2 Test diff --git a/mysql-test/suite/handler/interface.test b/mysql-test/suite/handler/interface.test index 2f576c9b291..8a90ffc0cf7 100644 --- a/mysql-test/suite/handler/interface.test +++ b/mysql-test/suite/handler/interface.test @@ -354,3 +354,23 @@ execute stmt; --error ER_UNKNOWN_TABLE handler v read next; drop view v; + +--echo # +--echo # 10.2 Test +--echo # +--echo # MDEV-20207: Assertion `! is_set()' failed in +--echo # Diagnostics_area::set_eof_status upon HANDLER READ +--echo # + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; + +--error ER_CANT_CREATE_GEOMETRY_OBJECT +HANDLER h READ a = (0); + +HANDLER h CLOSE; +DROP TABLE t1; + +--echo # End of 10.2 Test diff --git a/mysql-test/suite/handler/myisam.result b/mysql-test/suite/handler/myisam.result index 90e1767a1f3..c444027d062 100644 --- a/mysql-test/suite/handler/myisam.result +++ b/mysql-test/suite/handler/myisam.result @@ -1931,3 +1931,17 @@ test.t1 preload_keys status OK HANDLER t1 READ FIRST; ERROR 42S02: Unknown table 't1' in HANDLER End of 5.1 tests +# +# 10.2 Test +# +# MDEV-20207: Assertion `! is_set()' failed in +# Diagnostics_area::set_eof_status upon HANDLER READ +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; +HANDLER h READ a = (0); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +HANDLER h CLOSE; +DROP TABLE t1; +# End of 10.2 Test diff --git a/mysql-test/suite/handler/myisam.test b/mysql-test/suite/handler/myisam.test index a2d87630aef..2fce8548322 100644 --- a/mysql-test/suite/handler/myisam.test +++ b/mysql-test/suite/handler/myisam.test @@ -169,3 +169,23 @@ HANDLER t1 READ FIRST; --echo End of 5.1 tests + +--echo # +--echo # 10.2 Test +--echo # +--echo # MDEV-20207: Assertion `! is_set()' failed in +--echo # Diagnostics_area::set_eof_status upon HANDLER READ +--echo # + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 (a POINT, KEY(a)); +HANDLER t1 OPEN h; + +--error ER_CANT_CREATE_GEOMETRY_OBJECT +HANDLER h READ a = (0); + +HANDLER h CLOSE; +DROP TABLE t1; + +--echo # End of 10.2 Test diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index ec3756eceba..132556f57b8 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -613,8 +613,10 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler, if (!in_prepare) { MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set); - (void) item->save_in_field(key_part->field, 1); + int res= item->save_in_field(key_part->field, 1); dbug_tmp_restore_column_map(&table->write_set, old_map); + if (res) + return 1; } key_len+= key_part->store_length; keypart_map= (keypart_map << 1) | 1; From d45841b9be6fe069383cc05405f747ae36d08362 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Tue, 26 Apr 2022 12:58:48 +0530 Subject: [PATCH 37/94] MDEV-26695: Number of an invalid row is not calculated for table value constructor Analysis: counter does not increment while sending rows for table value constructor and so row_number assumes the default value (0 in this case). Fix: Increment the counter to avoid counter using default value. --- mysql-test/main/get_diagnostics.result | 10 ++++++++++ mysql-test/main/get_diagnostics.test | 9 +++++++++ sql/sql_tvc.cc | 2 ++ 3 files changed, 21 insertions(+) diff --git a/mysql-test/main/get_diagnostics.result b/mysql-test/main/get_diagnostics.result index 6944103c805..41511d8a521 100644 --- a/mysql-test/main/get_diagnostics.result +++ b/mysql-test/main/get_diagnostics.result @@ -790,3 +790,13 @@ GET DIAGNOSTICS @var1 = NUMBER; SHOW STATUS LIKE 'Com%get_diagnostics'; Variable_name Value Com_get_diagnostics 1 +# +# MDEV-26695: Number of an invalid row is not calculated for table value constructor +# +CREATE TABLE t1 (a CHAR(1)) VALUES ('a'),('b'),('foo'); +Warnings: +Warning 1406 Data too long for column 'a' at row 3 +CREATE TABLE t2 (a char(1)) VALUES ('a'),('b') UNION VALUES ('foo'); +Warnings: +Warning 1406 Data too long for column 'a' at row 3 +DROP TABLE t1, t2; diff --git a/mysql-test/main/get_diagnostics.test b/mysql-test/main/get_diagnostics.test index 1553eb500b7..78ed3ea811b 100644 --- a/mysql-test/main/get_diagnostics.test +++ b/mysql-test/main/get_diagnostics.test @@ -851,3 +851,12 @@ FLUSH STATUS; SHOW STATUS LIKE 'Com%get_diagnostics'; GET DIAGNOSTICS @var1 = NUMBER; SHOW STATUS LIKE 'Com%get_diagnostics'; + +--echo # +--echo # MDEV-26695: Number of an invalid row is not calculated for table value constructor +--echo # + +CREATE TABLE t1 (a CHAR(1)) VALUES ('a'),('b'),('foo'); +CREATE TABLE t2 (a char(1)) VALUES ('a'),('b') UNION VALUES ('foo'); + +DROP TABLE t1, t2; diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index 9a99224b26e..72d53b2307c 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -406,9 +406,11 @@ bool table_value_constr::exec(SELECT_LEX *sl) while ((elem= li++)) { + THD *cur_thd= sl->parent_lex->thd; if (send_records >= sl->master_unit()->select_limit_cnt) break; int rc= result->send_data(*elem); + cur_thd->get_stmt_da()->inc_current_row_for_warning(); if (!rc) send_records++; else if (rc > 0) From e6bbc83d5e3fc7334c13a5eb883c78b1078512f2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 25 Apr 2022 18:13:13 +0200 Subject: [PATCH 38/94] MDEV-26212 PAM authentication fails with ENOMEM use posix_spawn(), not fork() - it's better for systems that don't overcommit memory --- plugin/auth_pam/auth_pam.c | 77 ++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 45 deletions(-) diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index 35272c6b7cd..3f3a49bf55d 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "auth_pam_tool.h" #include @@ -51,65 +52,51 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) unsigned char field, *pkt; unsigned int n_sleep= 0; useconds_t sleep_time= 100; + posix_spawn_file_actions_t file_actions; + char toolpath[FN_REFLEN]; + size_t plugin_dir_len= strlen(opt_plugin_dir); + char *const argv[2]= {toolpath, 0}; + int res; PAM_DEBUG((stderr, "PAM: opening pipes.\n")); if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) { - /* Error creating pipes. */ + my_printf_error(ENOEXEC, "pam: cannot create pipes (errno: %M)", + ME_ERROR_LOG_ONLY, errno); return CR_ERROR; } - PAM_DEBUG((stderr, "PAM: forking.\n")); - if ((proc_id= fork()) < 0) + + if (plugin_dir_len + tool_name_len + 2 > sizeof(toolpath)) { - /* Error forking. */ - close(p_to_c[0]); - close(c_to_p[1]); - goto error_ret; + my_printf_error(ENOEXEC, "pam: too long path to /%s", + ME_ERROR_LOG_ONLY, tool_name); + return CR_ERROR; } - if (proc_id == 0) - { - /* The 'sandbox' process started. */ - char toolpath[FN_REFLEN]; - size_t plugin_dir_len= strlen(opt_plugin_dir); + memcpy(toolpath, opt_plugin_dir, plugin_dir_len); + if (plugin_dir_len && toolpath[plugin_dir_len-1] != FN_LIBCHAR) + toolpath[plugin_dir_len++]= FN_LIBCHAR; + memcpy(toolpath+plugin_dir_len, tool_name, tool_name_len+1); - PAM_DEBUG((stderr, "PAM: Child process prepares pipes.\n")); - - if (close(p_to_c[1]) < 0 || - close(c_to_p[0]) < 0 || - dup2(p_to_c[0], 0) < 0 || /* Parent's pipe to STDIN. */ - dup2(c_to_p[1], 1) < 0) /* Sandbox's pipe to STDOUT. */ - { - exit(-1); - } - - PAM_DEBUG((stderr, "PAM: check tool directory: %s, %s.\n", - opt_plugin_dir, tool_name)); - if (plugin_dir_len + tool_name_len + 2 > sizeof(toolpath)) - { - /* Tool path too long. */ - exit(-1); - } - - memcpy(toolpath, opt_plugin_dir, plugin_dir_len); - if (plugin_dir_len && toolpath[plugin_dir_len-1] != FN_LIBCHAR) - toolpath[plugin_dir_len++]= FN_LIBCHAR; - memcpy(toolpath+plugin_dir_len, tool_name, tool_name_len+1); - - PAM_DEBUG((stderr, "PAM: execute pam sandbox [%s].\n", toolpath)); - (void) execl(toolpath, toolpath, NULL); - PAM_DEBUG((stderr, "PAM: exec() failed.\n")); - my_printf_error(1, "PAM: Cannot execute %s (errno: %M)", ME_ERROR_LOG_ONLY, - toolpath, errno); - exit(-1); - } + PAM_DEBUG((stderr, "PAM: forking %s\n", toolpath)); + res= posix_spawn_file_actions_init(&file_actions) || + posix_spawn_file_actions_addclose(&file_actions, p_to_c[1]) || + posix_spawn_file_actions_addclose(&file_actions, c_to_p[0]) || + posix_spawn_file_actions_adddup2(&file_actions, p_to_c[0], 0) || + posix_spawn_file_actions_adddup2(&file_actions, c_to_p[1], 1) || + posix_spawn(&proc_id, toolpath, &file_actions, NULL, argv, NULL); /* Parent process continues. */ + posix_spawn_file_actions_destroy(&file_actions); + close(p_to_c[0]); + close(c_to_p[1]); - PAM_DEBUG((stderr, "PAM: parent continues.\n")); - if (close(p_to_c[0]) < 0 || - close(c_to_p[1]) < 0) + if (res) + { + my_printf_error(ENOEXEC, "pam: cannot exec %s (errno: %M)", + ME_ERROR_LOG_ONLY, toolpath, errno); goto error_ret; + } /* no user name yet ? read the client handshake packet with the user name */ if (info->user_name == 0) From 5100b20b15edd93200f34a79d25f1b14e46a677e Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Fri, 22 Apr 2022 20:26:14 +0300 Subject: [PATCH 39/94] MDEV-26047: MariaDB server crash at Item_subselect::init_expr_cache_tracker The cause of crash: remove_redundant_subquery_clauses() removes redundant item expressions. The primary goal of this is to remove the subquery items. The removal process unlinks the subquery from SELECT_LEX tree, but does not remove it from SELECT_LEX:::ref_pointer_array or from JOIN::all_fields. Then, setup_subquery_caches() tries to wrap the subquery item in an expression cache, which fails, the first reason for failure being that the item doesn't have a query plan. Solution: do not wrap eliminated items with expression cache. (also added an assert to check that we do not attempt to execute them). This may look like an incomplete fix: why don't we remove any mention of eliminated item everywhere? The difficulties here are: * items can be "un-removed" (see set_fake_select_as_master_processor) * it's difficult to remove an element from ref_pointer_array: Item_ref objects refer to elements of that array, so one can't shift elements in it. Replacing eliminated subselect with a dummy Item doesn't look like a good idea, either. --- mysql-test/r/subselect_innodb.result | 32 ++++++++++++++++++++++++++++ mysql-test/t/subselect_innodb.test | 28 ++++++++++++++++++++++++ sql/item_subselect.cc | 11 ++++++++++ 3 files changed, 71 insertions(+) diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index 4eaea099451..4796245f8e3 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -629,3 +629,35 @@ a b 2019-03-10 02:55:05 2019-03-10 02:55:05 DROP TABLE t1,t2; set character_set_connection=@save_character_set_connection; +# +# MDEV-26047: MariaDB server crash at Item_subselect::init_expr_cache_tracker +# +CREATE TABLE t1 (a int) engine=innodb; +SELECT 1 IN ( +SELECT NULL +FROM t1 +WHERE +a IS NOT NULL +GROUP BY +(SELECT NULL from dual WHERE a = 1) +); +1 IN ( +SELECT NULL +FROM t1 +WHERE +a IS NOT NULL +GROUP BY +(SELECT NULL from dual WHERE a = 1) +) +0 +drop table t1; +# Testcase from MDEV-26164 +create table t1(a int); +# Disable the warning as it includes current time and changes for every test run. +select 1 from t1 where not exists +( +select 1 from t1 where binary current_time() +group by (select a),(select 1) +); +1 +drop table t1; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index 2c117fe00d6..f42ac514d53 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -627,3 +627,31 @@ SELECT * FROM t1 WHERE (SELECT 1,CONCAT(a) FROM t1) = (SELECT 1,CONCAT(a) FROM t DROP TABLE t1,t2; set character_set_connection=@save_character_set_connection; + +--echo # +--echo # MDEV-26047: MariaDB server crash at Item_subselect::init_expr_cache_tracker +--echo # +CREATE TABLE t1 (a int) engine=innodb; + +SELECT 1 IN ( + SELECT NULL + FROM t1 + WHERE + a IS NOT NULL + GROUP BY + (SELECT NULL from dual WHERE a = 1) +); +drop table t1; + +--echo # Testcase from MDEV-26164 +create table t1(a int); +--echo # Disable the warning as it includes current time and changes for every test run. +--disable_warnings +select 1 from t1 where not exists +( + select 1 from t1 where binary current_time() + group by (select a),(select 1) +); +--enable_warnings +drop table t1; + diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7033d38c07b..de9b5dc8438 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -752,6 +752,7 @@ bool Item_subselect::exec() DBUG_ENTER("Item_subselect::exec"); DBUG_ASSERT(fixed); + DBUG_ASSERT(!eliminated); /* Do not execute subselect in case of a fatal error @@ -1313,6 +1314,16 @@ Item* Item_singlerow_subselect::expr_cache_insert_transformer(THD *tmp_thd, DBUG_ASSERT(thd == tmp_thd); + /* + Do not create subquery cache if the subquery was eliminated. + The optimizer may eliminate subquery items (see + eliminate_subselect_processor). However it does not update + all query's data structures, so the eliminated item may be + still reachable. + */ + if (eliminated) + DBUG_RETURN(this); + if (expr_cache) DBUG_RETURN(expr_cache); From 945245aea4baf5399470ec0cff5d5d51c36a95d6 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 26 Apr 2022 17:03:32 +0300 Subject: [PATCH 40/94] MDEV-27697. Two affected tests fixed. A result file is updated in one case and former error simulation got refined. --- mysql-test/suite/binlog_encryption/rpl_parallel.result | 1 + mysql-test/suite/rpl/r/rpl_parallel_temptable.result | 5 +++++ mysql-test/suite/rpl/t/rpl_parallel_temptable.test | 8 ++++++++ sql/slave.cc | 6 ++++-- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel.result b/mysql-test/suite/binlog_encryption/rpl_parallel.result index 12e5455c6c1..79efad1a27a 100644 --- a/mysql-test/suite/binlog_encryption/rpl_parallel.result +++ b/mysql-test/suite/binlog_encryption/rpl_parallel.result @@ -1379,6 +1379,7 @@ include/stop_slave.inc SET GLOBAL slave_parallel_threads=1; SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000"; +CALL mtr.add_suppression("Unexpected break of being relay-logged GTID"); connection server_1; INSERT INTO t2 VALUES (101); INSERT INTO t2 VALUES (102); diff --git a/mysql-test/suite/rpl/r/rpl_parallel_temptable.result b/mysql-test/suite/rpl/r/rpl_parallel_temptable.result index 52efed22541..1a1c12f836d 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_temptable.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_temptable.result @@ -132,8 +132,13 @@ connection server_1; INSERT INTO t1 VALUES (0, 1); include/save_master_gtid.inc connection server_2; +set @@sql_log_bin=0; +call mtr.add_suppression("Unexpected break of being relay-logged GTID 1-1-32 event group by the current GTID event 0-1-4"); +set @@sql_log_bin=1; +set @@global.debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000"; include/start_slave.inc include/sync_with_master_gtid.inc +set @@global.debug_dbug=""; SELECT * FROM t1 ORDER BY a; a b 0 1 diff --git a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test index 04165ee4752..d444793a99d 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test @@ -201,9 +201,17 @@ INSERT INTO t1 VALUES (0, 1); # execution of format_description event will not wait infinitely # for a commit of the incomplete group that never happens. +# Apart from the suppression, MDEV-27697 refinement to the original test needs +# an allowance to one time accept malformed event group. +set @@sql_log_bin=0; +call mtr.add_suppression("Unexpected break of being relay-logged GTID 1-1-32 event group by the current GTID event 0-1-4"); +set @@sql_log_bin=1; +set @@global.debug_dbug="+d,slave_discard_xid_for_gtid_0_x_1000"; + --source include/start_slave.inc #--sync_with_master --source include/sync_with_master_gtid.inc +set @@global.debug_dbug=""; SELECT * FROM t1 ORDER BY a; SHOW STATUS LIKE 'Slave_open_temp_tables'; diff --git a/sql/slave.cc b/sql/slave.cc index 31e50753c9e..0d50e8b0c61 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -6223,8 +6223,10 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) DBUG_EXECUTE_IF("slave_discard_xid_for_gtid_0_x_1000", { /* Inject an event group that is missing its XID commit event. */ - if (mi->last_queued_gtid.domain_id == 0 && - mi->last_queued_gtid.seq_no == 1000) + if ((mi->last_queued_gtid.domain_id == 0 && + mi->last_queued_gtid.seq_no == 1000) || + (mi->last_queued_gtid.domain_id == 1 && + mi->last_queued_gtid.seq_no == 32)) { sql_print_warning( "Unexpected break of being relay-logged GTID %u-%u-%llu " From eca207c46293bc72dd8d0d5622153fab4d3fccf1 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 22 Apr 2022 01:32:55 +0400 Subject: [PATCH 41/94] MDEV-25317 Assertion `scale <= precision' failed in decimal_bin_size And Assertion `scale >= 0 && precision > 0 && scale <= precision' failed in decimal_bin_size_inline/decimal_bin_size. Precision should be kept below DECIMAL_MAX_SCALE for computations. It can be bigger in Item_decimal. I'd fix this too but it changes the existing behaviour so problemmatic to ix. --- mysql-test/r/func_time.result | 6 ++++++ mysql-test/r/type_newdecimal.result | 24 ++++++++++++++++++++++++ mysql-test/t/func_time.test | 4 ++++ mysql-test/t/type_newdecimal.test | 19 +++++++++++++++++++ sql/field.cc | 28 ++++++++++++++++------------ sql/field.h | 2 ++ sql/item_func.cc | 6 ++++-- sql/item_sum.cc | 6 ++++-- sql/sql_type.cc | 1 - 9 files changed, 79 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index a82cf3c19c2..563212cb756 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -989,6 +989,12 @@ ADDTIME('916:40:00', '416:40:00') Warnings: Warning 1292 Truncated incorrect time value: '916:40:00' Warning 1292 Truncated incorrect time value: '1255:39:59.999999' +SELECT ADDTIME(20010101,1e0), ADDTIME(20010101,1.1e0); +ADDTIME(20010101,1e0) ADDTIME(20010101,1.1e0) +2001-01-01 00:00:01 2001-01-01 00:00:01.100000 +SELECT ADDTIME(ADDTIME(20010101,1e0), 0); +ADDTIME(ADDTIME(20010101,1e0), 0) +2001-01-01 00:00:01 SELECT SUBTIME('916:40:00', '416:40:00'); SUBTIME('916:40:00', '416:40:00') 422:19:59.999999 diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 0fbf64a4b18..0df2b59d832 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -2456,5 +2456,29 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; # +# MDEV-25317 Assertion `scale <= precision' failed in +# decimal_bin_size And Assertion `scale >= 0 && precision > 0 && scale <= precision' +# failed in decimal_bin_size_inline/decimal_bin_size. +# +SELECT AVG(DISTINCT 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001); +AVG(DISTINCT 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +0.00000000000000000000000000000000000000 +CREATE TABLE t1 AS SELECT NULL AS v1; +SELECT 1 FROM t1 GROUP BY v1 ORDER BY AVG ( from_unixtime ( '' ) ) ; +1 +1 +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '' +DROP TABLE t1; +SELECT SUM(DISTINCT 0.000000000000000000000000000000000000001); +SUM(DISTINCT 0.000000000000000000000000000000000000001) +0.00000000000000000000000000000000000000 +CREATE TABLE t1 AS SELECT 1.000000000000000000000000000000000 AS a; +ALTER TABLE t1 ADD COLUMN b INT; +SELECT ROUND (a,b) AS c FROM t1 ORDER BY c; +c +NULL +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 22729b4300b..7f35e658d1b 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -513,6 +513,10 @@ SELECT TIME_TO_SEC('916:40:00'); SELECT ADDTIME('500:00:00', '416:40:00'); SELECT ADDTIME('916:40:00', '416:40:00'); +# check if ADDTIME() handles NOT_FIXED_DEC correctly +SELECT ADDTIME(20010101,1e0), ADDTIME(20010101,1.1e0); +SELECT ADDTIME(ADDTIME(20010101,1e0), 0); + # check if SUBTIME() handles out-of-range values correctly SELECT SUBTIME('916:40:00', '416:40:00'); SELECT SUBTIME('-916:40:00', '416:40:00'); diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index e5d903e95cd..a5cb15e1a2c 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1894,6 +1894,25 @@ show create table t1; drop table t1; +--echo # +--echo # MDEV-25317 Assertion `scale <= precision' failed in +--echo # decimal_bin_size And Assertion `scale >= 0 && precision > 0 && scale <= precision' +--echo # failed in decimal_bin_size_inline/decimal_bin_size. +--echo # + +SELECT AVG(DISTINCT 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001); + +CREATE TABLE t1 AS SELECT NULL AS v1; +SELECT 1 FROM t1 GROUP BY v1 ORDER BY AVG ( from_unixtime ( '' ) ) ; +DROP TABLE t1; + +SELECT SUM(DISTINCT 0.000000000000000000000000000000000000001); + +CREATE TABLE t1 AS SELECT 1.000000000000000000000000000000000 AS a; +ALTER TABLE t1 ADD COLUMN b INT; +SELECT ROUND (a,b) AS c FROM t1 ORDER BY c; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/field.cc b/sql/field.cc index 74317a4d70b..07212a53b45 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3103,6 +3103,15 @@ Field *Field_decimal::make_new_field(MEM_ROOT *root, TABLE *new_table, } +void Field_new_decimal::set_and_validate_prec(uint32 len_arg, + uint8 dec_arg, bool unsigned_arg) +{ + precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg); + set_if_smaller(precision, DECIMAL_MAX_PRECISION); + bin_size= my_decimal_get_binary_size(precision, dec); +} + + /**************************************************************************** ** Field_new_decimal ****************************************************************************/ @@ -3115,13 +3124,10 @@ Field_new_decimal::Field_new_decimal(uchar *ptr_arg, uint8 dec_arg,bool zero_arg, bool unsigned_arg) :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg) + unireg_check_arg, field_name_arg, + MY_MIN(dec_arg, DECIMAL_MAX_SCALE), zero_arg, unsigned_arg) { - precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg); - set_if_smaller(precision, DECIMAL_MAX_PRECISION); - DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) && - (dec <= DECIMAL_MAX_SCALE)); - bin_size= my_decimal_get_binary_size(precision, dec); + set_and_validate_prec(len_arg, dec_arg, unsigned_arg); } @@ -3132,13 +3138,11 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, bool unsigned_arg) :Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0, - NONE, name, dec_arg, 0, unsigned_arg) + NONE, name, + MY_MIN(dec_arg, DECIMAL_MAX_SCALE), 0, unsigned_arg) { - precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg); - set_if_smaller(precision, DECIMAL_MAX_PRECISION); - DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) && - (dec <= DECIMAL_MAX_SCALE)); - bin_size= my_decimal_get_binary_size(precision, dec); + DBUG_ASSERT(dec <= DECIMAL_MAX_SCALE); + set_and_validate_prec(len_arg, dec_arg, unsigned_arg); } diff --git a/sql/field.h b/sql/field.h index 78b6dcb516b..ad01b2ff642 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1913,6 +1913,8 @@ public: class Field_new_decimal :public Field_num { private: int do_save_field_metadata(uchar *first_byte); + void set_and_validate_prec(uint32 len_arg, + uint8 dec_arg, bool unsigned_arg); public: /* The maximum number of decimal digits can be stored */ uint precision; diff --git a/sql/item_func.cc b/sql/item_func.cc index 7a7eaf9dc23..4e28e8e9528 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2453,14 +2453,16 @@ bool Item_func_round::fix_length_and_dec() if (!args[1]->const_item()) { decimals= args[0]->decimals; - max_length= float_length(decimals); if (args[0]->result_type() == DECIMAL_RESULT) { - max_length++; + max_length= args[0]->max_length; set_handler_by_result_type(DECIMAL_RESULT); } else + { + max_length= float_length(decimals); set_handler_by_result_type(REAL_RESULT); + } return FALSE; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index dd65f04a652..77224d5321d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1346,6 +1346,8 @@ bool Item_sum_sum::fix_length_and_dec() { /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */ int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS; + decimals= MY_MIN(decimals, DECIMAL_MAX_SCALE); + precision= MY_MIN(precision, DECIMAL_MAX_PRECISION); max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, unsigned_flag); @@ -1673,12 +1675,12 @@ bool Item_sum_avg::fix_length_and_dec() if (Item_sum_avg::result_type() == DECIMAL_RESULT) { int precision= args[0]->decimal_precision() + prec_increment; - decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE); + decimals= MY_MIN(args[0]->decimal_scale() + prec_increment, DECIMAL_MAX_SCALE); max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, unsigned_flag); f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION); - f_scale= args[0]->decimals; + f_scale= args[0]->decimal_scale(); dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale); } else diff --git a/sql/sql_type.cc b/sql/sql_type.cc index c1f192b0622..b1e141d0eeb 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -258,7 +258,6 @@ Type_handler_decimal_result::make_num_distinct_aggregator_field( const Item *item) const { - DBUG_ASSERT(item->decimals <= DECIMAL_MAX_SCALE); return new (mem_root) Field_new_decimal(NULL, item->max_length, (uchar *) (item->maybe_null ? "" : 0), From 388032e99057449219d4a943b4407e36c42ec4af Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 26 Apr 2022 19:46:44 +0300 Subject: [PATCH 42/94] MDEV-27697. Removed a false assert. --- libmariadb | 2 +- sql/slave.cc | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libmariadb b/libmariadb index f33017c19a5..f6c3d9fd2af 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit f33017c19a5b02394de5d0816513d2e2c9d1767c +Subproject commit f6c3d9fd2af5d17db64cc996574aa312efd70fcf diff --git a/sql/slave.cc b/sql/slave.cc index 0d50e8b0c61..80b1137d90e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -6594,8 +6594,6 @@ dbug_gtid_accept: Query_log_event::peek_is_commit_rollback(buf, event_len, checksum_alg)))))) { - DBUG_ASSERT(mi->events_queued_since_last_gtid > 1); - if (unlikely(gtid_skip_enqueue)) { error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE; From 44e7c312bad9d00498f6f04afe165f5d8570765d Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 25 Apr 2022 15:47:33 +0200 Subject: [PATCH 43/94] New C/C version *again* after 388032e9905 has reverted 25ccf8f6dcf by mistake --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index f6c3d9fd2af..f33017c19a5 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit f6c3d9fd2af5d17db64cc996574aa312efd70fcf +Subproject commit f33017c19a5b02394de5d0816513d2e2c9d1767c From 39990135e57e7377fd2f9a156973a59eb07bc739 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 26 Apr 2022 14:18:32 +0200 Subject: [PATCH 44/94] MDEV-28020 CHECKSUM TABLE calculates different checksums Two bugs here: 1. CHECKSUM TABLE asserted that all fields in the table are arranged sequentially in the record, but virtual columns are always at the end, violating this assertion 2. virtual columns were not calculated for CHECKSUM, so CHECKSUM was using, essentially, garbage left from the previous statement. (that's why the test must use INSERT IGNORE to have this "previous statement" mark vcols not null) Fix: don't include virtual columns into the table CHECKSUM. Indeed, they cannot be included as the engine does not see virtual columns, so in-engine checksum cannot include them, meaning in-server checksum should not either --- mysql-test/r/row-checksum-old.result | 45 +++++++++++++++++++++++++++- mysql-test/r/row-checksum.result | 45 +++++++++++++++++++++++++++- mysql-test/t/row-checksum.test | 35 ++++++++++++++++++---- sql/sql_table.cc | 2 ++ 4 files changed, 119 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/row-checksum-old.result b/mysql-test/r/row-checksum-old.result index d374013f61c..7caed4fc7dc 100644 --- a/mysql-test/r/row-checksum-old.result +++ b/mysql-test/r/row-checksum-old.result @@ -1,4 +1,3 @@ -drop table if exists t1; create table t1 (a int null, v varchar(100)) engine=myisam checksum=0; insert into t1 values(null, null), (1, "hello"); checksum table t1; @@ -98,4 +97,48 @@ CHECKSUM TABLE t1 EXTENDED; Table Checksum test.t1 2326430205 drop table t1; +# # End of 5.5 tests +# +# +# MDEV-28020 CHECKSUM TABLE calculates different checksums +# +create table t1 ( a int, b int as (a) virtual, c text) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +Warnings: +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +checksum table t1 extended; +Table Checksum +test.t1 4101438232 +checksum table t1; +Table Checksum +test.t1 4101438232 +drop table t1; +create table t1 ( a int, b int as (a) virtual, c text, key(b)) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +Warnings: +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +checksum table t1 extended; +Table Checksum +test.t1 4101438232 +checksum table t1; +Table Checksum +test.t1 4101438232 +drop table t1; +create table t1 ( a int, b int as (a) stored, c text) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +Warnings: +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +checksum table t1 extended; +Table Checksum +test.t1 2897795735 +checksum table t1; +Table Checksum +test.t1 2897795735 +drop table t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/r/row-checksum.result b/mysql-test/r/row-checksum.result index 4625e09c060..c80ca4eed9a 100644 --- a/mysql-test/r/row-checksum.result +++ b/mysql-test/r/row-checksum.result @@ -1,4 +1,3 @@ -drop table if exists t1; create table t1 (a int null, v varchar(100)) engine=myisam checksum=0; insert into t1 values(null, null), (1, "hello"); checksum table t1; @@ -98,4 +97,48 @@ CHECKSUM TABLE t1 EXTENDED; Table Checksum test.t1 2326430205 drop table t1; +# # End of 5.5 tests +# +# +# MDEV-28020 CHECKSUM TABLE calculates different checksums +# +create table t1 ( a int, b int as (a) virtual, c text) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +Warnings: +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +checksum table t1 extended; +Table Checksum +test.t1 4101438232 +checksum table t1; +Table Checksum +test.t1 4101438232 +drop table t1; +create table t1 ( a int, b int as (a) virtual, c text, key(b)) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +Warnings: +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +checksum table t1 extended; +Table Checksum +test.t1 4101438232 +checksum table t1; +Table Checksum +test.t1 4101438232 +drop table t1; +create table t1 ( a int, b int as (a) stored, c text) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +Warnings: +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'b' in table 't1' has been ignored +checksum table t1 extended; +Table Checksum +test.t1 2897795735 +checksum table t1; +Table Checksum +test.t1 2897795735 +drop table t1; +# +# End of 10.2 tests +# diff --git a/mysql-test/t/row-checksum.test b/mysql-test/t/row-checksum.test index 5acfda45f75..3b510abba84 100644 --- a/mysql-test/t/row-checksum.test +++ b/mysql-test/t/row-checksum.test @@ -2,12 +2,8 @@ # Test checksum # --- source include/have_innodb.inc --- source include/have_maria.inc - ---disable_warnings -drop table if exists t1; ---enable_warnings +--source include/have_innodb.inc +--source include/have_maria.inc create table t1 (a int null, v varchar(100)) engine=myisam checksum=0; insert into t1 values(null, null), (1, "hello"); @@ -76,4 +72,31 @@ CHECKSUM TABLE t1 EXTENDED; drop table t1; +--echo # --echo # End of 5.5 tests +--echo # + +--echo # +--echo # MDEV-28020 CHECKSUM TABLE calculates different checksums +--echo # +create table t1 ( a int, b int as (a) virtual, c text) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +checksum table t1 extended; +checksum table t1; +drop table t1; + +create table t1 ( a int, b int as (a) virtual, c text, key(b)) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +checksum table t1 extended; +checksum table t1; +drop table t1; + +create table t1 ( a int, b int as (a) stored, c text) engine=myisam checksum=1; +insert ignore t1 values (1,2,'foo'),(2,3,'bar'); +checksum table t1 extended; +checksum table t1; +drop table t1; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a2dc5c97aeb..f9d7f4a2ea2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10631,6 +10631,8 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, for (uint i= 0; i < t->s->fields; i++ ) { Field *f= t->field[i]; + if (!f->stored_in_db()) + continue; if (! thd->variables.old_mode && f->is_real_null(0)) { From fccca49997320bafe1282c758a5143f88b6e0e0f Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 26 Apr 2022 06:58:51 +0200 Subject: [PATCH 45/94] MDEV-28377: galera_as_slave_nonprim bind: Address already in use This commit fixes a crash reported as MDEV-28377 and a number of other crashes in automated tests with mtr that are related to broken .cnf files in galera and galera_3nodes suites, which happened when automatically migrating MDEV-26171 from 10.3 to subsequent higher versions. --- mysql-test/suite/galera/disabled.def | 1 - mysql-test/suite/galera/galera_2nodes.cnf | 19 +- .../suite/galera/galera_2nodes_as_master.cnf | 36 +- .../suite/galera/galera_2nodes_as_slave.cnf | 74 +-- .../suite/galera/galera_3nodes_as_slave.cnf | 89 +-- mysql-test/suite/galera/galera_4nodes.cnf | 17 +- ...era_sst_mariabackup_logarchive,debug.rdiff | 200 +++++-- .../galera_sst_mariabackup_logarchive.result | 554 +++++++++++++----- .../t/galera_sst_mariabackup_logarchive.cnf | 2 +- .../t/galera_sst_mariabackup_logarchive.test | 18 +- .../suite/galera_3nodes/galera_2x3nodes.cnf | 54 +- .../suite/galera_3nodes/galera_3nodes.cnf | 24 +- .../r/galera_garbd_backup.result | 2 - .../galera_3nodes/t/galera_garbd_backup.test | 2 + scripts/wsrep_sst_rsync.sh | 7 - 15 files changed, 642 insertions(+), 457 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 6c5aed79664..0cb698bbe73 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -16,7 +16,6 @@ MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-329 : MDEV-19962 Galera test failure on MW-329 galera_as_slave_ctas : MDEV-28378 timeout -galera_as_slave_nonprim : MDEV-28377 bind: Address already in use galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit galera_bf_lock_wait : MDEV-21597 wsrep::transaction::start_transaction(): Assertion `active() == false' failed diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index 352a68b06e6..3532c1f2134 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -8,40 +8,31 @@ innodb-autoinc-lock-mode=2 default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER # enforce read-committed characteristics across the cluster +# wsrep-causal-reads=ON wsrep-sync-wait=15 -wsrep-on=1 [mysqld.1] -loose-innodb +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-cluster-address=gcomm:// +wsrep_cluster_address=gcomm:// wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep_causal_reads=ON -wsrep_sync_wait = 15 - [mysqld.2] -loose-innodb -# debug=d:t:i:o,/tmp/mysqld.2.trace +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep_causal_reads=ON -wsrep_sync_wait = 15 - [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf index 08e4f97b7b8..ba53d6062c1 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_master.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_master.cnf @@ -7,50 +7,44 @@ !include include/default_mysqld.cnf [mysqld] +loose-innodb log-bin=mysqld-bin +log-slave-updates binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb +# enforce read-committed characteristics across the cluster +# wsrep-causal-reads=ON +wsrep-sync-wait=15 [mysqld.1] +wsrep-on=1 +server-id=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port - -server-id=1 -log_slave_updates - -wsrep-on=1 -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' +wsrep_provider=@ENV.WSREP_PROVIDER wsrep_cluster_address=gcomm:// -wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 +wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' [mysqld.2] +wsrep-on=1 +server-id=2 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port - -server-id=2 -log_slave_updates - -wsrep-on=1 wsrep_provider=@ENV.WSREP_PROVIDER -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 +wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' [mysqld.3] +wsrep-on=OFF server-id=3 [ENV] diff --git a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf index 0d680731dcd..f25c7cc6d48 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf @@ -6,81 +6,45 @@ !include include/default_mysqld.cnf [mysqld] +loose-innodb +log-bin=mysqld-bin +log-slave-updates binlog-format=row +innodb-autoinc-lock-mode=2 +default-storage-engine=innodb +# enforce read-committed characteristics across the cluster +# wsrep-causal-reads=ON +wsrep-sync-wait=15 [mysqld.1] +wsrep-on=1 +server-id=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 - -log-bin=master-bin -log-bin-index=master-bin -log-slave-updates - -innodb-autoinc-lock-mode=2 -default-storage-engine=innodb -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep-cluster-address=gcomm:// -wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' +wsrep_provider=@ENV.WSREP_PROVIDER +wsrep_cluster_address=gcomm:// +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' +wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 -server-id=1 - [mysqld.2] +wsrep-on=1 +server-id=2 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 - -log-bin=master-bin -log-bin-index=master-bin -log-slave-updates - -innodb-autoinc-lock-mode=2 -default-storage-engine=innodb -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep_node_address=127.0.0.1 +wsrep_provider=@ENV.WSREP_PROVIDER wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 -server-id=2 - [mysqld.3] -#galera_port=@OPT.port -#ist_port=@OPT.port -#sst_port=@OPT.port - -wsrep-on=1 - -log-bin=master-bin -log-bin-index=master-bin -log-slave-updates - -innodb-autoinc-lock-mode=2 -default-storage-engine=innodb -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port' -wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M' -wsrep_node_address='127.0.0.1:@mysqld.3.#galera_port' -wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' - -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 -server-id=3 wsrep-on=OFF +server-id=3 [ENV] NODE_MYPORT_1= @mysqld.1.port diff --git a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf index bb9473c7fc4..0ecf877b5a3 100644 --- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf @@ -6,98 +6,57 @@ !include include/default_mysqld.cnf [mysqld] -log-bin +loose-innodb +log-bin=mysqld-bin +log-slave-updates binlog-format=row +innodb-autoinc-lock-mode=2 +default-storage-engine=innodb +# enforce read-committed characteristics across the cluster +# wsrep-causal-reads=ON +wsrep-sync-wait=15 [mysqld.1] +wsrep-on=1 +server-id=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 - -log-slave-updates -wsrep-on=1 - -innodb-autoinc-lock-mode=2 -default-storage-engine=innodb -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep-cluster-address=gcomm:// -wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.install_timeout = PT15S;evs.max_install_timeouts=1;gcache.size=10M' +wsrep_provider=@ENV.WSREP_PROVIDER +wsrep_cluster_address=gcomm:// +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 -server-id=1 - [mysqld.2] +wsrep-on=1 +server-id=2 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 - -log-slave-updates -wsrep-on=1 - -innodb-autoinc-lock-mode=2 -default-storage-engine=innodb -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep_node_address=127.0.0.1 +wsrep_provider=@ENV.WSREP_PROVIDER wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M' -wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' - -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 -server-id=2 +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' +wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' +wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' [mysqld.3] +wsrep-on=1 +server-id=3 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 - -log-slave-updates -wsrep-on=1 - -innodb-autoinc-lock-mode=2 -default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.3.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 -server-id=3 - [mysqld.4] -#galera_port=@OPT.port -#ist_port=@OPT.port -#sst_port=@OPT.port - -log-slave-updates -wsrep-on=1 - -innodb-autoinc-lock-mode=2 -default-storage-engine=innodb -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.4.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M' -wsrep_node_address='127.0.0.1:@mysqld.4.#galera_port' -wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' - -# enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON -wsrep-sync-wait=15 +wsrep-on=OFF server-id=4 [ENV] diff --git a/mysql-test/suite/galera/galera_4nodes.cnf b/mysql-test/suite/galera/galera_4nodes.cnf index 03a7b226280..66238a8e4c2 100644 --- a/mysql-test/suite/galera/galera_4nodes.cnf +++ b/mysql-test/suite/galera/galera_4nodes.cnf @@ -2,50 +2,55 @@ !include include/default_mysqld.cnf [mysqld] +loose-innodb binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER # enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON +# wsrep-causal-reads=ON wsrep-sync-wait=15 [mysqld.1] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-cluster-address=gcomm:// -wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' +wsrep_cluster_address=gcomm:// +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' [mysqld.2] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' [mysqld.3] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.3.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' [mysqld.4] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.4.#galera_port;gcache.size=10M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.4.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.4.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive,debug.rdiff b/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive,debug.rdiff index e6757c7561e..a9c796da607 100644 --- a/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive,debug.rdiff +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive,debug.rdiff @@ -1,27 +1,27 @@ --- r/galera_sst_mariabackup_logarchive.result +++ r/galera_sst_mariabackup_logarchive.reject -@@ -286,5 +286,113 @@ +@@ -516,5 +516,189 @@ + 1 DROP TABLE t1; COMMIT; - SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +connection node_1; -+CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; ++CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; -+INSERT INTO t1 VALUES ('node1_committed_before'); -+INSERT INTO t1 VALUES ('node1_committed_before'); -+INSERT INTO t1 VALUES ('node1_committed_before'); -+INSERT INTO t1 VALUES ('node1_committed_before'); -+INSERT INTO t1 VALUES ('node1_committed_before'); ++INSERT INTO t1 VALUES (1,'node1_committed_before'); ++INSERT INTO t1 VALUES (2,'node1_committed_before'); ++INSERT INTO t1 VALUES (3,'node1_committed_before'); ++INSERT INTO t1 VALUES (4,'node1_committed_before'); ++INSERT INTO t1 VALUES (5,'node1_committed_before'); +connection node_2; +START TRANSACTION; -+INSERT INTO t1 VALUES ('node2_committed_before'); -+INSERT INTO t1 VALUES ('node2_committed_before'); -+INSERT INTO t1 VALUES ('node2_committed_before'); -+INSERT INTO t1 VALUES ('node2_committed_before'); -+INSERT INTO t1 VALUES ('node2_committed_before'); ++INSERT INTO t1 VALUES (6,'node2_committed_before'); ++INSERT INTO t1 VALUES (7,'node2_committed_before'); ++INSERT INTO t1 VALUES (8,'node2_committed_before'); ++INSERT INTO t1 VALUES (9,'node2_committed_before'); ++INSERT INTO t1 VALUES (10,'node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +connection node_1; @@ -32,26 +32,26 @@ +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; -+INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_during'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (11,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (12,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (13,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (14,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (15,'node1_committed_during'); +COMMIT; +START TRANSACTION; -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (16,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (17,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (18,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (19,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (20,'node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (21,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (22,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (23,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (24,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (25,'node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +connection node_2; @@ -59,58 +59,134 @@ +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; -+INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node2_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (26,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (27,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (28,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (29,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (30,'node2_committed_after'); +COMMIT; +connection node_1; -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (31,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (32,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (33,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (34,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (35,'node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; -+INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_after'); -+INSERT INTO t1 (f1) VALUES ('node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (36,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (37,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (38,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (39,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (40,'node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave_ddl; -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (41,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (42,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (43,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (44,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (45,'node1_to_be_rollbacked_after'); +ROLLBACK; -+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; -+COUNT(*) = 2 -+1 -+SELECT COUNT(*) = 35 FROM t1; -+COUNT(*) = 35 -+1 ++SET AUTOCOMMIT=ON; ++SET SESSION wsrep_sync_wait=15; ++SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++EXPECT_3 ++3 ++SELECT COUNT(*) AS EXPECT_35 FROM t1; ++EXPECT_35 ++35 ++SELECT * FROM t1; ++id f1 f2 ++1 node1_committed_before NULL ++2 node1_committed_before NULL ++3 node1_committed_before NULL ++4 node1_committed_before NULL ++5 node1_committed_before NULL ++6 node2_committed_before NULL ++7 node2_committed_before NULL ++8 node2_committed_before NULL ++9 node2_committed_before NULL ++10 node2_committed_before NULL ++11 node1_committed_during NULL ++12 node1_committed_during NULL ++13 node1_committed_during NULL ++14 node1_committed_during NULL ++15 node1_committed_during NULL ++16 node1_to_be_committed_after NULL ++17 node1_to_be_committed_after NULL ++18 node1_to_be_committed_after NULL ++19 node1_to_be_committed_after NULL ++20 node1_to_be_committed_after NULL ++26 node2_committed_after NULL ++27 node2_committed_after NULL ++28 node2_committed_after NULL ++29 node2_committed_after NULL ++30 node2_committed_after NULL ++31 node1_to_be_committed_after NULL ++32 node1_to_be_committed_after NULL ++33 node1_to_be_committed_after NULL ++34 node1_to_be_committed_after NULL ++35 node1_to_be_committed_after NULL ++36 node1_committed_after NULL ++37 node1_committed_after NULL ++38 node1_committed_after NULL ++39 node1_committed_after NULL ++40 node1_committed_after NULL +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; -+SET AUTOCOMMIT=ON; +connection node_1; -+SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; -+COUNT(*) = 2 -+1 -+SELECT COUNT(*) = 35 FROM t1; -+COUNT(*) = 35 -+1 ++SET AUTOCOMMIT=ON; ++SET SESSION wsrep_sync_wait=15; ++SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++EXPECT_3 ++3 ++SELECT COUNT(*) AS EXPECT_35 FROM t1; ++EXPECT_35 ++35 ++SELECT * FROM t1; ++id f1 f2 ++1 node1_committed_before NULL ++2 node1_committed_before NULL ++3 node1_committed_before NULL ++4 node1_committed_before NULL ++5 node1_committed_before NULL ++6 node2_committed_before NULL ++7 node2_committed_before NULL ++8 node2_committed_before NULL ++9 node2_committed_before NULL ++10 node2_committed_before NULL ++11 node1_committed_during NULL ++12 node1_committed_during NULL ++13 node1_committed_during NULL ++14 node1_committed_during NULL ++15 node1_committed_during NULL ++16 node1_to_be_committed_after NULL ++17 node1_to_be_committed_after NULL ++18 node1_to_be_committed_after NULL ++19 node1_to_be_committed_after NULL ++20 node1_to_be_committed_after NULL ++26 node2_committed_after NULL ++27 node2_committed_after NULL ++28 node2_committed_after NULL ++29 node2_committed_after NULL ++30 node2_committed_after NULL ++31 node1_to_be_committed_after NULL ++32 node1_to_be_committed_after NULL ++33 node1_to_be_committed_after NULL ++34 node1_to_be_committed_after NULL ++35 node1_to_be_committed_after NULL ++36 node1_committed_after NULL ++37 node1_committed_after NULL ++38 node1_committed_after NULL ++39 node1_committed_after NULL ++40 node1_committed_after NULL +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; -+SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; disconnect node_2; disconnect node_1; diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive.result index 09e49e6f717..c2bbb94653a 100644 --- a/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive.result +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_logarchive.result @@ -1,292 +1,522 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_2; connection node_1; Performing State Transfer on a server that has been shut down cleanly and restarted connection node_1; -CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES (1,'node1_committed_before'); +INSERT INTO t1 VALUES (2,'node1_committed_before'); +INSERT INTO t1 VALUES (3,'node1_committed_before'); +INSERT INTO t1 VALUES (4,'node1_committed_before'); +INSERT INTO t1 VALUES (5,'node1_committed_before'); COMMIT; connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES (6,'node2_committed_before'); +INSERT INTO t1 VALUES (7,'node2_committed_before'); +INSERT INTO t1 VALUES (8,'node2_committed_before'); +INSERT INTO t1 VALUES (9,'node2_committed_before'); +INSERT INTO t1 VALUES (10,'node2_committed_before'); COMMIT; Shutting down server ... connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES (11,'node1_committed_during'); +INSERT INTO t1 VALUES (12,'node1_committed_during'); +INSERT INTO t1 VALUES (13,'node1_committed_during'); +INSERT INTO t1 VALUES (14,'node1_committed_during'); +INSERT INTO t1 VALUES (15,'node1_committed_during'); COMMIT; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES (16,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (17,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (18,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (19,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (20,'node1_to_be_committed_after'); connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after'); connection node_2; Starting server ... SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES (26,'node2_committed_after'); +INSERT INTO t1 VALUES (27,'node2_committed_after'); +INSERT INTO t1 VALUES (28,'node2_committed_after'); +INSERT INTO t1 VALUES (29,'node2_committed_after'); +INSERT INTO t1 VALUES (30,'node2_committed_after'); COMMIT; connection node_1; -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES (31,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (32,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (33,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (34,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (35,'node1_to_be_committed_after'); COMMIT; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES (36,'node1_committed_after'); +INSERT INTO t1 VALUES (37,'node1_committed_after'); +INSERT INTO t1 VALUES (38,'node1_committed_after'); +INSERT INTO t1 VALUES (39,'node1_committed_after'); +INSERT INTO t1 VALUES (40,'node1_committed_after'); COMMIT; connection node_1a_galera_st_shutdown_slave; -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after'); ROLLBACK; -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_15 FROM t1; +EXPECT_15 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; COUNT(*) = 0 1 COMMIT; -SET AUTOCOMMIT=ON; connection node_1; -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_15 FROM t1; +EXPECT_15 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; COUNT(*) = 0 1 DROP TABLE t1; COMMIT; -SET AUTOCOMMIT=ON; Performing State Transfer on a server that starts from a clean var directory This is accomplished by shutting down node #2 and removing its var directory before restarting it connection node_1; -CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES (1,'node1_committed_before'); +INSERT INTO t1 VALUES (2,'node1_committed_before'); +INSERT INTO t1 VALUES (3,'node1_committed_before'); +INSERT INTO t1 VALUES (4,'node1_committed_before'); +INSERT INTO t1 VALUES (5,'node1_committed_before'); COMMIT; connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES (6,'node2_committed_before'); +INSERT INTO t1 VALUES (7,'node2_committed_before'); +INSERT INTO t1 VALUES (8,'node2_committed_before'); +INSERT INTO t1 VALUES (9,'node2_committed_before'); +INSERT INTO t1 VALUES (10,'node2_committed_before'); COMMIT; Shutting down server ... connection node_1; Cleaning var directory ... SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES (11,'node1_committed_during'); +INSERT INTO t1 VALUES (12,'node1_committed_during'); +INSERT INTO t1 VALUES (13,'node1_committed_during'); +INSERT INTO t1 VALUES (14,'node1_committed_during'); +INSERT INTO t1 VALUES (15,'node1_committed_during'); COMMIT; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES (16,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (17,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (18,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (19,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (20,'node1_to_be_committed_after'); connect node_1a_galera_st_clean_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after'); connection node_2; Starting server ... SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES (26,'node2_committed_after'); +INSERT INTO t1 VALUES (27,'node2_committed_after'); +INSERT INTO t1 VALUES (28,'node2_committed_after'); +INSERT INTO t1 VALUES (29,'node2_committed_after'); +INSERT INTO t1 VALUES (30,'node2_committed_after'); COMMIT; connection node_1; -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES (31,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (32,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (33,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (34,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (35,'node1_to_be_committed_after'); COMMIT; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES (36,'node1_committed_after'); +INSERT INTO t1 VALUES (37,'node1_committed_after'); +INSERT INTO t1 VALUES (38,'node1_committed_after'); +INSERT INTO t1 VALUES (39,'node1_committed_after'); +INSERT INTO t1 VALUES (40,'node1_committed_after'); COMMIT; connection node_1a_galera_st_clean_slave; -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after'); ROLLBACK; -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; COUNT(*) = 0 1 COMMIT; -SET AUTOCOMMIT=ON; connection node_1; -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; COUNT(*) = 0 1 DROP TABLE t1; COMMIT; -SET AUTOCOMMIT=ON; Performing State Transfer on a server that has been killed and restarted connection node_1; -CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); -INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES (1,'node1_committed_before'); +INSERT INTO t1 VALUES (2,'node1_committed_before'); +INSERT INTO t1 VALUES (3,'node1_committed_before'); +INSERT INTO t1 VALUES (4,'node1_committed_before'); +INSERT INTO t1 VALUES (5,'node1_committed_before'); COMMIT; connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); -INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES (6,'node2_committed_before'); +INSERT INTO t1 VALUES (7,'node2_committed_before'); +INSERT INTO t1 VALUES (8,'node2_committed_before'); +INSERT INTO t1 VALUES (9,'node2_committed_before'); +INSERT INTO t1 VALUES (10,'node2_committed_before'); COMMIT; Killing server ... connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); -INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES (11,'node1_committed_during'); +INSERT INTO t1 VALUES (12,'node1_committed_during'); +INSERT INTO t1 VALUES (13,'node1_committed_during'); +INSERT INTO t1 VALUES (14,'node1_committed_during'); +INSERT INTO t1 VALUES (15,'node1_committed_during'); COMMIT; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES (16,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (17,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (18,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (19,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (20,'node1_to_be_committed_after'); connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after'); connection node_2; Performing --wsrep-recover ... Starting server ... Using --wsrep-start-position when starting mysqld ... SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); -INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES (26,'node2_committed_after'); +INSERT INTO t1 VALUES (27,'node2_committed_after'); +INSERT INTO t1 VALUES (28,'node2_committed_after'); +INSERT INTO t1 VALUES (29,'node2_committed_after'); +INSERT INTO t1 VALUES (30,'node2_committed_after'); COMMIT; connection node_1; -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); -INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES (31,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (32,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (33,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (34,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (35,'node1_to_be_committed_after'); COMMIT; SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); -INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES (36,'node1_committed_after'); +INSERT INTO t1 VALUES (37,'node1_committed_after'); +INSERT INTO t1 VALUES (38,'node1_committed_after'); +INSERT INTO t1 VALUES (39,'node1_committed_after'); +INSERT INTO t1 VALUES (40,'node1_committed_after'); COMMIT; connection node_1a_galera_st_kill_slave; -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); -INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (46,'node1_to_be_rollbacked_after'); ROLLBACK; -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * FROM t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; COUNT(*) = 0 1 COMMIT; -SET AUTOCOMMIT=ON; connection node_1; -SELECT COUNT(*) = 35 FROM t1; -COUNT(*) = 35 -1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * FROM t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; COUNT(*) = 0 1 DROP TABLE t1; COMMIT; -SET AUTOCOMMIT=ON; disconnect node_2; disconnect node_1; diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.cnf index 96b1b5465cd..04043ac2b74 100644 --- a/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.cnf @@ -3,7 +3,7 @@ [mysqld] wsrep_sst_method=mariabackup wsrep_sst_auth="root:" -loose_wsrep_debug=ON +wsrep_debug=1 [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.test b/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.test index 4d4a754e93c..09a18ab4c2c 100644 --- a/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.test +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_logarchive.test @@ -1,6 +1,5 @@ --source include/big_test.inc --source include/galera_cluster.inc ---source include/galera_have_debug_sync.inc --source include/have_innodb.inc --source include/have_mariabackup.inc @@ -33,10 +32,10 @@ # Restore original auto_increment_offset values. --source include/auto_increment_offset_restore.inc ---let sst_test_true_count=7 -if (`select version() like '%debug%'`) -{ - --let sst_test_true_count=10 +--let sst_test_true_count=6 +--source include/maybe_debug.inc +if ($have_debug) { + --let sst_test_true_count=6 } --source include/galera_end.inc @@ -46,16 +45,17 @@ if (`select version() like '%debug%'`) --perl use strict; use warnings; - my $file= $ENV{'MYSQLTEST_VARDIR'}.'/tmp/logarchive_list'; - my $count= 0; + my $file=$ENV{'MYSQLTEST_VARDIR'}.'/tmp/logarchive_list'; + my $count=0; open(FILE, "$file") or die("Error $? opening $file: $!\n"); while () { my $line = $_; $count++; } close(FILE) or die("Error $? closing $file: $!"); - if ($count != $ENV{'sst_test_true_count'}) { - die("Wrong log archives counter: $count"); + my $true_count=$ENV{'sst_test_true_count'}; + if ($count != $true_count) { + die("Wrong log archives counter: $count instead of $true_count"); } EOF diff --git a/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf index 46679336f47..9f99adbd711 100644 --- a/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf @@ -2,7 +2,8 @@ !include include/default_mysqld.cnf [mysqld] -log-bin +loose-innodb +log-bin=mysqld-bin log-slave-updates binlog-format=row innodb-autoinc-lock-mode=2 @@ -13,92 +14,71 @@ auto_increment_increment=3 wsrep-provider=@ENV.WSREP_PROVIDER # enforce read-committed characteristics across the cluster +# wsrep-causal-reads=ON wsrep-sync-wait=15 [mysqld.1] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 -wsrep-cluster-address='gcomm://' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT30S;evs.inactive_timeout=PT90S;evs.install_timeout=PT60S;pc.wait_prim_timeout = PT60S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.1.#sst_port +wsrep_cluster_address=gcomm:// +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' [mysqld.2] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT30S;evs.inactive_timeout=PT90S;evs.install_timeout=PT60S;pc.wait_prim_timeout = PT60S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.2.#sst_port +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' [mysqld.3] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT30S;evs.inactive_timeout=PT90S;evs.install_timeout=PT60S;pc.wait_prim_timeout = PT60S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.3.#sst_port +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.3.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' -<<<<<<< HEAD - -||||||| 3c99a48db31 -wsrep-on=1 - -======= ->>>>>>> origin/st-10.3-marko [mysqld.4] -wsrep_cluster_name=cluster2 +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 -wsrep-cluster-address='gcomm://' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.4.#galera_port;evs.suspect_timeout=PT30S;evs.inactive_timeout=PT90S;evs.install_timeout=PT60S;pc.wait_prim_timeout = PT60S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.4.#sst_port +wsrep_cluster_address='gcomm:// +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.4.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.4.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' [mysqld.5] -wsrep_cluster_name=cluster2 +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.4.#galera_port' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.5.#galera_port;evs.suspect_timeout=PT30S;evs.inactive_timeout=PT90S;evs.install_timeout=PT60S;pc.wait_prim_timeout = PT60S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.5.#sst_port +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.5.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.5.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.5.port wsrep_sst_receive_address='127.0.0.1:@mysqld.5.#sst_port' [mysqld.6] -wsrep_cluster_name=cluster2 +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.4.#galera_port' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.6.#galera_port;evs.suspect_timeout=PT30S;evs.inactive_timeout=PT90S;evs.install_timeout=PT60S;pc.wait_prim_timeout = PT60S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.6.#sst_port +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.6.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.6.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.6.port wsrep_sst_receive_address='127.0.0.1:@mysqld.6.#sst_port' diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf index 8f69b8e0270..a7dd4d21bc7 100644 --- a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf @@ -2,6 +2,7 @@ !include include/default_mysqld.cnf [mysqld] +loose-innodb binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb @@ -9,45 +10,38 @@ auto_increment_increment=3 wsrep-provider=@ENV.WSREP_PROVIDER # enforce read-committed characteristics across the cluster -wsrep-causal-reads=ON +# wsrep-causal-reads=ON wsrep-sync-wait=15 [mysqld.1] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -#wsrep-new-cluster -wsrep-on=1 -wsrep-cluster-address='gcomm://' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.1.#sst_port +wsrep_cluster_address=gcomm:// +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' [mysqld.2] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.2.#sst_port +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' [mysqld.3] +wsrep-on=1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port -wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' - -wsrep_sst_receive_address=127.0.0.2:@mysqld.3.#sst_port +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_address='127.0.0.1:@mysqld.3.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' diff --git a/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result b/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result index 1cf4e0194ca..4a5e9a4530c 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result +++ b/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result @@ -33,8 +33,6 @@ DROP TABLE ten; Restarting node #3 to satisfy MTR's end-of-test checks connection node_3; connection node_1; -SET GLOBAL innodb_max_dirty_pages_pct = 75.000000; -SET GLOBAL innodb_max_dirty_pages_pct_lwm = 0.000000; connection node_1; CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)"); connection node_2; diff --git a/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test b/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test index 302bf430dde..f5eaf6fc59a 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test @@ -119,8 +119,10 @@ let $restart_noprint=2; --source include/start_mysqld.inc --connection node_1 +--disable_query_log --eval SET GLOBAL innodb_max_dirty_pages_pct = $innodb_max_dirty_pages_pct --eval SET GLOBAL innodb_max_dirty_pages_pct_lwm = $innodb_max_dirty_pages_pct_lwm +--enable_query_log --source ../galera/include/auto_increment_offset_restore.inc diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 29e2b390e27..2c3622dff7a 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -443,13 +443,6 @@ EOF elif tar --version | grep -q -E '^bsdtar\>'; then tar_type=2 fi - if [ $tar_type -ne 2 ]; then - if [ -n "$BASH_VERSION" ]; then - printf '%s' "$binlog_files" >&2 - else - echo "$binlog_files" >&2 - fi - fi if [ $tar_type -ne 0 ]; then # Preparing list of the binlog file names: echo "$binlog_files" | { From f21a87560091a8149752b13e097d382ba30786d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 27 Apr 2022 07:57:04 +0300 Subject: [PATCH 46/94] MDEV-28415 ALTER TABLE on a large table hangs InnoDB buf_flush_page(): Never wait for a page latch, even in checkpoint flushing (flush_type == BUF_FLUSH_LIST), to prevent a hang of the page cleaner threads when a large number of pages is latched. In mysql/mysql-server@9542f3015b00330ef537f6223565b28b82a5b325 it was claimed that such a hang only affects CREATE FULLTEXT INDEX. Their fix was to retain buffer-fix but release exclusive latch on non-leaf pages, and subsequently write to those pages while they are not associated with the mini-transaction, which would trip a debug assertion in the MariaDB version of mtr_t::memo_modify_page() and cause potential corruption when using the default MariaDB setting innodb_log_optimize_ddl=OFF. This change essentially backports a small part of commit 7cffb5f6e8a231a041152447be8980ce35d2c9b8 (MDEV-23399) from MariaDB Server 10.5.7. --- storage/innobase/buf/buf0flu.cc | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 2beddf4b243..e029948be55 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Copyright (c) 2013, 2014, Fusion-io This program is free software; you can redistribute it and/or modify it under @@ -1160,15 +1160,10 @@ buf_flush_page( /* For table residing in temporary tablespace sync is done using IO_FIX and so before scheduling for flush ensure that page is not fixed. */ - flush = FALSE; + return FALSE; } else { rw_lock = &reinterpret_cast(bpage)->lock; - if (flush_type != BUF_FLUSH_LIST) { - flush = rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE); - } else { - /* Will SX lock later */ - flush = TRUE; - } + flush = rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE); } if (flush) { @@ -1190,22 +1185,6 @@ buf_flush_page( buf_pool_mutex_exit(buf_pool); - if (flush_type == BUF_FLUSH_LIST - && is_uncompressed - && !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) { - - if (!fsp_is_system_temporary(bpage->id.space())) { - /* avoiding deadlock possibility involves - doublewrite buffer, should flush it, because - it might hold the another block->lock. */ - buf_dblwr_flush_buffered_writes(); - } else { - buf_dblwr_sync_datafiles(); - } - - rw_lock_sx_lock_gen(rw_lock, BUF_IO_WRITE); - } - /* If there is an observer that want to know if the asynchronous flushing was sent then notify it. Note: we set flush observer to a page with x-latch, so we can From 44a27a26e910c9fb27731bd2cb267262949ea2da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 27 Apr 2022 08:08:06 +0300 Subject: [PATCH 47/94] MDEV-28416 Incorrect AUTO_INCREMENT may be issued when close to UINT64_MAX ha_innobase::get_auto_increment(): In the overflow check, account for 64-bit unsigned integer wrap-around. Based on mysql/mysql-server@25ecfe7f49b5a649e96d462cb90602de9de3b919 --- .../suite/innodb/r/innodb-autoinc-part.result | 34 +++++++++++++++++++ .../suite/innodb/r/innodb-autoinc.result | 25 +++++++++++++- .../suite/innodb/t/innodb-autoinc-part.test | 24 +++++++++++++ mysql-test/suite/innodb/t/innodb-autoinc.test | 23 +++++++++---- storage/innobase/handler/ha_innodb.cc | 4 +-- 5 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-autoinc-part.result create mode 100644 mysql-test/suite/innodb/t/innodb-autoinc-part.test diff --git a/mysql-test/suite/innodb/r/innodb-autoinc-part.result b/mysql-test/suite/innodb/r/innodb-autoinc-part.result new file mode 100644 index 00000000000..6872b5e02f5 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-autoinc-part.result @@ -0,0 +1,34 @@ +# +# MDEV-28416 Incorrect AUTO_INCREMENT may be issued +# +SET @aii=@@auto_increment_increment; +SET auto_increment_increment=300; +CREATE TABLE t1 (a SERIAL) ENGINE=innodb +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (6), +PARTITION p1 VALUES LESS THAN MAXVALUE +); +INSERT INTO t1 VALUES (18446744073709551613); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551614 DEFAULT CHARSET=latin1 + PARTITION BY RANGE (`a`) +(PARTITION `p0` VALUES LESS THAN (6) ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN MAXVALUE ENGINE = InnoDB) +INSERT INTO t1 VALUES (NULL); +ERROR 22003: Out of range value for column 'a' at row 1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB AUTO_INCREMENT=298 DEFAULT CHARSET=latin1 + PARTITION BY RANGE (`a`) +(PARTITION `p0` VALUES LESS THAN (6) ENGINE = InnoDB, + PARTITION `p1` VALUES LESS THAN MAXVALUE ENGINE = InnoDB) +DROP TABLE t1; +SET auto_increment_increment=@aii; +# End of 10.2 tests diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result index 6c405627e08..00690ecaff7 100644 --- a/mysql-test/suite/innodb/r/innodb-autoinc.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc.result @@ -1,4 +1,3 @@ -drop table if exists t1; CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; INSERT INTO t1 VALUES (9223372036854775807, null); INSERT INTO t1 (c2) VALUES ('innodb'); @@ -1619,3 +1618,27 @@ id name -1 dog 2 cat DROP PROCEDURE autoinc_mdev15353_one; +# +# MDEV-28416 Incorrect AUTO_INCREMENT may be issued +# +SET @aii=@@auto_increment_increment; +SET auto_increment_increment=300; +CREATE TABLE t1 (a SERIAL) ENGINE=innodb; +INSERT INTO t1 VALUES (18446744073709551613); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551614 DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (NULL); +ERROR 22003: Out of range value for column 'a' at row 1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET auto_increment_increment=@aii; +# End of 10.2 tests diff --git a/mysql-test/suite/innodb/t/innodb-autoinc-part.test b/mysql-test/suite/innodb/t/innodb-autoinc-part.test new file mode 100644 index 00000000000..100546704ce --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-autoinc-part.test @@ -0,0 +1,24 @@ +--source include/have_partition.inc +--source include/have_innodb.inc + +--echo # +--echo # MDEV-28416 Incorrect AUTO_INCREMENT may be issued +--echo # + +SET @aii=@@auto_increment_increment; +SET auto_increment_increment=300; + +CREATE TABLE t1 (a SERIAL) ENGINE=innodb +PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN MAXVALUE +); +INSERT INTO t1 VALUES (18446744073709551613); +SHOW CREATE TABLE t1; +--error HA_ERR_AUTOINC_ERANGE +INSERT INTO t1 VALUES (NULL); +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET auto_increment_increment=@aii; + +--echo # End of 10.2 tests diff --git a/mysql-test/suite/innodb/t/innodb-autoinc.test b/mysql-test/suite/innodb/t/innodb-autoinc.test index ca7727d4cef..158460558d5 100644 --- a/mysql-test/suite/innodb/t/innodb-autoinc.test +++ b/mysql-test/suite/innodb/t/innodb-autoinc.test @@ -1,10 +1,4 @@ --source include/have_innodb.inc -# embedded server ignores 'delayed', so skip this --- source include/not_embedded.inc - ---disable_warnings -drop table if exists t1; ---enable_warnings # # Bug #34335 @@ -770,3 +764,20 @@ DROP TABLE t1; SET @engine='INNODB'; --source include/autoinc_mdev15353.inc + +--echo # +--echo # MDEV-28416 Incorrect AUTO_INCREMENT may be issued +--echo # + +SET @aii=@@auto_increment_increment; +SET auto_increment_increment=300; +CREATE TABLE t1 (a SERIAL) ENGINE=innodb; +INSERT INTO t1 VALUES (18446744073709551613); +SHOW CREATE TABLE t1; +--error HA_ERR_AUTOINC_ERANGE +INSERT INTO t1 VALUES (NULL); +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET auto_increment_increment=@aii; + +--echo # End of 10.2 tests diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1884250ee48..53d5a07b79f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -16970,8 +16970,8 @@ ha_innobase::get_auto_increment( (3) It is restricted only for insert operations. */ - if (increment > 1 && thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE - && autoinc < col_max_value) { + if (increment > 1 && increment <= ~autoinc && autoinc < col_max_value + && thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE) { ulonglong prev_auto_inc = autoinc; From 0806592ac8fb7c6071defccb51e762a89f5bd8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 27 Apr 2022 13:16:07 +0300 Subject: [PATCH 48/94] MDEV-28422 Page split breaks a gap lock btr_insert_into_right_sibling(): Inherit any gap lock from the left sibling to the right sibling before inserting the record to the right sibling and updating the node pointer(s). lock_update_node_pointer(): Update locks in case a node pointer will move. Based on mysql/mysql-server@c7d93c274fdc5c56e36458fa4000fa3a483ffffd --- .../suite/innodb/r/gap_lock_split.result | 27 +++++++++++++ mysql-test/suite/innodb/t/gap_lock_split.test | 39 +++++++++++++++++++ storage/innobase/btr/btr0btr.cc | 6 +-- storage/innobase/include/lock0lock.h | 38 +++++++++++++++++- storage/innobase/lock/lock0lock.cc | 15 ++++++- 5 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/innodb/r/gap_lock_split.result create mode 100644 mysql-test/suite/innodb/t/gap_lock_split.test diff --git a/mysql-test/suite/innodb/r/gap_lock_split.result b/mysql-test/suite/innodb/r/gap_lock_split.result new file mode 100644 index 00000000000..25a3cf711f9 --- /dev/null +++ b/mysql-test/suite/innodb/r/gap_lock_split.result @@ -0,0 +1,27 @@ +SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB; +INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023; +connect con1,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1 WHERE id=1788; +BEGIN; +SELECT * FROM t1 WHERE id=1788 FOR UPDATE; +id val +connection con1; +COMMIT; +InnoDB 0 transactions not purged +connection default; +INSERT INTO t1 (id,val) VALUES (1787, REPEAT('x',2000)); +connection con1; +SET innodb_lock_wait_timeout=0; +INSERT INTO t1 (id,val) VALUES (1788, 'x'); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1 WHERE id=1788 FOR UPDATE; +id val +disconnect con1; +connection default; +COMMIT; +DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/mysql-test/suite/innodb/t/gap_lock_split.test b/mysql-test/suite/innodb/t/gap_lock_split.test new file mode 100644 index 00000000000..462f073ddce --- /dev/null +++ b/mysql-test/suite/innodb/t/gap_lock_split.test @@ -0,0 +1,39 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc +--source include/have_debug.inc + +SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; + +CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB; +INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023; + +connect(con1,localhost,root,,); +# Prevent purge. +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; + +DELETE FROM t1 WHERE id=1788; + +BEGIN; +# This will return no result, but should acquire a gap lock. +SELECT * FROM t1 WHERE id=1788 FOR UPDATE; + +connection con1; +COMMIT; +source include/wait_all_purged.inc; +connection default; + +INSERT INTO t1 (id,val) VALUES (1787, REPEAT('x',2000)); + +connection con1; +SET innodb_lock_wait_timeout=0; +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 (id,val) VALUES (1788, 'x'); +SELECT * FROM t1 WHERE id=1788 FOR UPDATE; +disconnect con1; + +connection default; +COMMIT; +DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index bc85a955f80..b2c3b55cbaa 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2021, MariaDB Corporation. +Copyright (c) 2014, 2022, 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 @@ -2688,8 +2688,8 @@ btr_insert_into_right_sibling( max_size = page_get_max_insert_size_after_reorganize(next_page, 1); /* Extends gap lock for the next page */ - if (!dict_table_is_locking_disabled(cursor->index->table)) { - lock_update_split_left(next_block, block); + if (is_leaf && !dict_table_is_locking_disabled(cursor->index->table)) { + lock_update_node_pointer(block, next_block); } rec = page_cur_tuple_insert( diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 9c3f5d57f01..c7fb219a7d5 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 1996, 2022, Oracle and/or its affiliates. +Copyright (c) 2017, 2022, 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 @@ -151,6 +151,40 @@ lock_update_copy_and_discard( which copied */ const buf_block_t* block); /*!< in: index page; NOT the root! */ +/** Update gap locks between the last record of the left_block and the +first record of the right_block when a record is about to be inserted +at the start of the right_block, even though it should "naturally" be +inserted as the last record of the left_block according to the +current node pointer in the parent page. + +That is, we assume that the lowest common ancestor of the left_block +and right_block routes the key of the new record to the left_block, +but a heuristic which tries to avoid overflowing left_block has chosen +to insert the record into right_block instead. Said ancestor performs +this routing by comparing the key of the record to a "split point" - +all records greater or equal to than the split point (node pointer) +are in right_block, and smaller ones in left_block. +The split point may be smaller than the smallest key in right_block. + +The gap between the last record on the left_block and the first record +on the right_block is represented as a gap lock attached to the supremum +pseudo-record of left_block, and a gap lock attached to the new first +record of right_block. + +Thus, inserting the new record, and subsequently adjusting the node +pointers in parent pages to values smaller or equal to the new +records' key, will mean that gap will be sliced at a different place +("moved to the left"): fragment of the 1st gap will now become treated +as 2nd. Therefore, we must copy any GRANTED locks from 1st gap to the +2nd gap. Any WAITING locks must be of INSERT_INTENTION type (as no +other GAP locks ever wait for anything) and can stay at 1st gap, as +their only purpose is to notify the requester they can retry +insertion, and there's no correctness requirement to avoid waking them +up too soon. +@param left_block left page +@param right_block right page */ +void lock_update_node_pointer(const buf_block_t *left_block, + const buf_block_t *right_block); /*************************************************************//** Updates the lock table when a page is split to the left. */ void diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 37e23b56dfc..3398f09b772 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2021, MariaDB Corporation. +Copyright (c) 1996, 2022, Oracle and/or its affiliates. +Copyright (c) 2014, 2022, 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 @@ -3044,6 +3044,17 @@ lock_update_split_right( lock_mutex_exit(); } +void lock_update_node_pointer(const buf_block_t *left_block, + const buf_block_t *right_block) +{ + const ulint h= lock_get_min_heap_no(right_block); + + lock_mutex_enter(); + lock_rec_inherit_to_gap(right_block, left_block, + h, PAGE_HEAP_NO_SUPREMUM); + lock_mutex_exit(); +} + /*************************************************************//** Updates the lock table when a page is merged to the right. */ void From 39feab3cd31b5414aa9b428eaba915c251ac34a2 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 25 Apr 2022 18:08:57 -0700 Subject: [PATCH 49/94] MDEV-26412 Server crash in Item_field::fix_outer_field for INSERT SELECT IF an INSERT/REPLACE SELECT statement contained an ON expression in the top level select and this expression used a subquery with a column reference that could not be resolved then an attempt to resolve this reference as an outer reference caused a crash of the server. This happened because the outer context field in the Name_resolution_context structure was not set to NULL for such references. Rather it pointed to the first element in the select_stack. Note that starting from 10.4 we cannot use the SELECT_LEX::outer_select() method when parsing a SELECT construct. Approved by Oleksandr Byelkin --- mysql-test/main/insert.result | 16 ++++++++++++++++ mysql-test/main/insert.test | 22 ++++++++++++++++++++++ sql/sql_lex.cc | 1 + sql/sql_lex.h | 17 +++++++++++++++++ sql/sql_parse.cc | 4 +--- sql/sql_yacc.yy | 2 ++ 6 files changed, 59 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/insert.result b/mysql-test/main/insert.result index 4aea81262d2..1062ddd6a94 100644 --- a/mysql-test/main/insert.result +++ b/mysql-test/main/insert.result @@ -751,3 +751,19 @@ REPLACE INTO v1 SET f = NULL; ERROR 22007: Truncated incorrect DOUBLE value: 'foo' DROP VIEW v1; DROP TABLE t1; +# End of 10.0 tests +# +# MDEV-26412: INSERT CREATE with subquery in ON expression +# +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create table t4 (d1 int, d2 int); +insert into t4 +select * from t1 left join t2 on (select t1.i from t3); +ERROR 42S22: Unknown column 't1.i' in 'field list' +replace t4 +select * from t1 left join t2 on (select t1.i from t3); +ERROR 42S22: Unknown column 't1.i' in 'field list' +drop table t1,t2,t3,t4; +# End of 10.4 tests diff --git a/mysql-test/main/insert.test b/mysql-test/main/insert.test index e00c9cd7a0d..9fd0933cc7c 100644 --- a/mysql-test/main/insert.test +++ b/mysql-test/main/insert.test @@ -612,3 +612,25 @@ CREATE VIEW v1 AS SELECT * FROM t1 WHERE f <=> 'foo' WITH CHECK OPTION; REPLACE INTO v1 SET f = NULL; DROP VIEW v1; DROP TABLE t1; + +--echo # End of 10.0 tests + +--echo # +--echo # MDEV-26412: INSERT CREATE with subquery in ON expression +--echo # + +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create table t4 (d1 int, d2 int); + +--error ER_BAD_FIELD_ERROR +insert into t4 + select * from t1 left join t2 on (select t1.i from t3); +--error ER_BAD_FIELD_ERROR +replace t4 + select * from t1 left join t2 on (select t1.i from t3); + +drop table t1,t2,t3,t4; + +--echo # End of 10.4 tests diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c769e6f0972..e622d5fb863 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -701,6 +701,7 @@ void LEX::start(THD *thd_arg) context_stack.empty(); //empty select_stack select_stack_top= 0; + select_stack_outer_barrier= 0; unit.init_query(); current_select_number= 0; curr_with_clause= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 044eb425f71..3e35d16d355 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3246,6 +3246,12 @@ public: List context_stack; SELECT_LEX *select_stack[MAX_SELECT_NESTING + 1]; uint select_stack_top; + /* + Usually this is set to 0, but for INSERT/REPLACE SELECT it is set to 1. + When parsing such statements the pointer to the most outer select is placed + into the second element of select_stack rather than into the first. + */ + uint select_stack_outer_barrier; SQL_I_List proc_list; SQL_I_List auxiliary_table_list, save_list; @@ -3686,6 +3692,17 @@ public: bool copy_db_to(LEX_CSTRING *to); + void inc_select_stack_outer_barrier() + { + select_stack_outer_barrier++; + } + + SELECT_LEX *parser_current_outer_select() + { + return select_stack_top - 1 == select_stack_outer_barrier ? + 0 : select_stack[select_stack_top - 1]; + } + Name_resolution_context *current_context() { return context_stack.head(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5471861c092..6a1b849b912 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -9015,9 +9015,7 @@ push_new_name_resolution_context(THD *thd, right_op->last_leaf_for_name_resolution(); LEX *lex= thd->lex; on_context->select_lex = lex->current_select; - st_select_lex *curr_select= lex->pop_select(); - st_select_lex *outer_sel= lex->select_stack_head(); - lex->push_select(curr_select); + st_select_lex *outer_sel= lex->parser_current_outer_select(); on_context->outer_context = outer_sel ? &outer_sel->context : 0; return lex->push_context(on_context); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1559118a211..cb0d8fff50a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -13608,6 +13608,7 @@ insert: if (Lex->main_select_push()) MYSQL_YYABORT; mysql_init_select(lex); + lex->inc_select_stack_outer_barrier(); lex->current_select->parsing_place= BEFORE_OPT_LIST; } insert_lock_option @@ -13634,6 +13635,7 @@ replace: if (Lex->main_select_push()) MYSQL_YYABORT; mysql_init_select(lex); + lex->inc_select_stack_outer_barrier(); lex->current_select->parsing_place= BEFORE_OPT_LIST; } replace_lock_option insert2 From 0e4bc67eab9bbe75109b88bdcf1b3631fce35c04 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 28 Apr 2022 10:37:56 +0400 Subject: [PATCH 50/94] 10.4 specific changes for "MDEV-27494 Rename .ic files to .inl" Renaming ctype-uca.ic to ctype-uca.inl This file was introduced in 10.4, so it did not get to the main 10.2 patch for MDEV-27494 --- strings/ctype-uca.c | 16 ++++++++-------- strings/{ctype-uca.ic => ctype-uca.inl} | 0 2 files changed, 8 insertions(+), 8 deletions(-) rename strings/{ctype-uca.ic => ctype-uca.inl} (100%) diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 551efd8b0be..fbca4df39e7 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -33810,7 +33810,7 @@ static void my_uca_handler_map(struct charset_info_st *cs, #define MY_UCA_ASCII_OPTIMIZE 0 #define MY_UCA_COMPILE_CONTRACTIONS 1 #define MY_UCA_COLL_INIT my_coll_init_uca -#include "ctype-uca.ic" +#include "ctype-uca.inl" /* @@ -33915,7 +33915,7 @@ ex: #define MY_UCA_ASCII_OPTIMIZE 0 #define MY_UCA_COMPILE_CONTRACTIONS 1 #define MY_UCA_COLL_INIT my_coll_init_uca -#include "ctype-uca.ic" +#include "ctype-uca.inl" #define MY_CS_UCS2_UCA_FLAGS (MY_CS_COMMON_UCA_FLAGS|MY_CS_NONASCII) @@ -34878,7 +34878,7 @@ my_uca_coll_init_utf8mb3(struct charset_info_st *cs, MY_CHARSET_LOADER *loader); #define MY_UCA_ASCII_OPTIMIZE 1 #define MY_UCA_COMPILE_CONTRACTIONS 1 #define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb3 -#include "ctype-uca.ic" +#include "ctype-uca.inl" #define MY_FUNCTION_NAME(x) my_uca_ ## x ## _no_contractions_utf8mb3 #define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf8mb3_quick(wc, beg, end)) @@ -34886,7 +34886,7 @@ my_uca_coll_init_utf8mb3(struct charset_info_st *cs, MY_CHARSET_LOADER *loader); #define MY_UCA_ASCII_OPTIMIZE 1 #define MY_UCA_COMPILE_CONTRACTIONS 0 #define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb3 -#include "ctype-uca.ic" +#include "ctype-uca.inl" static my_bool @@ -35883,7 +35883,7 @@ my_uca_coll_init_utf8mb4(struct charset_info_st *cs, MY_CHARSET_LOADER *loader); #define MY_UCA_ASCII_OPTIMIZE 1 #define MY_UCA_COMPILE_CONTRACTIONS 1 #define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb4 -#include "ctype-uca.ic" +#include "ctype-uca.inl" #define MY_FUNCTION_NAME(x) my_uca_ ## x ## _no_contractions_utf8mb4 #define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf8mb4_quick(wc, beg, end)) @@ -35891,7 +35891,7 @@ my_uca_coll_init_utf8mb4(struct charset_info_st *cs, MY_CHARSET_LOADER *loader); #define MY_UCA_ASCII_OPTIMIZE 1 #define MY_UCA_COMPILE_CONTRACTIONS 0 #define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb4 -#include "ctype-uca.ic" +#include "ctype-uca.inl" static my_bool @@ -36859,7 +36859,7 @@ struct charset_info_st my_charset_utf8mb4_unicode_520_nopad_ci= #define MY_UCA_ASCII_OPTIMIZE 0 #define MY_UCA_COMPILE_CONTRACTIONS 1 #define MY_UCA_COLL_INIT my_coll_init_uca -#include "ctype-uca.ic" +#include "ctype-uca.inl" extern MY_CHARSET_HANDLER my_charset_utf32_handler; @@ -37817,7 +37817,7 @@ struct charset_info_st my_charset_utf32_unicode_520_nopad_ci= #define MY_UCA_ASCII_OPTIMIZE 0 #define MY_UCA_COMPILE_CONTRACTIONS 1 #define MY_UCA_COLL_INIT my_coll_init_uca -#include "ctype-uca.ic" +#include "ctype-uca.inl" extern MY_CHARSET_HANDLER my_charset_utf16_handler; diff --git a/strings/ctype-uca.ic b/strings/ctype-uca.inl similarity index 100% rename from strings/ctype-uca.ic rename to strings/ctype-uca.inl From add5137d84a41c3f45f18b149bd90099e7256cb7 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 28 Apr 2022 09:34:21 +0400 Subject: [PATCH 51/94] MDEV-28429 audit plugin report OOOOO. Few initializations to the connection_info structure added. I think they can be removed if we are sure the bug was fixed. --- plugin/server_audit/server_audit.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 12f43c3e330..80b4b644732 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -15,7 +15,7 @@ #define PLUGIN_VERSION 0x104 -#define PLUGIN_STR_VERSION "1.4.13" +#define PLUGIN_STR_VERSION "1.4.14" #define _my_thread_var loc_thread_var @@ -945,7 +945,19 @@ static unsigned long long query_counter= 1; static struct connection_info *get_loc_info(MYSQL_THD thd) { + /* + This is the original code and supposed to be returned + bach to this as the MENT-1438 is finally understood/resolved. return (struct connection_info *) THDVAR(thd, loc_info); + */ + struct connection_info *ci= (struct connection_info *) THDVAR(thd, loc_info); + if ((size_t) ci->user_length > sizeof(ci->user)) + { + ci->user_length= 0; + ci->host_length= 0; + ci->ip_length= 0; + } + return ci; } @@ -1373,6 +1385,16 @@ static size_t log_header(char *message, size_t message_len, host= userip; } + /* + That was added to find the possible cause of the MENT-1438. + Supposed to be removed after that. + */ + if (username_len > 1024) + { + username= "unknown_user"; + username_len= (unsigned int) strlen(username); + } + if (output_type == OUTPUT_SYSLOG) return my_snprintf(message, message_len, "%.*s,%.*s,%.*s,%d,%lld,%s", From eea15803ec875a27801ed9d32b7f5fbc4aec1fc7 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 26 Apr 2022 23:03:34 +0300 Subject: [PATCH 52/94] MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats Expression_cache_tmptable object uses an Expression_cache_tracker object to report the statistics. In the common scenario, Expression_cache_tmptable destructor sets tracker->cache=NULL. The tracker object survives after the expression cache is deleted and one may call cache_tracker->fetch_current_stats() for it with no harm. However a degenerate cache with no parameters does not set tracker->cache=NULL in Expression_cache_tmptable destructor which results in an attempt to use freed data in the cache_tracker->fetch_current_stats() call. Fixed by setting tracker->cache to NULL and wrapping the assignment into a function. --- mysql-test/r/subselect4.result | 75 ++++++++++++++++++++++++++++++++++ mysql-test/t/subselect4.test | 15 +++++++ sql/sql_expression_cache.cc | 4 +- sql/sql_expression_cache.h | 5 +++ 4 files changed, 98 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 43e698d2b56..e2c81d17737 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2841,4 +2841,79 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY tn eq_ref PRIMARY PRIMARY 32 test.tms.key1 1 Using where set optimizer_switch=@tmp_os; drop table t1, t10, t11; +# +# MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,4); +ANALYZE FORMAT=JSON +SELECT DISTINCT +(SELECT MIN(a) FROM t1 WHERE b <= ANY (SELECT a FROM t1)) AS f +FROM t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "duplicate_removal": { + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "subqueries": [ + { + "expression_cache": { + "state": "disabled", + "r_loops": 0, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 50, + "attached_condition": "((t1.b,(subquery#3) >= 4))" + }, + "subqueries": [ + { + "query_block": { + "select_id": 3, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + ] + } + } + } + ] + } + } + } +} +DROP TABLE t1; # End of 10.2 tests diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index 1313d2e49e7..6641cdc4557 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -2351,4 +2351,19 @@ set optimizer_switch=@tmp_os; drop table t1, t10, t11; +--echo # +--echo # MDEV-28268: Server crashes in Expression_cache_tracker::fetch_current_stats +--echo # +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,2),(3,4); + +--source include/analyze-format.inc +ANALYZE FORMAT=JSON +SELECT DISTINCT + (SELECT MIN(a) FROM t1 WHERE b <= ANY (SELECT a FROM t1)) AS f +FROM t1; + +# Cleanup +DROP TABLE t1; + --echo # End of 10.2 tests diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc index 4b6d4b4472e..5ce50a3fe52 100644 --- a/sql/sql_expression_cache.cc +++ b/sql/sql_expression_cache.cc @@ -63,7 +63,7 @@ void Expression_cache_tmptable::disable_cache() cache_table= NULL; update_tracker(); if (tracker) - tracker->cache= NULL; + tracker->detach_from_cache(); } @@ -188,6 +188,8 @@ Expression_cache_tmptable::~Expression_cache_tmptable() else { update_tracker(); + if (tracker) + tracker->detach_from_cache(); tracker= NULL; } } diff --git a/sql/sql_expression_cache.h b/sql/sql_expression_cache.h index 61e0c4c69b3..d4bb252dccb 100644 --- a/sql/sql_expression_cache.h +++ b/sql/sql_expression_cache.h @@ -83,7 +83,11 @@ public: cache(c), hit(0), miss(0), state(UNINITED) {} +private: + // This can be NULL if the cache is already deleted Expression_cache *cache; + +public: ulong hit, miss; enum expr_cache_state state; @@ -91,6 +95,7 @@ public: void set(ulong h, ulong m, enum expr_cache_state s) {hit= h; miss= m; state= s;} + void detach_from_cache() { cache= NULL; } void fetch_current_stats() { if (cache) From af810407f78b7f792a9bb8c47c8c532eb3b3a758 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 28 Apr 2022 01:58:31 +0200 Subject: [PATCH 53/94] MDEV-28098 incorrect key in "dup value" error after long unique reset errkey after using it, so that it wouldn't affect the next error message in the next statement --- mysql-test/main/long_unique_bugs.result | 14 ++++++++++++++ mysql-test/main/long_unique_bugs.test | 17 +++++++++++++++-- sql/handler.cc | 1 + 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index bf53b8f1d88..db4c8b2f3f3 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -302,4 +302,18 @@ c 1 DELETE FROM t; DROP TABLE t; +# +# MDEV-28098 incorrect key in "dup value" error after long unique +# +create table t1 (v3 int primary key, v2 text(100) unique not null, v1 int unique) engine=innodb; +insert into t1 values ( -32768 , -128 , 58 ) , ( -1 , 44 , -128 ); +create table t2 (v6 int primary key, v5 text, a int not null) engine=innodb; +insert into t2 values ( 50 , 61 , -1 ) , ( -2147483648 , -128 , 0 ); +update t1 set v2 = 1, v3 = -128; +ERROR 23000: Duplicate entry '1' for key 'v2' +update t1,t2 set v1 = v2 , v5 = 0; +ERROR 23000: Duplicate entry '-128' for key 'v1' +drop table t1, t2; +# # End of 10.4 tests +# diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index b0e6c2b3bf6..02852cf08e5 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -233,7 +233,6 @@ DROP TABLE t1; # # MDEV-18901 Wrong results after ADD UNIQUE INDEX(blob_column) # ---source include/have_innodb.inc CREATE TABLE t1 (data VARCHAR(7961)) ENGINE=InnoDB; INSERT INTO t1 VALUES ('f'), ('o'), ('o'); @@ -279,7 +278,6 @@ DROP TABLE t1; # MDEV-18820 Assertion `lock_table_has(trx, index->table, LOCK_IX)' failed in lock_rec_insert_check_and_lock upon INSERT into table with blob key' # ---source include/have_innodb.inc set innodb_lock_wait_timeout= 10; CREATE TABLE t1 ( @@ -385,4 +383,19 @@ DELETE FROM t; DROP TABLE t; +--echo # +--echo # MDEV-28098 incorrect key in "dup value" error after long unique +--echo # +create table t1 (v3 int primary key, v2 text(100) unique not null, v1 int unique) engine=innodb; +insert into t1 values ( -32768 , -128 , 58 ) , ( -1 , 44 , -128 ); +create table t2 (v6 int primary key, v5 text, a int not null) engine=innodb; +insert into t2 values ( 50 , 61 , -1 ) , ( -2147483648 , -128 , 0 ); +--error ER_DUP_ENTRY +update t1 set v2 = 1, v3 = -128; +--error ER_DUP_ENTRY +update t1,t2 set v1 = v2 , v5 = 0; +drop table t1, t2; + +--echo # --echo # End of 10.4 tests +--echo # diff --git a/sql/handler.cc b/sql/handler.cc index fe8a9e1f64e..22f5aa4e7e7 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3834,6 +3834,7 @@ void handler::print_error(int error, myf errflag) if ((int) key_nr >= 0 && key_nr < table->s->keys) { print_keydup_error(table, &table->key_info[key_nr], errflag); + table->file->errkey= -1; DBUG_VOID_RETURN; } } From 1430cf7873e0c2f1c2082291531835cec342e625 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 27 Apr 2022 16:39:50 +0200 Subject: [PATCH 54/94] MDEV-28428 Master_SSL_Crl shows Master_SSL_CA value in SHOW SLAVE STATUS output it was showing ca and capath instead of crl and crl_path --- mysql-test/extra/rpl_tests/rpl_ssl.inc | 2 +- mysql-test/suite/binlog_encryption/rpl_ssl.result | 4 ++++ mysql-test/suite/rpl/r/rpl_ssl.result | 4 ++++ sql/slave.cc | 6 +++--- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_ssl.inc b/mysql-test/extra/rpl_tests/rpl_ssl.inc index aff5499c8e5..bd77f213ae1 100644 --- a/mysql-test/extra/rpl_tests/rpl_ssl.inc +++ b/mysql-test/extra/rpl_tests/rpl_ssl.inc @@ -37,7 +37,7 @@ select * from t1; # The slave is synced and waiting/reading from master # SHOW SLAVE STATUS will show "Waiting for master to send event" -let $status_items= Master_SSL_Allowed, Master_SSL_CA_Path, Master_SSL_CA_File, Master_SSL_Cert, Master_SSL_Key; +let $status_items= Master_SSL_Allowed, Master_SSL_CA_Path, Master_SSL_CA_File, Master_SSL_Crl, Master_SSL_Crlpath, Master_SSL_Cert, Master_SSL_Key; source include/show_slave_status.inc; source include/check_slave_is_running.inc; diff --git a/mysql-test/suite/binlog_encryption/rpl_ssl.result b/mysql-test/suite/binlog_encryption/rpl_ssl.result index 0b3a6cd0eca..ce9e4d486cf 100644 --- a/mysql-test/suite/binlog_encryption/rpl_ssl.result +++ b/mysql-test/suite/binlog_encryption/rpl_ssl.result @@ -23,6 +23,8 @@ t Master_SSL_Allowed = 'Yes' Master_SSL_CA_Path = '' Master_SSL_CA_File = 'MYSQL_TEST_DIR/std_data/cacert.pem' +Master_SSL_Crl = '' +Master_SSL_Crlpath = '' Master_SSL_Cert = 'MYSQL_TEST_DIR/std_data/client-cert.pem' Master_SSL_Key = 'MYSQL_TEST_DIR/std_data/client-key.pem' include/check_slave_is_running.inc @@ -37,6 +39,8 @@ include/wait_for_slave_to_start.inc Master_SSL_Allowed = 'Yes' Master_SSL_CA_Path = '' Master_SSL_CA_File = 'MYSQL_TEST_DIR/std_data/cacert.pem' +Master_SSL_Crl = '' +Master_SSL_Crlpath = '' Master_SSL_Cert = 'MYSQL_TEST_DIR/std_data/client-cert.pem' Master_SSL_Key = 'MYSQL_TEST_DIR/std_data/client-key.pem' include/check_slave_is_running.inc diff --git a/mysql-test/suite/rpl/r/rpl_ssl.result b/mysql-test/suite/rpl/r/rpl_ssl.result index 0b3a6cd0eca..ce9e4d486cf 100644 --- a/mysql-test/suite/rpl/r/rpl_ssl.result +++ b/mysql-test/suite/rpl/r/rpl_ssl.result @@ -23,6 +23,8 @@ t Master_SSL_Allowed = 'Yes' Master_SSL_CA_Path = '' Master_SSL_CA_File = 'MYSQL_TEST_DIR/std_data/cacert.pem' +Master_SSL_Crl = '' +Master_SSL_Crlpath = '' Master_SSL_Cert = 'MYSQL_TEST_DIR/std_data/client-cert.pem' Master_SSL_Key = 'MYSQL_TEST_DIR/std_data/client-key.pem' include/check_slave_is_running.inc @@ -37,6 +39,8 @@ include/wait_for_slave_to_start.inc Master_SSL_Allowed = 'Yes' Master_SSL_CA_Path = '' Master_SSL_CA_File = 'MYSQL_TEST_DIR/std_data/cacert.pem' +Master_SSL_Crl = '' +Master_SSL_Crlpath = '' Master_SSL_Cert = 'MYSQL_TEST_DIR/std_data/client-cert.pem' Master_SSL_Key = 'MYSQL_TEST_DIR/std_data/client-key.pem' include/check_slave_is_running.inc diff --git a/sql/slave.cc b/sql/slave.cc index 80b1137d90e..ca3397e5e7b 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2914,9 +2914,9 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, protocol->store((uint32) mi->master_id); // SQL_Delay // Master_Ssl_Crl - protocol->store(mi->ssl_ca, &my_charset_bin); + protocol->store(mi->ssl_crl, &my_charset_bin); // Master_Ssl_Crlpath - protocol->store(mi->ssl_capath, &my_charset_bin); + protocol->store(mi->ssl_crlpath, &my_charset_bin); // Using_Gtid protocol->store(mi->using_gtid_astext(mi->using_gtid), &my_charset_bin); // Gtid_IO_Pos @@ -3004,7 +3004,7 @@ bool show_all_master_info(THD* thd) String gtid_pos; Master_info **tmp; List field_list; - DBUG_ENTER("show_master_info"); + DBUG_ENTER("show_all_master_info"); mysql_mutex_assert_owner(&LOCK_active_mi); gtid_pos.length(0); From f354e457e1c4171ce38cd3db3e492640db95036c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 27 Apr 2022 18:48:06 +0200 Subject: [PATCH 55/94] Bug#33578113: DROP privilege on performance_schema.* can't be revoked test case only --- mysql-test/r/grant.result | 10 ++++++++-- mysql-test/t/grant.test | 18 +++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index bd24c5bf380..e4e4e2339e5 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -2,8 +2,6 @@ set GLOBAL sql_mode=""; set LOCAL sql_mode=""; SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; SET GLOBAL log_bin_trust_function_creators = 1; -drop table if exists t1; -drop database if exists mysqltest; connect master,localhost,root,,; connection master; SET NAMES binary; @@ -2785,5 +2783,13 @@ DROP USER foo; DROP TABLE db.t; DROP DATABASE db; # +# Bug#33578113: DROP privilege on performance_schema.* can't be revoked +# +connection default; +CREATE USER bug33578113; +GRANT DROP ON performance_schema.* TO bug33578113; +REVOKE DROP ON performance_schema.* FROM bug33578113; +DROP USER bug33578113; +# # End of 10.2 tests # diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index fa3a690a2ee..5f862db1f35 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1,7 +1,7 @@ # Test of GRANT commands # Grant tests not performed with embedded server --- source include/not_embedded.inc +--source include/not_embedded.inc # Save the initial number of concurrent sessions --source include/count_sessions.inc @@ -11,12 +11,6 @@ set LOCAL sql_mode=""; SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; SET GLOBAL log_bin_trust_function_creators = 1; -# Cleanup ---disable_warnings -drop table if exists t1; -drop database if exists mysqltest; ---enable_warnings - connect (master,localhost,root,,); connection master; SET NAMES binary; @@ -2292,6 +2286,16 @@ DROP USER foo; DROP TABLE db.t; DROP DATABASE db; +--echo # +--echo # Bug#33578113: DROP privilege on performance_schema.* can't be revoked +--echo # +connection default; +CREATE USER bug33578113; +GRANT DROP ON performance_schema.* TO bug33578113; +REVOKE DROP ON performance_schema.* FROM bug33578113; +DROP USER bug33578113; +--source include/wait_until_count_sessions.inc + --echo # --echo # End of 10.2 tests --echo # From 7215b0035435c15362bd94d169943eaad851d7dc Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 28 Apr 2022 09:58:20 +0400 Subject: [PATCH 56/94] MDEV-28431 auth_pam tool left zombie processes. The faulure in username packet reading can lead to the auth_plugin_tool zombie. So check and close the application. --- plugin/auth_pam/auth_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index 3f3a49bf55d..d232b3b5c65 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -102,7 +102,7 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) if (info->user_name == 0) { if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) - return CR_ERROR; + goto error_ret; } else pkt= NULL; From ea2f09979fc74a8fa7fb1e74c874e00df757c6db Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Sun, 24 Apr 2022 00:28:54 +0300 Subject: [PATCH 57/94] MDEV-28271 Assertion on TRUNCATE PARTITION for PARTITION BY SYSTEM_TIME Like in MDEV-27217 vers_set_hist_part() for LIMIT depends on all partitions selected in read_partitions. That bugfix just disabled partition selection for DELETE with this check: if (table->pos_in_table_list && table->pos_in_table_list->partition_names) { return HA_ERR_PARTITION_LIST; } ALTER TABLE TRUNCATE PARTITION is a different story. First, it doesn't update pos_in_table_list->partition_names, but thd->lex->alter_info.partition_names. But we cannot depend on that since alter_info will be stale for DML. Second, we should not disable TRUNCATE PARTITION for that to be consistent with TRUNCATE TABLE behavior. Now we don't do vers_set_hist_part() for ALTER TABLE as this command is not DML, so it does not produce history. --- .../suite/versioning/r/partition.result | 72 +++++++++++++++++++ mysql-test/suite/versioning/t/partition.test | 60 ++++++++++++++++ sql/ha_partition.cc | 1 + 3 files changed, 133 insertions(+) diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index 70416360697..cada225db7e 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -839,5 +839,77 @@ p0 10 p1 0 pn 90 drop table t1; +# +# MDEV-28271 Assertion on TRUNCATE PARTITION for PARTITION BY SYSTEM_TIME +# +create table t1 (x int) with system versioning +partition by system_time limit 1 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 values (0); +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +select * from t1 partition (p0); +x +0 +1 +select * from t1 partition (p1); +x +2 +3 +select * from t1 partition (pn); +x +4 +# TRUNCATE TABLE deletes history and current data +truncate table t1; +select * from t1 partition (p0); +x +select * from t1 partition (p1); +x +select * from t1 partition (pn); +x +insert into t1 values (0); +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +# TRUNCATE PARTITION ALL does the same +alter table t1 truncate partition all; +select * from t1 partition (p0); +x +select * from t1 partition (p1); +x +select * from t1 partition (pn); +x +insert into t1 values (0); +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +# TRUNCATE PARTITION deletes data from HISTORY partition +alter table t1 truncate partition p1; +select * from t1 partition (p0); +x +0 +1 +select * from t1 partition (p1); +x +select * from t1 partition (pn); +x +4 +# or from CURRENT partition +alter table t1 truncate partition pn; +select * from t1 partition (p0); +x +0 +1 +select * from t1 partition (p1); +x +select * from t1 partition (pn); +x +drop table t1; # End of 10.3 tests set global innodb_stats_persistent= @save_persistent; diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index a687cd9b09f..7f75f905254 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -822,6 +822,66 @@ from information_schema.partitions where table_name = 't1'; # Cleanup drop table t1; + +--echo # +--echo # MDEV-28271 Assertion on TRUNCATE PARTITION for PARTITION BY SYSTEM_TIME +--echo # +create table t1 (x int) with system versioning +partition by system_time limit 1 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 values (0); +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; + +select * from t1 partition (p0); +select * from t1 partition (p1); +select * from t1 partition (pn); + +--echo # TRUNCATE TABLE deletes history and current data +--disable_warnings +truncate table t1; +--enable_warnings +select * from t1 partition (p0); +select * from t1 partition (p1); +select * from t1 partition (pn); + +insert into t1 values (0); +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; + +--echo # TRUNCATE PARTITION ALL does the same +alter table t1 truncate partition all; +select * from t1 partition (p0); +select * from t1 partition (p1); +select * from t1 partition (pn); + +insert into t1 values (0); +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; + +--echo # TRUNCATE PARTITION deletes data from HISTORY partition +alter table t1 truncate partition p1; +select * from t1 partition (p0); +select * from t1 partition (p1); +select * from t1 partition (pn); + +--echo # or from CURRENT partition +alter table t1 truncate partition pn; +select * from t1 partition (p0); +select * from t1 partition (p1); +select * from t1 partition (pn); + +drop table t1; + --echo # End of 10.3 tests set global innodb_stats_persistent= @save_persistent; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b4bb3e7e61e..b1645a9c4a7 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4034,6 +4034,7 @@ int ha_partition::external_lock(THD *thd, int lock_type) only for versioned DML. */ thd->lex->sql_command != SQLCOM_SELECT && thd->lex->sql_command != SQLCOM_INSERT_SELECT && + thd->lex->sql_command != SQLCOM_ALTER_TABLE && (error= m_part_info->vers_set_hist_part(thd))) goto err_handler; } From ddc416c60698e1f8939faff0cb09c5b5af8e03a7 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 25 Apr 2022 13:58:41 +0300 Subject: [PATCH 58/94] MDEV-20077 Warning on full history partition is delayed until next DML statement Moved LIMIT warning from vers_set_hist_part() to new call vers_check_limit() at table unlock phase. At that point read_partitions bitmap is already pruned by DML code (see prune_partitions(), find_used_partitions()) so we have to set corresponding bits for working history partition. Also we don't do my_error(ME_WARNING|ME_ERROR_LOG), because at that point it doesn't update warnings number, so command reports 0 warnings (but warning list is still updated). Instead we do push_warning_printf() and sql_print_warning() separately. Under LOCK TABLES external_lock(F_UNLCK) is not executed. There is start_stmt(), but no corresponding "stop_stmt()". So for that mode we call vers_check_limit() directly from close_thread_tables(). Test result has been changed according to new LIMIT and warning printing algorithm. For convenience all LIMIT warnings are marked with "You see warning above ^". TODO MDEV-20345 fixed. Now vers_history_generating() contains fine-grained list of DML-commands that can generate history (and TODO mechanism worked well). --- .../suite/versioning/r/delete_history.result | 3 + .../suite/versioning/r/partition.result | 258 ++++++++++++++++-- .../suite/versioning/t/delete_history.test | 1 + mysql-test/suite/versioning/t/partition.test | 214 ++++++++++++++- sql/ha_partition.cc | 17 +- sql/partition_info.cc | 53 +++- sql/partition_info.h | 6 + sql/sql_base.cc | 5 + sql/sql_lex.h | 22 ++ 9 files changed, 530 insertions(+), 49 deletions(-) diff --git a/mysql-test/suite/versioning/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result index 95d7304c3dd..065b1f00876 100644 --- a/mysql-test/suite/versioning/r/delete_history.result +++ b/mysql-test/suite/versioning/r/delete_history.result @@ -65,6 +65,9 @@ partition pn current); insert into t values (1); update t set a= 2; update t set a= 3; +Warnings: +Warning 4114 Versioned table `test`.`t`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ delete history from t; select * from t for system_time all; a diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index cada225db7e..a5bc8284f8c 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -244,6 +244,9 @@ x 6 delete from t1 where x < 4; delete from t1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ select * from t1 partition (p0); x 1 @@ -255,12 +258,11 @@ x 5 6 insert into t1 values (7), (8); -Warnings: -Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions ### warn about full partition delete from t1; Warnings: Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ select * from t1 partition (p1) order by x; x 4 @@ -320,20 +322,26 @@ x ### warn about full partition delete from t1 where x < 3; delete from t1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ delete from t1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ (no matter if nothing was deleted) select * from t1 partition (p0sp0); x 1 -3 -5 select * from t1 partition (p0sp1); x 2 -4 select * from t1 partition (p1sp0); x +3 +5 select * from t1 partition (p1sp1); x +4 create or replace table t1 ( a bigint, row_start SYS_DATATYPE as row start invisible, @@ -415,7 +423,13 @@ partition p1 history, partition p2 history, partition pn current); delete from t1 where x = 1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p2` is full, add more HISTORY partitions +# You see warning above ^ delete from t1 where x = 2; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p2` is full, add more HISTORY partitions +# You see warning above ^ # MDEV-14923 Assertion upon INSERT into locked versioned partitioned table create or replace table t1 (x int) with system versioning partition by system_time (partition p1 history, partition pn current); @@ -577,9 +591,13 @@ create or replace table t1 (x int) with system versioning partition by system_ti lock tables t1 write; insert into t1 values (0), (1), (2), (3); delete from t1 where x < 3; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ delete from t1; Warnings: Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ unlock tables; # # MDEV-20336 Assertion bitmap_is_set(read_partitions) upon SELECT FOR UPDATE from versioned table @@ -680,6 +698,9 @@ partition by system_time limit 1 insert into t1 values (null); update t1 set f= 'foo'; update t1 set f= 'bar'; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p2` is full, add more HISTORY partitions +# You see warning above ^ create or replace view v1 as select * from t1 for system_time all; update v1 set f= ''; ERROR HY000: Table 't1' was locked with a READ lock and can't be updated @@ -846,23 +867,20 @@ create table t1 (x int) with system versioning partition by system_time limit 1 ( partition p0 history, partition p1 history, +partition p2 history, # p2 just disables warning about p1 partition full partition pn current); insert into t1 values (0); update t1 set x= x + 1; update t1 set x= x + 1; -update t1 set x= x + 1; -update t1 set x= x + 1; select * from t1 partition (p0); x 0 -1 select * from t1 partition (p1); x -2 -3 +1 select * from t1 partition (pn); x -4 +2 # TRUNCATE TABLE deletes history and current data truncate table t1; select * from t1 partition (p0); @@ -874,8 +892,6 @@ x insert into t1 values (0); update t1 set x= x + 1; update t1 set x= x + 1; -update t1 set x= x + 1; -update t1 set x= x + 1; # TRUNCATE PARTITION ALL does the same alter table t1 truncate partition all; select * from t1 partition (p0); @@ -887,29 +903,235 @@ x insert into t1 values (0); update t1 set x= x + 1; update t1 set x= x + 1; -update t1 set x= x + 1; -update t1 set x= x + 1; # TRUNCATE PARTITION deletes data from HISTORY partition alter table t1 truncate partition p1; select * from t1 partition (p0); x 0 -1 select * from t1 partition (p1); x select * from t1 partition (pn); x -4 +2 # or from CURRENT partition alter table t1 truncate partition pn; select * from t1 partition (p0); x 0 -1 select * from t1 partition (p1); x select * from t1 partition (pn); x drop table t1; +# +# MDEV-20077 Warning on full history partition is delayed until next DML statement +# +# DELETE +create table t1 (x int) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_0_to_200; +# p0 is filled with 100 records (no warnings): +delete from t1 where x <= 99; +# p1 is filled with 1 + 100 records (warning is printed): +delete from t1 where x <= 100; +delete from t1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +101 +drop table t1; +# DELETE under LOCK TABLES +create table t1 (x int) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_0_to_200; +lock tables t1 write; +# (LOCK TABLES) p0 is filled with 100 records (no warnings): +delete from t1 where x <= 99; +# (LOCK TABLES) p1 is filled with 1 + 100 records (warning is printed): +delete from t1 where x <= 100; +delete from t1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ +unlock tables; +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +101 +drop table t1; +# DELETE multitable +create table t1 (x int) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +create table t2 (y int); +insert into t1 select seq from seq_0_to_200; +insert into t2 select seq from seq_0_to_3; +delete t1, t2 from t1 join t2 where x < 50 and y = 0; +delete t1, t2 from t1 join t2 where x < 100 and y = 1; +delete t1, t2 from t1 join t2 where x < 150 and y = 2; +delete t1, t2 from t1 join t2; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +101 +drop table t1; +# UDPATE +create table t1 (x int) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_0_to_49; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +100 +drop tables t1, t2; +# UPDATE multitable +create table t1 (x int) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +create table t2 (y int); +insert into t1 select seq from seq_0_to_49; +insert into t2 values (5); +update t1, t2 set x= x + 1; +update t1, t2 set x= x + 1; +update t1, t2 set x= x + 1; +update t1, t2 set x= x + 1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +100 +drop tables t1, t2; +# INSERT .. ON DUPLICATE KEY UPDATE (ODKU) +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_0_to_100; +delete from t1 where x <= 99; +insert into t1 values (100) on duplicate key update x= 400; +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +1 +drop table t1; +# INSERT .. SELECT .. ON DUPLICATE KEY UPDATE (ODKU) +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +create table t2 (y int); +insert into t2 values (100); +insert into t1 select seq from seq_0_to_100; +delete from t1 where x <= 99; +insert into t1 select * from t2 on duplicate key update x= 500; +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +1 +drop tables t1, t2; +# REPLACE +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_0_to_100; +delete from t1 where x < 99; +replace t1 values (100); +replace t1 values (100); +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +1 +drop table t1; +# LOAD DATA .. REPLACE +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_0_to_49; +select x into outfile 'MDEV-20077.data' from t1; +load data infile 'MDEV-20077.data' replace into table t1 (x); +load data infile 'MDEV-20077.data' replace into table t1 (x); +load data infile 'MDEV-20077.data' replace into table t1 (x); +load data infile 'MDEV-20077.data' replace into table t1 (x); +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +100 +drop table t1; +# REPLACE .. SELECT +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( +partition p0 history, +partition p1 history, +partition pn current); +insert into t1 select seq from seq_0_to_49; +replace t1 select * from t1; +replace t1 select * from t1; +replace t1 select * from t1; +replace t1 select * from t1; +Warnings: +Warning 4114 Versioned table `test`.`t1`: partition `p1` is full, add more HISTORY partitions +# You see warning above ^ +select count(*) from t1 partition (p0); +count(*) +100 +select count(*) from t1 partition (p1); +count(*) +100 +drop table t1; # End of 10.3 tests set global innodb_stats_persistent= @save_persistent; diff --git a/mysql-test/suite/versioning/t/delete_history.test b/mysql-test/suite/versioning/t/delete_history.test index bd605c689ad..dae7ff2db9b 100644 --- a/mysql-test/suite/versioning/t/delete_history.test +++ b/mysql-test/suite/versioning/t/delete_history.test @@ -65,6 +65,7 @@ partition by system_time limit 1 ( insert into t values (1); update t set a= 2; update t set a= 3; +--echo # You see warning above ^ delete history from t; select * from t for system_time all; diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index 7f75f905254..f65f544147f 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -228,12 +228,14 @@ insert into t1 values (1), (2), (3), (4), (5), (6); select * from t1 partition (pn); delete from t1 where x < 4; delete from t1; +--echo # You see warning above ^ select * from t1 partition (p0); select * from t1 partition (p1); insert into t1 values (7), (8); --echo ### warn about full partition delete from t1; +--echo # You see warning above ^ select * from t1 partition (p1) order by x; --echo ### Assertion in ALTER on warning from partitioning LIMIT [#446] @@ -283,7 +285,9 @@ select * from t1 partition (pnsp1); --echo ### warn about full partition delete from t1 where x < 3; delete from t1; +--echo # You see warning above ^ delete from t1; +--echo # You see warning above ^ (no matter if nothing was deleted) select * from t1 partition (p0sp0); select * from t1 partition (p0sp1); select * from t1 partition (p1sp0); @@ -381,7 +385,9 @@ alter table t1 partition by system_time limit 1 ( partition p2 history, partition pn current); delete from t1 where x = 1; +--echo # You see warning above ^ delete from t1 where x = 2; +--echo # You see warning above ^ --echo # MDEV-14923 Assertion upon INSERT into locked versioned partitioned table create or replace table t1 (x int) with system versioning @@ -529,7 +535,9 @@ create or replace table t1 (x int) with system versioning partition by system_ti lock tables t1 write; insert into t1 values (0), (1), (2), (3); delete from t1 where x < 3; +--echo # You see warning above ^ delete from t1; +--echo # You see warning above ^ unlock tables; --echo # @@ -640,6 +648,7 @@ partition by system_time limit 1 insert into t1 values (null); update t1 set f= 'foo'; update t1 set f= 'bar'; +--echo # You see warning above ^ create or replace view v1 as select * from t1 for system_time all; --error ER_TABLE_NOT_LOCKED_FOR_WRITE @@ -830,22 +839,19 @@ create table t1 (x int) with system versioning partition by system_time limit 1 ( partition p0 history, partition p1 history, + partition p2 history, # p2 just disables warning about p1 partition full partition pn current); insert into t1 values (0); update t1 set x= x + 1; update t1 set x= x + 1; -update t1 set x= x + 1; -update t1 set x= x + 1; select * from t1 partition (p0); select * from t1 partition (p1); select * from t1 partition (pn); --echo # TRUNCATE TABLE deletes history and current data ---disable_warnings truncate table t1; ---enable_warnings select * from t1 partition (p0); select * from t1 partition (p1); select * from t1 partition (pn); @@ -853,8 +859,6 @@ select * from t1 partition (pn); insert into t1 values (0); update t1 set x= x + 1; update t1 set x= x + 1; -update t1 set x= x + 1; -update t1 set x= x + 1; --echo # TRUNCATE PARTITION ALL does the same alter table t1 truncate partition all; @@ -865,8 +869,6 @@ select * from t1 partition (pn); insert into t1 values (0); update t1 set x= x + 1; update t1 set x= x + 1; -update t1 set x= x + 1; -update t1 set x= x + 1; --echo # TRUNCATE PARTITION deletes data from HISTORY partition alter table t1 truncate partition p1; @@ -882,6 +884,202 @@ select * from t1 partition (pn); drop table t1; +--echo # +--echo # MDEV-20077 Warning on full history partition is delayed until next DML statement +--echo # +--echo # DELETE +create table t1 (x int) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 select seq from seq_0_to_200; + +--echo # p0 is filled with 100 records (no warnings): +delete from t1 where x <= 99; +--echo # p1 is filled with 1 + 100 records (warning is printed): +delete from t1 where x <= 100; +delete from t1; +--echo # You see warning above ^ + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop table t1; + +--echo # DELETE under LOCK TABLES +create table t1 (x int) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 select seq from seq_0_to_200; + +lock tables t1 write; +--echo # (LOCK TABLES) p0 is filled with 100 records (no warnings): +delete from t1 where x <= 99; +--echo # (LOCK TABLES) p1 is filled with 1 + 100 records (warning is printed): +delete from t1 where x <= 100; +delete from t1; +--echo # You see warning above ^ +unlock tables; + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop table t1; + +--echo # DELETE multitable +create table t1 (x int) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +create table t2 (y int); + +insert into t1 select seq from seq_0_to_200; +insert into t2 select seq from seq_0_to_3; +delete t1, t2 from t1 join t2 where x < 50 and y = 0; +delete t1, t2 from t1 join t2 where x < 100 and y = 1; +delete t1, t2 from t1 join t2 where x < 150 and y = 2; +delete t1, t2 from t1 join t2; +--echo # You see warning above ^ + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop table t1; + +--echo # UDPATE +create table t1 (x int) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 select seq from seq_0_to_49; + +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +update t1 set x= x + 1; +--echo # You see warning above ^ + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop tables t1, t2; + +--echo # UPDATE multitable +create table t1 (x int) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +create table t2 (y int); + +insert into t1 select seq from seq_0_to_49; +insert into t2 values (5); + +update t1, t2 set x= x + 1; +update t1, t2 set x= x + 1; +update t1, t2 set x= x + 1; +update t1, t2 set x= x + 1; +--echo # You see warning above ^ + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop tables t1, t2; + +--echo # INSERT .. ON DUPLICATE KEY UPDATE (ODKU) +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 select seq from seq_0_to_100; + +delete from t1 where x <= 99; +insert into t1 values (100) on duplicate key update x= 400; + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop table t1; + +--echo # INSERT .. SELECT .. ON DUPLICATE KEY UPDATE (ODKU) +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +create table t2 (y int); +insert into t2 values (100); +insert into t1 select seq from seq_0_to_100; + +delete from t1 where x <= 99; +insert into t1 select * from t2 on duplicate key update x= 500; + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop tables t1, t2; + +--echo # REPLACE +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 select seq from seq_0_to_100; + +delete from t1 where x < 99; +replace t1 values (100); +replace t1 values (100); + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop table t1; + +--echo # LOAD DATA .. REPLACE +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 select seq from seq_0_to_49; +select x into outfile 'MDEV-20077.data' from t1; + +load data infile 'MDEV-20077.data' replace into table t1 (x); +load data infile 'MDEV-20077.data' replace into table t1 (x); +load data infile 'MDEV-20077.data' replace into table t1 (x); +load data infile 'MDEV-20077.data' replace into table t1 (x); +--echo # You see warning above ^ + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop table t1; +--remove_file $datadir/test/MDEV-20077.data + +--echo # REPLACE .. SELECT +create table t1 (x int primary key) with system versioning +partition by system_time limit 100 ( + partition p0 history, + partition p1 history, + partition pn current); + +insert into t1 select seq from seq_0_to_49; +replace t1 select * from t1; +replace t1 select * from t1; +replace t1 select * from t1; +replace t1 select * from t1; +--echo # You see warning above ^ + +select count(*) from t1 partition (p0); +select count(*) from t1 partition (p1); +drop table t1; --echo # End of 10.3 tests set global innodb_stats_persistent= @save_persistent; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b1645a9c4a7..48c479070a5 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4008,6 +4008,8 @@ int ha_partition::external_lock(THD *thd, int lock_type) if (lock_type == F_UNLCK) { bitmap_clear_all(used_partitions); + if (m_lock_type == F_WRLCK && m_part_info->vers_require_hist_part(thd)) + m_part_info->vers_check_limit(thd); } else { @@ -4028,14 +4030,7 @@ int ha_partition::external_lock(THD *thd, int lock_type) { if (m_part_info->part_expr) m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0); - if (m_part_info->part_type == VERSIONING_PARTITION && - /* TODO: MDEV-20345 exclude more inapproriate commands like INSERT - These commands may be excluded because working history partition is needed - only for versioned DML. */ - thd->lex->sql_command != SQLCOM_SELECT && - thd->lex->sql_command != SQLCOM_INSERT_SELECT && - thd->lex->sql_command != SQLCOM_ALTER_TABLE && - (error= m_part_info->vers_set_hist_part(thd))) + if ((error= m_part_info->vers_set_hist_part(thd))) goto err_handler; } DBUG_RETURN(0); @@ -4188,11 +4183,7 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type) case TL_WRITE_ONLY: if (m_part_info->part_expr) m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0); - if (m_part_info->part_type == VERSIONING_PARTITION && - // TODO: MDEV-20345 (see above) - thd->lex->sql_command != SQLCOM_SELECT && - thd->lex->sql_command != SQLCOM_INSERT_SELECT) - error= m_part_info->vers_set_hist_part(thd); + error= m_part_info->vers_set_hist_part(thd); default:; } DBUG_RETURN(error); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index f523415f6cc..90ef388f3b9 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -835,6 +835,9 @@ bool partition_info::has_unique_name(partition_element *element) int partition_info::vers_set_hist_part(THD *thd) { + if (!vers_require_hist_part(thd)) + return 0; + if (table->pos_in_table_list && table->pos_in_table_list->partition_names) { @@ -856,12 +859,8 @@ int partition_info::vers_set_hist_part(THD *thd) vers_info->hist_part= next; records= next_records; } - if (records > vers_info->limit) - { - if (next == vers_info->now_part) - goto warn; + if (records >= vers_info->limit && next != vers_info->now_part) vers_info->hist_part= next; - } return 0; } @@ -883,11 +882,45 @@ int partition_info::vers_set_hist_part(THD *thd) } } return 0; -warn: - my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG), - table->s->db.str, table->s->table_name.str, - vers_info->hist_part->partition_name); - return 0; +} + + +/** + Warn at the end of DML command if the last history partition is out of LIMIT. +*/ +void partition_info::vers_check_limit(THD *thd) +{ + if (!vers_info->limit || + vers_info->hist_part->id + 1 < vers_info->now_part->id) + return; + + /* + NOTE: at this point read_partitions bitmap is already pruned by DML code, + we have to set read bits for working history partition. We could use + bitmap_set_all(), but this is not optimal since there can be quite a number + of partitions. + */ + const uint32 sub_factor= num_subparts ? num_subparts : 1; + uint32 part_id= vers_info->hist_part->id * sub_factor; + const uint32 part_id_end= part_id + sub_factor; + DBUG_ASSERT(part_id_end <= num_parts * sub_factor); + for (; part_id < part_id_end; ++part_id) + bitmap_set_bit(&read_partitions, part_id); + + ha_partition *hp= (ha_partition*)(table->file); + ha_rows hist_rows= hp->part_records(vers_info->hist_part); + if (hist_rows >= vers_info->limit) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + WARN_VERS_PART_FULL, + ER_THD(thd, WARN_VERS_PART_FULL), + table->s->db.str, table->s->table_name.str, + vers_info->hist_part->partition_name); + + sql_print_warning(ER_THD(thd, WARN_VERS_PART_FULL), + table->s->db.str, table->s->table_name.str, + vers_info->hist_part->partition_name); + } } diff --git a/sql/partition_info.h b/sql/partition_info.h index 341ae363c7f..ddbb89fa605 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -421,7 +421,13 @@ public: vers_info->limit= limit; return !limit; } + bool vers_require_hist_part(THD *thd) const + { + return part_type == VERSIONING_PARTITION && + thd->lex->vers_history_generating(); + } int vers_set_hist_part(THD *thd); + void vers_check_limit(THD *thd); bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */ partition_element *get_partition(uint part_id) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f12ba831c7d..88eaf1bc0a5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -750,7 +750,12 @@ void close_thread_tables(THD *thd) DBUG_PRINT("tcache", ("table: '%s' query_id: %lu", table->s->table_name.str, (ulong) table->query_id)); if (thd->locked_tables_mode) + { + if (table->part_info && table->part_info->vers_require_hist_part(thd) && + !thd->stmt_arena->is_stmt_prepare()) + table->part_info->vers_check_limit(thd); table->vcol_cleanup_expr(thd); + } if (thd->locked_tables_mode <= LTM_LOCK_TABLES || table->query_id == thd->query_id) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b5cc9604a8f..bd7bd2f248c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -4084,6 +4084,28 @@ public: { return create_info.vers_info; } + /* The list of history-generating DML commands */ + bool vers_history_generating() const + { + switch (sql_command) + { + case SQLCOM_DELETE: + return !vers_conditions.delete_history; + case SQLCOM_UPDATE: + case SQLCOM_UPDATE_MULTI: + case SQLCOM_DELETE_MULTI: + case SQLCOM_REPLACE: + case SQLCOM_REPLACE_SELECT: + return true; + case SQLCOM_INSERT: + case SQLCOM_INSERT_SELECT: + return duplicates == DUP_UPDATE; + case SQLCOM_LOAD: + return duplicates == DUP_REPLACE; + default: + return false; + } + } sp_package *get_sp_package() const; /** From 182b8a29e7a1a0f0fbffeed39518c2c9dc026e13 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Fri, 29 Apr 2022 17:36:48 +0300 Subject: [PATCH 59/94] MDEV-20077 compilation fix --- sql/sql_base.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 88eaf1bc0a5..e825c247fc1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -751,9 +751,11 @@ void close_thread_tables(THD *thd) table->s->table_name.str, (ulong) table->query_id)); if (thd->locked_tables_mode) { +#ifdef WITH_PARTITION_STORAGE_ENGINE if (table->part_info && table->part_info->vers_require_hist_part(thd) && !thd->stmt_arena->is_stmt_prepare()) table->part_info->vers_check_limit(thd); +#endif table->vcol_cleanup_expr(thd); } if (thd->locked_tables_mode <= LTM_LOCK_TABLES || From bc9102eb811cc39a76b04cab316bbdcceaa16026 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 28 Apr 2022 16:59:50 +0200 Subject: [PATCH 60/94] cleanup: (*order->item) -> item and minor style fixes --- mysql-test/main/having.result | 5 ++++- mysql-test/main/having.test | 25 ++++++++++++------------- mysql-test/main/subselect_innodb.result | 11 ++++++++--- mysql-test/main/subselect_innodb.test | 17 ++++++++--------- sql/item.cc | 6 ++---- sql/sql_base.cc | 2 +- sql/sql_select.cc | 20 +++++++++----------- 7 files changed, 44 insertions(+), 42 deletions(-) diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result index 51b88c5b8d2..8800402dc35 100644 --- a/mysql-test/main/having.result +++ b/mysql-test/main/having.result @@ -1,4 +1,3 @@ -drop table if exists t1,t2,t3; create table t1 (a int); select count(a) as b from t1 where a=0 having b > 0; b @@ -880,8 +879,10 @@ h # # drop table t1; +# # End of 10.3 tests # +# # MDEV-18681: AND formula in HAVING with several occurances # of the same field f in different conjuncts + f=constant # @@ -906,4 +907,6 @@ INSERT INTO t VALUES ('a'),('b'); SELECT * FROM t HAVING f = 'foo'; f DROP TABLE t; +# # End of 10.4 tests +# diff --git a/mysql-test/main/having.test b/mysql-test/main/having.test index 7e0a0439f8e..b3b128684a3 100644 --- a/mysql-test/main/having.test +++ b/mysql-test/main/having.test @@ -1,10 +1,6 @@ # test of problems with having (Reported by Mark Rogers) # ---disable_warnings -drop table if exists t1,t2,t3; ---enable_warnings - create table t1 (a int); select count(a) as b from t1 where a=0 having b > 0; insert into t1 values (null); @@ -207,7 +203,7 @@ select count(*) from t1 group by col1 having col1 = 10; select count(*) as count_col1 from t1 group by col1 having col1 = 10; select count(*) as count_col1 from t1 as tmp1 group by col1 having col1 = 10; select count(*) from t1 group by col2 having col2 = 'hello'; ---error 1054 +--error ER_BAD_FIELD_ERROR select count(*) from t1 group by col2 having col1 = 10; select col1 as count_col1 from t1 as tmp1 group by col1 having col1 = 10; select col1 as count_col1 from t1 as tmp1 group by col1 having count_col1 = 10; @@ -221,10 +217,10 @@ select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col1 = select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having count_col1 = 10; select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col2 = 'hello'; select col1 as count_col1,col2 as group_col2 from t1 as tmp1 group by col1,col2 having group_col2 = 'hello'; ---error 1064 +--error ER_PARSE_ERROR select sum(col1) as co12 from t1 group by col2 having col2 10; select sum(col1) as co2, count(col2) as cc from t1 group by col1 having col1 =10; ---error 1054 +--error ER_BAD_FIELD_ERROR select t2.col2 from t2 group by t2.col1, t2.col2 having t1.col1 <= 10; @@ -273,7 +269,7 @@ having (select col_t1 from t2 where col_t1 = col_t2 order by col_t2 limit 1); # nested queries with HAVING, inner having column resolved in outer FROM clause # the outer having column is not referenced in GROUP BY which results in an error ---error 1054 +--error ER_BAD_FIELD_ERROR select t1.col1 from t1 where t1.col2 in (select t2.col2 from t2 @@ -302,7 +298,7 @@ having col_t1 > 10 and # correlated subqueries - inner having column 't1.col2' resolves to # the outer FROM clause, which cannot be used because the outer query # is grouped ---error 1054 +--error ER_BAD_FIELD_ERROR select sum(col1) from t1 group by col_t1 having col_t1 in (select sum(t2.col1) from t2 @@ -318,11 +314,11 @@ having col_t1 in (select sum(t2.col1) from t2 # # queries with joins and ambiguous column names # ---error 1052 +--error ER_NON_UNIQ_ERROR select t1.col1, t2.col1 from t1, t2 where t1.col1 = t2.col1 group by t1.col1, t2.col1 having col1 = 2; ---error 1052 +--error ER_NON_UNIQ_ERROR select t1.col1*10+t2.col1 from t1,t2 where t1.col1=t2.col1 group by t1.col1, t2.col1 having col1 = 2; @@ -352,7 +348,7 @@ select count(s1) from t1 group by s1 having count(1+1)=2; select count(s1) from t1 group by s1 having s1*0=0; --- error 1052 +-- error ER_NON_UNIQ_ERROR select * from t1 a, t1 b group by a.s1 having s1 is null; # ANSI requires: 0 rows # MySQL returns: @@ -912,7 +908,9 @@ alter table t1 add column b int default (rand()+1+3); select default(b) AS h FROM t1 HAVING h > "2"; drop table t1; +--echo # --echo # End of 10.3 tests +--echo # --echo # --echo # MDEV-18681: AND formula in HAVING with several occurances @@ -930,7 +928,6 @@ HAVING t.f != 112 AND t.f = 'x' AND t.f != 'a'; DROP TABLE t1,t2; - --echo # --echo # MDEV-20200: AddressSanitizer: use-after-poison in --echo # Item_direct_view_ref::get_null_ref_table @@ -943,4 +940,6 @@ SELECT * FROM t HAVING f = 'foo'; # Cleanup DROP TABLE t; +--echo # --echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result index f1e07ce09fe..ae22329f62a 100644 --- a/mysql-test/main/subselect_innodb.result +++ b/mysql-test/main/subselect_innodb.result @@ -1,6 +1,5 @@ set @subselect_innodb_tmp=@@optimizer_switch; set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; -drop table if exists t1,t2,t3; CREATE TABLE t1 ( FOLDERID VARCHAR(32)BINARY NOT NULL @@ -154,6 +153,9 @@ EXECUTE my_stmt; b count(*) deallocate prepare my_stmt; drop table t1,t2; +# +# End of 4.1 tests +# CREATE TABLE t1 ( school_name varchar(45) NOT NULL, country varchar(45) NOT NULL, @@ -287,7 +289,6 @@ LIMIT 10; col_time_key col_datetime_key DROP TABLE t1; DROP TABLE t2; -# End of Bug #58756 # # Bug#60085 crash in Item::save_in_field() with time data type # @@ -356,7 +357,9 @@ LIMIT 1; maxkey NULL DROP TABLE t1,t2; -End of 5.1 tests +# +# End of 5.1 tests +# # # lp:827416 Crash in select_describe() on EXPLAIN with DISTINCT in nested subqueries # @@ -663,4 +666,6 @@ a b execute stmt; a b drop table t1,t2; +# # End of 10.4 tests +# diff --git a/mysql-test/main/subselect_innodb.test b/mysql-test/main/subselect_innodb.test index 37f8f40200e..e767891c8db 100644 --- a/mysql-test/main/subselect_innodb.test +++ b/mysql-test/main/subselect_innodb.test @@ -4,9 +4,6 @@ # settings are not relevant. set @subselect_innodb_tmp=@@optimizer_switch; set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; ---disable_warnings -drop table if exists t1,t2,t3; ---enable_warnings # # key field overflow test @@ -164,7 +161,9 @@ EXECUTE my_stmt; deallocate prepare my_stmt; drop table t1,t2; -# End of 4.1 tests +--echo # +--echo # End of 4.1 tests +--echo # CREATE TABLE t1 ( school_name varchar(45) NOT NULL, @@ -289,8 +288,6 @@ LIMIT 10; DROP TABLE t1; DROP TABLE t2; ---echo # End of Bug #58756 - --echo # --echo # Bug#60085 crash in Item::save_in_field() with time data type --echo # @@ -354,7 +351,9 @@ eval $query; DROP TABLE t1,t2; ---echo End of 5.1 tests +--echo # +--echo # End of 5.1 tests +--echo # --echo # --echo # lp:827416 Crash in select_describe() on EXPLAIN with DISTINCT in nested subqueries @@ -507,8 +506,6 @@ drop table t1,t2; --echo # for a subquery from the expression used in ref access --echo # ---source include/have_innodb.inc - CREATE TABLE t1 (i1 INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1),(2); @@ -661,4 +658,6 @@ execute stmt; drop table t1,t2; +--echo # --echo # End of 10.4 tests +--echo # diff --git a/sql/item.cc b/sql/item.cc index 8b336334cc0..4c699bb974d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7874,8 +7874,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) else if (!ref || ref == not_found_item) { DBUG_ASSERT(reference_trough_name != 0); - if (!(ref= resolve_ref_in_select_and_group(thd, this, - context->select_lex))) + if (!(ref= resolve_ref_in_select_and_group(thd, this, context->select_lex))) goto error; /* Some error occurred (e.g. ambiguous names). */ if (ref == not_found_item) /* This reference was not resolved. */ @@ -7888,8 +7887,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) if (unlikely(!outer_context)) { /* The current reference cannot be resolved in this query. */ - my_error(ER_BAD_FIELD_ERROR,MYF(0), - this->full_name(), thd->where); + my_error(ER_BAD_FIELD_ERROR,MYF(0), full_name(), thd->where); goto error; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3ca18bd007d..14b97b43660 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8453,7 +8453,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List &leaves, select_lex->where= *conds; } thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; - DBUG_RETURN(MY_TEST(thd->is_error())); + DBUG_RETURN(thd->is_error()); err_no_arena: select_lex->is_item_list_lookup= save_is_item_list_lookup; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d0377838ef0..2b0977aca9f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24528,8 +24528,8 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, if (find_order_in_list(thd, ref_pointer_array, tables, order, fields, all_fields, false, true, from_window_spec)) return 1; - if ((*order->item)->with_window_func && - context_analysis_place != IN_ORDER_BY) + Item * const item= *order->item; + if (item->with_window_func && context_analysis_place != IN_ORDER_BY) { my_error(ER_WINDOW_FUNCTION_IN_WINDOW_SPEC, MYF(0)); return 1; @@ -24540,20 +24540,18 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, an ORDER BY clause */ - if (for_union && - ((*order->item)->with_sum_func() || - (*order->item)->with_window_func)) + if (for_union && (item->with_sum_func() || item->with_window_func)) { my_error(ER_AGGREGATE_ORDER_FOR_UNION, MYF(0), number); return 1; } - if (!(*order->item)->with_sum_func()) - continue; - - if (from_window_spec && (*order->item)->type() != Item::SUM_FUNC_ITEM) - (*order->item)->split_sum_func(thd, ref_pointer_array, - all_fields, SPLIT_SUM_SELECT); + if (from_window_spec && item->with_sum_func() && + item->type() != Item::SUM_FUNC_ITEM) + { + item->split_sum_func(thd, ref_pointer_array, + all_fields, SPLIT_SUM_SELECT); + } } return 0; } From 8c34eab9688b4face54f15f89f5d62bdfd93b8a7 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 28 Apr 2022 17:40:49 +0200 Subject: [PATCH 61/94] MDEV-28094 Window function in expression in ORDER BY call item->split_sum_func() in setup_order() just as it's done in setup_fields() --- mysql-test/main/win_sum.result | 12 ++++++++++++ mysql-test/main/win_sum.test | 13 +++++++++++++ sql/sql_select.cc | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/win_sum.result b/mysql-test/main/win_sum.result index 66a48fe8293..71d87bd6eca 100644 --- a/mysql-test/main/win_sum.result +++ b/mysql-test/main/win_sum.result @@ -93,3 +93,15 @@ pk a c sum(c) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FO 126 6 NULL NULL 127 6 NULL NULL drop table t1; +# +# End of 10.2 tests +# +# +# MDEV-28094 Window function in expression in ORDER BY +# +SELECT EXISTS (SELECT 1 ORDER BY 1+sum(2) OVER ()); +EXISTS (SELECT 1 ORDER BY 1+sum(2) OVER ()) +1 +# +# End of 10.4 tests +# diff --git a/mysql-test/main/win_sum.test b/mysql-test/main/win_sum.test index aa4965bfd5a..640576acc53 100644 --- a/mysql-test/main/win_sum.test +++ b/mysql-test/main/win_sum.test @@ -45,3 +45,16 @@ select pk, a, c, sum(c) over (partition by a order by pk ROWS BETWEEN 1 PRECEDIN from t1; drop table t1; + +--echo # +--echo # End of 10.2 tests +--echo # + +--echo # +--echo # MDEV-28094 Window function in expression in ORDER BY +--echo # +SELECT EXISTS (SELECT 1 ORDER BY 1+sum(2) OVER ()); + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2b0977aca9f..735e00dd091 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24546,8 +24546,8 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, return 1; } - if (from_window_spec && item->with_sum_func() && - item->type() != Item::SUM_FUNC_ITEM) + if ((from_window_spec && item->with_sum_func() && + item->type() != Item::SUM_FUNC_ITEM) || item->with_window_func) { item->split_sum_func(thd, ref_pointer_array, all_fields, SPLIT_SUM_SELECT); From 0beed9b5e933f0ff79b3bb346524f7a451d14e38 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 29 Apr 2022 14:50:47 +0200 Subject: [PATCH 62/94] MDEV-28097 use-after-free when WHERE has subquery with an outer reference in HAVING when resolving WHERE and ON clauses, do not look in SELECT list/aliases. --- mysql-test/main/having.result | 6 +----- mysql-test/main/having.test | 3 ++- mysql-test/main/subselect_innodb.result | 12 ++++++++++++ mysql-test/main/subselect_innodb.test | 8 ++++++++ sql/sql_base.cc | 3 +++ 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result index 8800402dc35..b4ca607ec84 100644 --- a/mysql-test/main/having.result +++ b/mysql-test/main/having.result @@ -279,11 +279,7 @@ select t1.col1 as tmp_col from t1 where t1.col2 in (select t2.col2 from t2 group by t2.col1, t2.col2 having tmp_col <= 10); -tmp_col -10 -10 -10 -10 +ERROR 42S22: Unknown column 'tmp_col' in 'having clause' select t1.col1 from t1 where t1.col2 in (select t2.col2 from t2 diff --git a/mysql-test/main/having.test b/mysql-test/main/having.test index b3b128684a3..3f4e8a8e710 100644 --- a/mysql-test/main/having.test +++ b/mysql-test/main/having.test @@ -249,7 +249,8 @@ where t1.col2 in group by t2.col1, t2.col2 having t1.col1 <= 10); # the having column is resolved in the SELECT clause of the outer query - -# error in ANSI, works with MySQL extension +# error in ANSI +--error ER_BAD_FIELD_ERROR select t1.col1 as tmp_col from t1 where t1.col2 in (select t2.col2 from t2 diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result index ae22329f62a..467ed218198 100644 --- a/mysql-test/main/subselect_innodb.result +++ b/mysql-test/main/subselect_innodb.result @@ -667,5 +667,17 @@ execute stmt; a b drop table t1,t2; # +# MDEV-28097 use-after-free when WHERE has subquery with an outer reference in HAVING +# +create table t1 (a text(60) not null) engine=innodb; +insert into t1 values ('1'),('0'); +select distinct a from t1 where '' in (select 'x' like a having a like a); +a +1 +0 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '' +drop table t1; +# # End of 10.4 tests # diff --git a/mysql-test/main/subselect_innodb.test b/mysql-test/main/subselect_innodb.test index e767891c8db..8ff3a5acf7d 100644 --- a/mysql-test/main/subselect_innodb.test +++ b/mysql-test/main/subselect_innodb.test @@ -658,6 +658,14 @@ execute stmt; drop table t1,t2; +--echo # +--echo # MDEV-28097 use-after-free when WHERE has subquery with an outer reference in HAVING +--echo # +create table t1 (a text(60) not null) engine=innodb; +insert into t1 values ('1'),('0'); +select distinct a from t1 where '' in (select 'x' like a having a like a); +drop table t1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 14b97b43660..ef7a075e304 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8398,9 +8398,11 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List &leaves, thd->lex->which_check_option_applicable(); bool save_is_item_list_lookup= select_lex->is_item_list_lookup; TABLE_LIST *derived= select_lex->master_unit()->derived; + bool save_resolve_in_select_list= select_lex->context.resolve_in_select_list; DBUG_ENTER("setup_conds"); select_lex->is_item_list_lookup= 0; + select_lex->context.resolve_in_select_list= false; thd->column_usage= MARK_COLUMNS_READ; DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage)); @@ -8453,6 +8455,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List &leaves, select_lex->where= *conds; } thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; + select_lex->context.resolve_in_select_list= save_resolve_in_select_list; DBUG_RETURN(thd->is_error()); err_no_arena: From c8228369f6dad5cfd17c5a9d9ea1c5c3ecd30fe7 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 29 Apr 2022 10:37:01 -0700 Subject: [PATCH 63/94] MDEV-28080 Crash when using HAVING with NOT EXIST predicate in an equality MDEV-28082 Crash when using HAVING with IS NULL predicate in an equality These bugs have been fixed by the patch for MDEV-26402. Only test cases are added. --- mysql-test/main/having_cond_pushdown.result | 31 +++++++++++++++++++ mysql-test/main/having_cond_pushdown.test | 33 +++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result index 9a9ed2b9213..ad8befb29d5 100644 --- a/mysql-test/main/having_cond_pushdown.result +++ b/mysql-test/main/having_cond_pushdown.result @@ -4939,3 +4939,34 @@ i Warnings: Warning 1292 Truncated incorrect DOUBLE value: 'x' DROP TABLE t1; +# +# MDEV-28080: HAVING with NOT EXIST predicate in an equality +# (fixed by the patch for MDEV-26402) +# +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (0), (1), (1), (0); +INSERT INTO t2 VALUES (3), (7); +SELECT a FROM t1 +GROUP BY a HAVING a= (NOT EXISTS (SELECT b FROM t2 WHERE b = 1)); +a +1 +SELECT a FROM t1 +GROUP BY a HAVING a= (NOT EXISTS (SELECT b FROM t2 WHERE b = 7)); +a +0 +DROP TABLE t1, t2; +# +# MDEV-28082: HAVING with IS NULL predicate in an equality +# (fixed by the patch for MDEV-26402) +# +CREATE TABLE t1 (a int, b int NOT NULL) ; +INSERT INTO t1 VALUES (1,10), (0,11), (0,11), (1,10); +SELECT a,b FROM t1 GROUP BY a HAVING a = (b IS NULL); +a b +0 11 +SELECT a,b FROM t1 GROUP BY a,b HAVING a = (b IS NULL); +a b +0 11 +DROP TABLE t1; +End of 10.4 tests diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test index 270eac2a46f..aee5a770fa9 100644 --- a/mysql-test/main/having_cond_pushdown.test +++ b/mysql-test/main/having_cond_pushdown.test @@ -1450,3 +1450,36 @@ SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL); SELECT * FROM t1 GROUP BY i HAVING i IN ( i IS NULL AND 'x' = 0); SELECT * FROM t1 GROUP BY i HAVING i='1' IN ( i IS NULL AND 'x' = 0); DROP TABLE t1; + +--echo # +--echo # MDEV-28080: HAVING with NOT EXIST predicate in an equality +--echo # (fixed by the patch for MDEV-26402) +--echo # + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (0), (1), (1), (0); +INSERT INTO t2 VALUES (3), (7); + +SELECT a FROM t1 + GROUP BY a HAVING a= (NOT EXISTS (SELECT b FROM t2 WHERE b = 1)); +SELECT a FROM t1 + GROUP BY a HAVING a= (NOT EXISTS (SELECT b FROM t2 WHERE b = 7)); + +DROP TABLE t1, t2; + +--echo # +--echo # MDEV-28082: HAVING with IS NULL predicate in an equality +--echo # (fixed by the patch for MDEV-26402) +--echo # + +CREATE TABLE t1 (a int, b int NOT NULL) ; +INSERT INTO t1 VALUES (1,10), (0,11), (0,11), (1,10); + +SELECT a,b FROM t1 GROUP BY a HAVING a = (b IS NULL); + +SELECT a,b FROM t1 GROUP BY a,b HAVING a = (b IS NULL); + +DROP TABLE t1; + +--echo End of 10.4 tests From 6e7c6fcfd1f1ac131c423c1ba084d61abad10e8b Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 30 Apr 2022 13:25:34 -0700 Subject: [PATCH 64/94] MDEV-28448 Assertion failure for SELECT with subquery using ON expression This patch corrects the fix for MDEV-26412. Note that when parsing an ON expression the pointer to the current select is always in select_stack[select_stack_top - 1]. So the pointer to the outer select (if any) is in select_stack[select_stack_top - 2]. The query manifesting this bug is added to the test case of MDEV-26412. --- mysql-test/main/insert.result | 4 ++++ mysql-test/main/insert.test | 5 +++++ sql/sql_lex.h | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/insert.result b/mysql-test/main/insert.result index 1062ddd6a94..af7dcbedd1f 100644 --- a/mysql-test/main/insert.result +++ b/mysql-test/main/insert.result @@ -766,4 +766,8 @@ replace t4 select * from t1 left join t2 on (select t1.i from t3); ERROR 42S22: Unknown column 't1.i' in 'field list' drop table t1,t2,t3,t4; +create table t (a int); +select 1 in (select count(*) from t t1 join (t t2 join t t3 on (t1.a != 0))); +ERROR 42S22: Unknown column 't1.a' in 'on clause' +drop table t; # End of 10.4 tests diff --git a/mysql-test/main/insert.test b/mysql-test/main/insert.test index 9fd0933cc7c..27d44918bbb 100644 --- a/mysql-test/main/insert.test +++ b/mysql-test/main/insert.test @@ -633,4 +633,9 @@ replace t4 drop table t1,t2,t3,t4; +create table t (a int); +--error ER_BAD_FIELD_ERROR +select 1 in (select count(*) from t t1 join (t t2 join t t3 on (t1.a != 0))); +drop table t; + --echo # End of 10.4 tests diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3e35d16d355..6a3a01f69d6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3700,7 +3700,7 @@ public: SELECT_LEX *parser_current_outer_select() { return select_stack_top - 1 == select_stack_outer_barrier ? - 0 : select_stack[select_stack_top - 1]; + 0 : select_stack[select_stack_top - 2]; } Name_resolution_context *current_context() From 680ca15269ba3fddf3c795da6bf889acacfdd258 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 30 Apr 2022 08:49:13 +0400 Subject: [PATCH 65/94] MDEV-28446 mariabackup prepare fails for incrementals if a new schema is created after full backup is taken When "mariabackup --target-dir=$basedir --incremental-dir=$incremental_dir" is running and is moving a new table file (e.g. `db1/t1.new`) from the incremental directory to the base directory, it needs to verify that the base backup database directory (e.g. `$basedir/db1`) really exists (or create it otherwise). The table `db1/t1` can come from a new database `db1` which was created during the base mariabackup execution time. In such case the directory `db1` exists only in the incremental directory, but does not exist in the base directory. --- extra/mariabackup/xtrabackup.cc | 16 ++++++- .../incremental_newdb_while_backup.result | 24 ++++++++++ .../incremental_newdb_while_backup.test | 47 +++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/mariabackup/incremental_newdb_while_backup.result create mode 100644 mysql-test/suite/mariabackup/incremental_newdb_while_backup.test diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index c1b2a1a9c85..ada63e1e882 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -5441,11 +5441,23 @@ static ibool prepare_handle_new_files(const char *data_home_dir, const char *file_name, void *arg) { const char *dest_dir = static_cast(arg); - std::string src_path = std::string(data_home_dir) + '/' + std::string(db_name) + '/' + file_name; + std::string src_path = std::string(data_home_dir) + '/' + std::string(db_name) + '/'; /* Copy "*.new" files from incremental to base dir for incremental backup */ std::string dest_path= dest_dir ? std::string(dest_dir) + '/' + std::string(db_name) + - '/' + file_name : src_path; + '/' : src_path; + + /* + A CREATE DATABASE could have happened during the base mariabackup run. + In case if the current table file (e.g. `t1.new`) is from such + a new database, the database directory may not exist yet in + the base backup directory. Let's make sure to check if the directory + exists (and create if needed). + */ + if (!directory_exists(dest_path.c_str(), true/*create if not exists*/)) + return FALSE; + src_path+= file_name; + dest_path+= file_name; size_t index = dest_path.find(".new"); DBUG_ASSERT(index != std::string::npos); diff --git a/mysql-test/suite/mariabackup/incremental_newdb_while_backup.result b/mysql-test/suite/mariabackup/incremental_newdb_while_backup.result new file mode 100644 index 00000000000..e1d5c7a5df4 --- /dev/null +++ b/mysql-test/suite/mariabackup/incremental_newdb_while_backup.result @@ -0,0 +1,24 @@ +call mtr.add_suppression("InnoDB: New log files created"); +# +# Start of 10.2 tests +# +# +# MDEV-28446 mariabackup prepare fails for incrementals if a new schema is created after full backup is taken +# +CREATE TABLE t1(i INT PRIMARY KEY) ENGINE INNODB; +# Prepare full backup, apply incremental one +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT COUNT(*) FROM test.t1; +COUNT(*) +0 +SELECT COUNT(*) FROM test1.t1; +COUNT(*) +10000 +DROP TABLE t1; +DROP DATABASE test1; +# +# End of 10.2 tests +# diff --git a/mysql-test/suite/mariabackup/incremental_newdb_while_backup.test b/mysql-test/suite/mariabackup/incremental_newdb_while_backup.test new file mode 100644 index 00000000000..2433fb4a35a --- /dev/null +++ b/mysql-test/suite/mariabackup/incremental_newdb_while_backup.test @@ -0,0 +1,47 @@ +--source include/have_innodb.inc +--source include/have_debug.inc + +call mtr.add_suppression("InnoDB: New log files created"); + +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-28446 mariabackup prepare fails for incrementals if a new schema is created after full backup is taken +--echo # + +--let $basedir=$MYSQLTEST_VARDIR/tmp/backup +--let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1 + +CREATE TABLE t1(i INT PRIMARY KEY) ENGINE INNODB; + +--disable_result_log +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir +--enable_result_log + +--let after_load_tablespaces=BEGIN NOT ATOMIC CREATE DATABASE test1; CREATE TABLE test1.t1 ENGINE=INNODB SELECT UUID() from test.seq_1_to_10000; END + +--exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir --dbug=+d,mariabackup_events,mariabackup_inject_code +--let after_load_tablespaces= +--disable_result_log +--echo # Prepare full backup, apply incremental one +--exec $XTRABACKUP --apply-log-only --prepare --target-dir=$basedir +--exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir +--enable_result_log + +--let $targetdir=$basedir +--source include/restart_and_restore.inc +--enable_result_log + +SELECT COUNT(*) FROM test.t1; +SELECT COUNT(*) FROM test1.t1; + +DROP TABLE t1; +DROP DATABASE test1; +--rmdir $basedir +--rmdir $incremental_dir + +--echo # +--echo # End of 10.2 tests +--echo # From 70555454b4c224e85383d482411961c7f2eba2e2 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 2 May 2022 11:55:31 +0200 Subject: [PATCH 66/94] New CC 3.1 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index f33017c19a5..ab7a81e79e4 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit f33017c19a5b02394de5d0816513d2e2c9d1767c +Subproject commit ab7a81e79e4be4324a2d09d19d4f5249801ef665 From c796c2664036e608f9859c1a6a025b00c4d1c285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 29 Apr 2022 09:49:14 +0300 Subject: [PATCH 67/94] MDEV-24688 : galera.galera_ist_progress MTR failed: assert_grep.inc failed Grep is not safe as it will confuse if there is more than one matching line or if progress report is slightly different as progress reporting is afected by how fast IST is send/received. Fix is to use sed and we are interested only that there is at least one progress report from IST. --- .../suite/galera/r/galera_ist_progress.result | 7 ++--- .../suite/galera/t/galera_ist_progress.cnf | 2 ++ .../suite/galera/t/galera_ist_progress.test | 28 ++++++------------- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_ist_progress.result b/mysql-test/suite/galera/r/galera_ist_progress.result index 9233d95b970..16772271b72 100644 --- a/mysql-test/suite/galera/r/galera_ist_progress.result +++ b/mysql-test/suite/galera/r/galera_ist_progress.result @@ -7,7 +7,7 @@ connection node_2; SET SESSION wsrep_on = OFF; SET SESSION wsrep_on = ON; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2); INSERT INTO t1 VALUES (3); @@ -23,8 +23,7 @@ SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; connection node_1; connection node_2; connection node_1; -include/assert_grep.inc [Receiving IST: 13 writesets, seqnos 3-15] -include/assert_grep.inc [Receiving IST\.\.\. 0\.0% \( 0/13 events\) complete] -include/assert_grep.inc [Receiving IST\.\.\.100\.0% \(13/13 events\) complete] +"Trying to find IST progress reporting" +found connection node_1; DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_ist_progress.cnf b/mysql-test/suite/galera/t/galera_ist_progress.cnf index 0a26f6d6c83..b37e7f38ce3 100644 --- a/mysql-test/suite/galera/t/galera_ist_progress.cnf +++ b/mysql-test/suite/galera/t/galera_ist_progress.cnf @@ -3,3 +3,5 @@ [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + + diff --git a/mysql-test/suite/galera/t/galera_ist_progress.test b/mysql-test/suite/galera/t/galera_ist_progress.test index 3d7c53bd1eb..60034ec0db1 100644 --- a/mysql-test/suite/galera/t/galera_ist_progress.test +++ b/mysql-test/suite/galera/t/galera_ist_progress.test @@ -3,12 +3,11 @@ # --source include/galera_cluster.inc -# This could cause out of storage if run /dev/shm ---source include/big_test.inc ---source include/force_restart.inc # Isolate node #2 --connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; --connection node_1 @@ -24,7 +23,7 @@ SET SESSION wsrep_on = ON; # Node #2 is now isolated. Run some transactions to accumulate writesets for IST --connection node_1 -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2); INSERT INTO t1 VALUES (3); @@ -50,26 +49,15 @@ SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; --source include/wait_condition.inc # -# Grep for expected IST output in joiner log +# sed for expected IST output in joiner log # --connection node_1 ---let $assert_count = 1 ---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err ---let $assert_only_after = Need state transfer - ---let $assert_text = Receiving IST: 13 writesets, seqnos 3-15 ---let $assert_select = Receiving IST: 13 writesets, seqnos 3-15 ---source include/assert_grep.inc - ---let $assert_text = Receiving IST\.\.\. 0\.0% \( 0/13 events\) complete ---let $assert_select = Receiving IST\.\.\. 0\.0% \( 0/13 events\) complete ---source include/assert_grep.inc - ---let $assert_text = Receiving IST\.\.\.100\.0% \(13/13 events\) complete ---let $assert_select = Receiving IST\.\.\.100\.0% \(13/13 events\) complete ---source include/assert_grep.inc +# Grep is not safe always and we are interested that there is at least one progress report (there can be more) +let $MYSQLD_DATADIR= `SELECT @@datadir`; +--echo "Trying to find IST progress reporting" +--exec sed -ne 's/.*Receiving IST.*/found/p' $MYSQLD_DATADIR/../../log/mysqld.2.err | tail -1 # Cleanup From 836a352b86fc90bffc25d62f2674ca33793ec33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 29 Apr 2022 10:34:58 +0300 Subject: [PATCH 68/94] MDEV-22666 : galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 Removed bad tests. --- mysql-test/suite/galera/disabled.def | 2 - mysql-test/suite/galera/r/MW-328A.result | 47 ------------ mysql-test/suite/galera/r/MW-328B.result | 25 ------- mysql-test/suite/galera/r/MW-328D.result | 22 ------ mysql-test/suite/galera/r/MW-328E.result | 22 ------ mysql-test/suite/galera/t/MW-328-footer.inc | 18 ----- mysql-test/suite/galera/t/MW-328-header.inc | 29 -------- mysql-test/suite/galera/t/MW-328A.cnf | 7 -- mysql-test/suite/galera/t/MW-328A.test | 82 --------------------- mysql-test/suite/galera/t/MW-328B.cnf | 7 -- mysql-test/suite/galera/t/MW-328B.test | 36 --------- mysql-test/suite/galera/t/MW-328D.cnf | 7 -- mysql-test/suite/galera/t/MW-328D.test | 39 ---------- mysql-test/suite/galera/t/MW-328E.cnf | 7 -- mysql-test/suite/galera/t/MW-328E.test | 40 ---------- 15 files changed, 390 deletions(-) delete mode 100644 mysql-test/suite/galera/r/MW-328A.result delete mode 100644 mysql-test/suite/galera/r/MW-328B.result delete mode 100644 mysql-test/suite/galera/r/MW-328D.result delete mode 100644 mysql-test/suite/galera/r/MW-328E.result delete mode 100644 mysql-test/suite/galera/t/MW-328-footer.inc delete mode 100644 mysql-test/suite/galera/t/MW-328-header.inc delete mode 100644 mysql-test/suite/galera/t/MW-328A.cnf delete mode 100644 mysql-test/suite/galera/t/MW-328A.test delete mode 100644 mysql-test/suite/galera/t/MW-328B.cnf delete mode 100644 mysql-test/suite/galera/t/MW-328B.test delete mode 100644 mysql-test/suite/galera/t/MW-328D.cnf delete mode 100644 mysql-test/suite/galera/t/MW-328D.test delete mode 100644 mysql-test/suite/galera/t/MW-328E.cnf delete mode 100644 mysql-test/suite/galera/t/MW-328E.test diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 0cb698bbe73..0263c57c264 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -12,8 +12,6 @@ GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081 GCF-939 : MDEV-21520 galera.GCF-939 -MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 -MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-329 : MDEV-19962 Galera test failure on MW-329 galera_as_slave_ctas : MDEV-28378 timeout galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() diff --git a/mysql-test/suite/galera/r/MW-328A.result b/mysql-test/suite/galera/r/MW-328A.result deleted file mode 100644 index f256558644e..00000000000 --- a/mysql-test/suite/galera/r/MW-328A.result +++ /dev/null @@ -1,47 +0,0 @@ -connection node_2; -connection node_1; -CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; -INSERT INTO t1 (f1) VALUES (1); -CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB; -CREATE PROCEDURE proc_update () -BEGIN -DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; -SET SESSION wsrep_sync_wait = 0; -WHILE 1 DO -UPDATE t1 SET f2 = LEFT(MD5(RAND()), 4); -END WHILE; -END| -connect node_1X, 127.0.0.1, root, , test, $NODE_MYPORT_1; -connection node_1X; -CALL proc_update();; -connection node_1; -call mtr.add_suppression("WSREP: Wait for gtid returned error 3 while waiting for prior transactions to commit before setting position"); -connection node_2; -call mtr.add_suppression("WSREP: Wait for gtid returned error 3 while waiting for prior transactions to commit before setting position"); -SET SESSION wsrep_retry_autocommit = 0; -connection node_1; -connection node_1X; -Got one of the listed errors -connection node_1; -DROP PROCEDURE proc_update; -DROP TABLE t1, t2; -CALL mtr.add_suppression("conflict state ABORTED after post commit"); -connection node_1; -CREATE TABLE t1 (i int primary key, j int) engine=innodb; -INSERT INTO t1 values (1,0); -BEGIN; -UPDATE t1 SET j=1 WHERE i=1; -connection node_2; -UPDATE t1 SET j=2 WHERE i=1; -connection node_1; -COMMIT; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SELECT * FROM t1; -i j -1 2 -connection node_2; -SELECT * FROM t1; -i j -1 2 -connection node_1; -DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/MW-328B.result b/mysql-test/suite/galera/r/MW-328B.result deleted file mode 100644 index 93a8685cc9e..00000000000 --- a/mysql-test/suite/galera/r/MW-328B.result +++ /dev/null @@ -1,25 +0,0 @@ -connection node_2; -connection node_1; -CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; -INSERT INTO t1 (f1) VALUES (1); -CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB; -CREATE PROCEDURE proc_update () -BEGIN -DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; -SET SESSION wsrep_sync_wait = 0; -WHILE 1 DO -UPDATE t1 SET f2 = LEFT(MD5(RAND()), 4); -END WHILE; -END| -connect node_1X, 127.0.0.1, root, , test, $NODE_MYPORT_1; -connection node_1X; -CALL proc_update();; -connection node_2; -SET SESSION wsrep_retry_autocommit = 0; -connection node_1; -connection node_1X; -Got one of the listed errors -connection node_1; -DROP PROCEDURE proc_update; -DROP TABLE t1, t2; -CALL mtr.add_suppression("conflict state ABORTED after post commit"); diff --git a/mysql-test/suite/galera/r/MW-328D.result b/mysql-test/suite/galera/r/MW-328D.result deleted file mode 100644 index 43e1cefe08f..00000000000 --- a/mysql-test/suite/galera/r/MW-328D.result +++ /dev/null @@ -1,22 +0,0 @@ -connection node_2; -connection node_1; -CREATE TABLE t1 (i INT) ENGINE = InnoDB; -INSERT INTO t1 (i) VALUES(1); -CREATE TABLE t2 (i INT) ENGINE = InnoDB; -connection node_1; -SET AUTOCOMMIT=OFF; -START TRANSACTION; -SELECT * FROM t1 WHERE i = 1 LOCK IN SHARE MODE; -i -1 -connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; -connection node_1a; -SET AUTOCOMMIT=OFF; -START TRANSACTION; -INSERT IGNORE INTO t2 SELECT * FROM t1 WHERE i = 1 FOR UPDATE;; -connection node_1; -DELETE FROM t1 WHERE i = 1; -COMMIT; -connection node_1a; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/r/MW-328E.result b/mysql-test/suite/galera/r/MW-328E.result deleted file mode 100644 index 729fdea1a63..00000000000 --- a/mysql-test/suite/galera/r/MW-328E.result +++ /dev/null @@ -1,22 +0,0 @@ -connection node_2; -connection node_1; -create table t1 (i int primary key, j int) engine=innodb; -create table t2 (i int primary key, j int) engine=innodb; -insert into t1 values (1,0); -insert into t2 values (2,0); -set autocommit=off; -start transaction; -update t1 set j=1 where i=1; -connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; -connection node_1a; -set autocommit=off; -start transaction; -begin; -update t2 set j=1 where i=2; -connection node_1; -insert into t1 select * from t2;; -connection node_1a; -insert into t2 select * from t1; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -connection node_1; -DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/t/MW-328-footer.inc b/mysql-test/suite/galera/t/MW-328-footer.inc deleted file mode 100644 index 12a4bf12590..00000000000 --- a/mysql-test/suite/galera/t/MW-328-footer.inc +++ /dev/null @@ -1,18 +0,0 @@ -# -# Cleanup for MW-328 tests -# - ---connection node_1 ---disable_query_log ---eval KILL CONNECTION $sp_connection_id ---enable_query_log - ---connection node_1X ---error 2013,1317 ---reap - ---connection node_1 -DROP PROCEDURE proc_update; -DROP TABLE t1, t2; - -CALL mtr.add_suppression("conflict state ABORTED after post commit"); diff --git a/mysql-test/suite/galera/t/MW-328-header.inc b/mysql-test/suite/galera/t/MW-328-header.inc deleted file mode 100644 index f0a6ccaccc6..00000000000 --- a/mysql-test/suite/galera/t/MW-328-header.inc +++ /dev/null @@ -1,29 +0,0 @@ -# -# Initialization for MW-328 tests -# - -CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; -INSERT INTO t1 (f1) VALUES (1); - -CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB; - -# -# Have some random updates going on against t1 -# - -DELIMITER |; -CREATE PROCEDURE proc_update () -BEGIN - DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; - SET SESSION wsrep_sync_wait = 0; - WHILE 1 DO - UPDATE t1 SET f2 = LEFT(MD5(RAND()), 4); - END WHILE; -END| - -DELIMITER ;| - ---connect node_1X, 127.0.0.1, root, , test, $NODE_MYPORT_1 ---connection node_1X ---let $sp_connection_id = `SELECT CONNECTION_ID()` ---send CALL proc_update(); diff --git a/mysql-test/suite/galera/t/MW-328A.cnf b/mysql-test/suite/galera/t/MW-328A.cnf deleted file mode 100644 index e68f891792c..00000000000 --- a/mysql-test/suite/galera/t/MW-328A.cnf +++ /dev/null @@ -1,7 +0,0 @@ -!include ../galera_2nodes.cnf - -[mysqld.1] -wsrep-debug=SERVER - -[mysqld.2] -wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328A.test b/mysql-test/suite/galera/t/MW-328A.test deleted file mode 100644 index 2435a9e2c2e..00000000000 --- a/mysql-test/suite/galera/t/MW-328A.test +++ /dev/null @@ -1,82 +0,0 @@ -# -# MW-328 Fix unnecessary/silent BF aborts -# - -# -# test phase 1 is not deterministic -# -# Here we attempt to insert into t2 and check if insert actually -# inserted rows if a success was reported. -# -# However, deadlocks may or may not happen in this test execution -# it all depends on timing. -# - ---source include/galera_cluster.inc ---source include/force_restart.inc ---source suite/galera/t/MW-328-header.inc - ---connection node_1 -call mtr.add_suppression("WSREP: Wait for gtid returned error 3 while waiting for prior transactions to commit before setting position"); - ---connection node_2 -call mtr.add_suppression("WSREP: Wait for gtid returned error 3 while waiting for prior transactions to commit before setting position"); ---let $count = 100 ---let $successes = 0 ---let $deadlocks = 0 - -SET SESSION wsrep_retry_autocommit = 0; - ---disable_query_log - -while ($count) -{ - TRUNCATE TABLE t2; - - --error 0,ER_LOCK_DEADLOCK - INSERT IGNORE INTO t2 SELECT f2 FROM t1; - if ($mysql_errno != 1213) { - --inc $successes - if (`SELECT COUNT(*) = 0 FROM t2`) { - --die No rows arrived in table t2 - } - } - - if ($mysql_errno == 1213) { - --inc $deadlocks - - } - - --dec $count -} - ---enable_query_log - - ---source suite/galera/t/MW-328-footer.inc - -# -# Test phase 2 is deterministic -# Here we generate a sure conflict in node 1 and verify that -# insert failed in both nodes -# ---connection node_1 -CREATE TABLE t1 (i int primary key, j int) engine=innodb; -INSERT INTO t1 values (1,0); - -BEGIN; -UPDATE t1 SET j=1 WHERE i=1; - ---connection node_2 -UPDATE t1 SET j=2 WHERE i=1; - ---connection node_1 ---error ER_LOCK_DEADLOCK -COMMIT; - -SELECT * FROM t1; ---connection node_2 -SELECT * FROM t1; ---connection node_1 - -DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/MW-328B.cnf b/mysql-test/suite/galera/t/MW-328B.cnf deleted file mode 100644 index e68f891792c..00000000000 --- a/mysql-test/suite/galera/t/MW-328B.cnf +++ /dev/null @@ -1,7 +0,0 @@ -!include ../galera_2nodes.cnf - -[mysqld.1] -wsrep-debug=SERVER - -[mysqld.2] -wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328B.test b/mysql-test/suite/galera/t/MW-328B.test deleted file mode 100644 index 41581d9c239..00000000000 --- a/mysql-test/suite/galera/t/MW-328B.test +++ /dev/null @@ -1,36 +0,0 @@ -# -# MW-328 Fix unnecessary/silent BF aborts -# - -# -# Make sure an unrelated SELECT following a BF-aborted query never -# gets the deadlock error -# - ---source include/galera_cluster.inc ---source include/force_restart.inc ---source suite/galera/t/MW-328-header.inc - ---connection node_2 ---let $count = 100 - -SET SESSION wsrep_retry_autocommit = 0; - ---disable_query_log - -while ($count) -{ - --error 0,1213 - INSERT IGNORE INTO t2 SELECT f2 FROM t1; - - --disable_result_log - --error 0 - SELECT 1 FROM DUAL; - --enable_result_log - - --dec $count -} - ---enable_query_log - ---source suite/galera/t/MW-328-footer.inc diff --git a/mysql-test/suite/galera/t/MW-328D.cnf b/mysql-test/suite/galera/t/MW-328D.cnf deleted file mode 100644 index e68f891792c..00000000000 --- a/mysql-test/suite/galera/t/MW-328D.cnf +++ /dev/null @@ -1,7 +0,0 @@ -!include ../galera_2nodes.cnf - -[mysqld.1] -wsrep-debug=SERVER - -[mysqld.2] -wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328D.test b/mysql-test/suite/galera/t/MW-328D.test deleted file mode 100644 index e8a22f22a99..00000000000 --- a/mysql-test/suite/galera/t/MW-328D.test +++ /dev/null @@ -1,39 +0,0 @@ -# -# MW-328 Fix unnecessary/silent BF aborts -# - -# -# Test that non-Galera deadlock error still behaves as expected -# - ---source include/galera_cluster.inc - -CREATE TABLE t1 (i INT) ENGINE = InnoDB; -INSERT INTO t1 (i) VALUES(1); - -CREATE TABLE t2 (i INT) ENGINE = InnoDB; - -# Create a deadlock situation - ---connection node_1 -SET AUTOCOMMIT=OFF; -START TRANSACTION; -SELECT * FROM t1 WHERE i = 1 LOCK IN SHARE MODE; - ---connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 ---connection node_1a -SET AUTOCOMMIT=OFF; -START TRANSACTION; ---send INSERT IGNORE INTO t2 SELECT * FROM t1 WHERE i = 1 FOR UPDATE; - ---connection node_1 ---sleep 2 -DELETE FROM t1 WHERE i = 1; -COMMIT; - -# We expect that ER_LOCK_DEADLOCK will be delivered even though it was a INSERT INGORE statement ---connection node_1a ---error ER_LOCK_DEADLOCK ---reap - -DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/t/MW-328E.cnf b/mysql-test/suite/galera/t/MW-328E.cnf deleted file mode 100644 index e68f891792c..00000000000 --- a/mysql-test/suite/galera/t/MW-328E.cnf +++ /dev/null @@ -1,7 +0,0 @@ -!include ../galera_2nodes.cnf - -[mysqld.1] -wsrep-debug=SERVER - -[mysqld.2] -wsrep-debug=SERVER diff --git a/mysql-test/suite/galera/t/MW-328E.test b/mysql-test/suite/galera/t/MW-328E.test deleted file mode 100644 index 34b17be7b08..00000000000 --- a/mysql-test/suite/galera/t/MW-328E.test +++ /dev/null @@ -1,40 +0,0 @@ -# -# MW-328 Fix unnecessary/silent BF aborts -# - -# -# Test that non-Galera deadlock error still behaves as expected (case #2) -# - ---source include/galera_cluster.inc - -create table t1 (i int primary key, j int) engine=innodb; -create table t2 (i int primary key, j int) engine=innodb; - -insert into t1 values (1,0); -insert into t2 values (2,0); - -set autocommit=off; -start transaction; -update t1 set j=1 where i=1; - ---connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 ---connection node_1a -set autocommit=off; -start transaction; -begin; -update t2 set j=1 where i=2; - ---connection node_1 -# Hang expected here ---send insert into t1 select * from t2; - ---sleep 2 ---connection node_1a ---error ER_LOCK_DEADLOCK -insert into t2 select * from t1; - ---connection node_1 ---reap - -DROP TABLE t1, t2; From 9c29a444c532328a3d79ae5883b8adeb1a322b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 29 Apr 2022 12:19:19 +0300 Subject: [PATCH 69/94] MDEV-21557 : galera_bf_abort_at_after_statement MTR failed: query 'reap' succeeded - should have failed with errno 1213 Add wait_condition so that conflicting update is done. --- .../galera/r/galera_bf_abort_at_after_statement.result | 4 ++++ .../galera/t/galera_bf_abort_at_after_statement.test | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/mysql-test/suite/galera/r/galera_bf_abort_at_after_statement.result b/mysql-test/suite/galera/r/galera_bf_abort_at_after_statement.result index f6f0803227f..71eeb6861ea 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_at_after_statement.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_at_after_statement.result @@ -12,6 +12,8 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; SET DEBUG_SYNC = 'now WAIT_FOR blocked'; connection node_1; UPDATE t1 SET val=3 WHERE id=1; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +set session wsrep_sync_wait=0; connection node_2a; SET DEBUG_SYNC = 'now SIGNAL continue'; connection node_2; @@ -21,3 +23,5 @@ SET DEBUG_SYNC = 'RESET'; connection node_1; SET DEBUG_SYNC = 'RESET'; DROP TABLE t1; +disconnect node_2a; +disconnect node_2b; diff --git a/mysql-test/suite/galera/t/galera_bf_abort_at_after_statement.test b/mysql-test/suite/galera/t/galera_bf_abort_at_after_statement.test index 738aedbda9e..224db902569 100644 --- a/mysql-test/suite/galera/t/galera_bf_abort_at_after_statement.test +++ b/mysql-test/suite/galera/t/galera_bf_abort_at_after_statement.test @@ -34,6 +34,11 @@ SET DEBUG_SYNC = 'now WAIT_FOR blocked'; # cause BF abort on other node UPDATE t1 SET val=3 WHERE id=1; +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +set session wsrep_sync_wait=0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1 where id = 1 and val = 3 +--source include/wait_condition.inc + --connection node_2a SET DEBUG_SYNC = 'now SIGNAL continue'; @@ -47,3 +52,7 @@ SET DEBUG_SYNC = 'RESET'; --connection node_1 SET DEBUG_SYNC = 'RESET'; DROP TABLE t1; + +--disconnect node_2a +--disconnect node_2b + From 6393a2813d685c69dfbf1febc635ce0eb1d725f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 2 May 2022 08:57:47 +0300 Subject: [PATCH 70/94] Enable fixed test cases --- mysql-test/suite/galera_sr/disabled.def | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/suite/galera_sr/disabled.def b/mysql-test/suite/galera_sr/disabled.def index 49b6f90e762..58b4af32300 100644 --- a/mysql-test/suite/galera_sr/disabled.def +++ b/mysql-test/suite/galera_sr/disabled.def @@ -10,5 +10,4 @@ # ############################################################################## -galera-features#56 : MDEV-24896 GCF-1060 : MDEV-26528 wrong usage of mutex LOCK_thd_kill and LOCK_thd_kill From 40b8f3ec1a76fc23eb6bf9c5a8fef1debcbf5843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 2 May 2022 10:53:41 +0300 Subject: [PATCH 71/94] Update wsrep-lib --- wsrep-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsrep-lib b/wsrep-lib index 23fb8624624..8bfce041896 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit 23fb8624624c9144c77f3874647fa0f7394b0aa8 +Subproject commit 8bfce04189671eb1f06e0fa83dff8c880f31088f From 794bebf9ee18de4138c4d2c93853d49ff3af7f12 Mon Sep 17 00:00:00 2001 From: anel Date: Fri, 1 Apr 2022 07:17:43 -0700 Subject: [PATCH 72/94] Use proper pid namespace Problem: ============== By testing `pgrep` with `--ns` option, introduced with MDEV-21331, commit fb7c1b9415c9a8b0dc2e86ae44f0e7a2634e5d7e, I noted that: a) `--ns` cannot use more than single PID. b) `--ns` is returning the processes of the namespace to which supplied PID belongs to. So by that sense command `pgrep -x --ns $$ mysqld` will always return an error and skip checking of the existing PID of the server. Solution: ============== Suggested solution is to add `--nslist pid`, since `--ns` needs to know in which namespace type it should look for. See `pgrep --help` for different namespace types. Note also that this works *only* if script is run as a `root` (we have that case here). Current PR is a part of: 1. MDEV-21331: sync preinst and postrm script 2. MDEV-15718: check for exact mysqld process This commit: a) fixes fb7c1b9415c9a8b0dc2e86ae44f0e7a2634e5d7e b) Closes PR #2068 (obsolete) c) Closes PR #2069 (obsolete) Thanks Faustin Lammler for testing and verifying Reviewed by <> --- debian/mariadb-server-10.2.postrm | 5 +++++ debian/mariadb-server-10.2.preinst | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/debian/mariadb-server-10.2.postrm b/debian/mariadb-server-10.2.postrm index f8a95df54ea..1ead4098906 100644 --- a/debian/mariadb-server-10.2.postrm +++ b/debian/mariadb-server-10.2.postrm @@ -11,6 +11,11 @@ MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" # do it himself. No database directories should be removed while the server # is running! stop_server() { + # Return immediately if there are no mysql processes running + # as there is no point in trying to shutdown in that case. + # Compatibility with versions that ran 'mariadbd' + if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi + set +e if [ -x /usr/sbin/invoke-rc.d ]; then invoke-rc.d mysql stop diff --git a/debian/mariadb-server-10.2.preinst b/debian/mariadb-server-10.2.preinst index 161d9caee6e..13dda71998a 100644 --- a/debian/mariadb-server-10.2.preinst +++ b/debian/mariadb-server-10.2.preinst @@ -22,10 +22,11 @@ mysql_upgradedir=/var/lib/mysql-upgrade # is running! Another mysqld in e.g. a different chroot is fine for us. stop_server() { if [ ! -x /etc/init.d/mysql ]; then return; fi - - # Return immediately if there are no mysql processes running + # Return immediately if there are no mysql processes running on a host + # (leave containerized processes with the same name in other namespaces) # as there is no point in trying to shutdown in that case. - if ! pgrep --ns $$ mysqld > /dev/null; then return; fi + # Compatibility with versions that ran 'mariadbd' + if ! pgrep -x --nslist pid --ns $$ "mysqld|mariadbd" > /dev/null; then return; fi set +e if [ -x /usr/sbin/invoke-rc.d ]; then From 2c381d8cf65ad46936045fb7ee141de4e392cde7 Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Thu, 14 Apr 2022 14:27:23 +0300 Subject: [PATCH 73/94] MDEV-17843 Assertion `page_rec_is_leaf(rec)' failed in lock_rec_queue_validate upon SHOW ENGINE INNODB STATUS lock_validate() accumulates page ids under locked lock_sys->mutex, then releases the latch, and invokes lock_rec_block_validate() for each page. Some other thread has ability to add/remove locks and change pages between releasing the latch in lock_validate() and acquiring it in lock_rec_validate_page(). lock_rec_validate_page() can invoke lock_rec_queue_validate() for non-locked supremum, what can cause ut_ad(page_rec_is_leaf(rec)) failure in lock_rec_queue_validate(). The fix is to invoke lock_rec_queue_validate() only for locked records in lock_rec_validate_page(). The error message in lock_rec_block_validate() is not necessary as BUF_GET_POSSIBLY_FREED mode is used to get block from buffer pool, and this is not error if a block was evicted. The test case would require new debug sync point. I think it's not necessary as the fixed code is debug-only. --- storage/innobase/lock/lock0lock.cc | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 3398f09b772..2fd2ef94365 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5050,25 +5050,25 @@ loop: holding a space->latch. */ if (!sync_check_find(SYNC_FSP)) for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) { - - if (i == PAGE_HEAP_NO_SUPREMUM - || lock_rec_get_nth_bit(lock, i)) { + bool locked = lock_rec_get_nth_bit(lock, i); + if (locked || i == PAGE_HEAP_NO_SUPREMUM) { rec = page_find_rec_with_heap_no(block->frame, i); ut_a(rec); - ut_ad(!lock_rec_get_nth_bit(lock, i) - || page_rec_is_leaf(rec)); - offsets = rec_get_offsets(rec, lock->index, offsets, - lock->index->n_core_fields, - ULINT_UNDEFINED, &heap); + ut_ad(!locked || page_rec_is_leaf(rec)); /* If this thread is holding the file space latch (fil_space_t::latch), the following check WILL break the latching order and may cause a deadlock of threads. */ - lock_rec_queue_validate( - TRUE, block, rec, lock->index, offsets); + if (locked) { + offsets = rec_get_offsets(rec, lock->index, + offsets, lock->index->n_core_fields, + ULINT_UNDEFINED, &heap); + lock_rec_queue_validate(TRUE, block, rec, + lock->index, offsets); + } nth_bit = i + 1; @@ -5161,13 +5161,6 @@ lock_rec_block_validate( BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err); - if (err != DB_SUCCESS) { - ib::error() << "Lock rec block validate failed for tablespace " - << space->name - << " space_id " << space_id - << " page_no " << page_no << " err " << err; - } - if (block) { buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); From ba4927e520190bbad763bb5260ae154f29a61231 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 3 May 2022 14:06:27 +0300 Subject: [PATCH 74/94] MDEV-19398: Assertion `item1->type() == Item::FIELD_ITEM ... Window Functions code tries to minimize the number of times it needs to sort the select's resultset by finding "compatible" OVER (PARTITION BY ... ORDER BY ...) clauses. This employs compare_order_elements(). That function assumed that the order expressions are Item_field-derived objects (that refer to a temp.table). But this is not always the case: one can construct queries order expressions are arbitrary item expressions. Add handling for such expressions: sort them according to the window specification they appeared in. This means we cannot detect that two compatible PARTITION BY clauses that use expressions can share the sorting step. But at least we won't crash. --- mysql-test/r/win.result | 42 ++++++++++++++++++++++++++ mysql-test/t/win.test | 33 +++++++++++++++++++++ sql/sql_parse.cc | 2 ++ sql/sql_window.cc | 65 ++++++++++++++++++++++++++++++++++------- sql/sql_window.h | 7 +++++ 5 files changed, 139 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index 1ddafbd4f8f..b4d918eb437 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -4238,5 +4238,47 @@ SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ()); ERROR HY000: Expression #1 of ORDER BY contains aggregate function and applies to a UNION DROP TABLE t1; # +# MDEV-19398: Assertion `item1->type() == Item::FIELD_ITEM && +# item2->type() == Item::FIELD_ITEM' failed in compare_order_elements +# +CREATE TABLE t1 ( id varchar(10)); +INSERT INTO t1 values (1),(2),(3); +SELECT +dense_rank() over (ORDER BY avg(1)+3), +rank() over (ORDER BY avg(1)) +FROM t1 +GROUP BY nullif(id, 15532); +dense_rank() over (ORDER BY avg(1)+3) rank() over (ORDER BY avg(1)) +1 1 +1 1 +1 1 +SELECT +dense_rank() over (ORDER BY avg(1)), +rank() over (ORDER BY avg(1)) +FROM t1 +GROUP BY nullif(id, 15532); +dense_rank() over (ORDER BY avg(1)) rank() over (ORDER BY avg(1)) +1 1 +1 1 +1 1 +drop table t1; +CREATE TABLE t1 ( a char(25), b text); +INSERT INTO t1 VALUES ('foo','bar'); +SELECT +SUM(b) OVER (PARTITION BY a), +ROW_NUMBER() OVER (PARTITION BY b) +FROM t1 +GROUP BY +LEFT((SYSDATE()), 'foo') +WITH ROLLUP; +SUM(b) OVER (PARTITION BY a) ROW_NUMBER() OVER (PARTITION BY b) +NULL 1 +NULL 1 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: 'foo' +Warning 1292 Truncated incorrect INTEGER value: 'foo' +drop table t1; +# +# # End of 10.2 tests # diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index 37f09a6e850..ba1008afa60 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -2740,6 +2740,39 @@ INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(2),(2),(2),(2),(2); SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ()); DROP TABLE t1; +--echo # +--echo # MDEV-19398: Assertion `item1->type() == Item::FIELD_ITEM && +--echo # item2->type() == Item::FIELD_ITEM' failed in compare_order_elements +--echo # +CREATE TABLE t1 ( id varchar(10)); +INSERT INTO t1 values (1),(2),(3); + +SELECT + dense_rank() over (ORDER BY avg(1)+3), + rank() over (ORDER BY avg(1)) +FROM t1 +GROUP BY nullif(id, 15532); + +SELECT + dense_rank() over (ORDER BY avg(1)), + rank() over (ORDER BY avg(1)) +FROM t1 +GROUP BY nullif(id, 15532); +drop table t1; + +CREATE TABLE t1 ( a char(25), b text); +INSERT INTO t1 VALUES ('foo','bar'); + +SELECT + SUM(b) OVER (PARTITION BY a), + ROW_NUMBER() OVER (PARTITION BY b) +FROM t1 +GROUP BY + LEFT((SYSDATE()), 'foo') +WITH ROLLUP; +drop table t1; + +--echo # --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 989ca0c8803..457849a7569 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8624,6 +8624,7 @@ bool st_select_lex::add_window_def(THD *thd, fields_in_window_functions+= win_part_list_ptr->elements + win_order_list_ptr->elements; } + win_def->win_spec_number= window_specs.elements; return (win_def == NULL || window_specs.push_back(win_def)); } @@ -8651,6 +8652,7 @@ bool st_select_lex::add_window_spec(THD *thd, win_order_list_ptr->elements; } thd->lex->win_spec= win_spec; + win_spec->win_spec_number= window_specs.elements; return (win_spec == NULL || window_specs.push_back(win_spec)); } diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 3ef751bc5b9..8afdaa1e6da 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -312,15 +312,49 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, #define CMP_GT 2 // Greater then static -int compare_order_elements(ORDER *ord1, ORDER *ord2) +int compare_order_elements(ORDER *ord1, int weight1, + ORDER *ord2, int weight2) { if (*ord1->item == *ord2->item && ord1->direction == ord2->direction) return CMP_EQ; Item *item1= (*ord1->item)->real_item(); Item *item2= (*ord2->item)->real_item(); - DBUG_ASSERT(item1->type() == Item::FIELD_ITEM && - item2->type() == Item::FIELD_ITEM); - ptrdiff_t cmp= ((Item_field *) item1)->field - ((Item_field *) item2)->field; + + bool item1_field= (item1->type() == Item::FIELD_ITEM); + bool item2_field= (item2->type() == Item::FIELD_ITEM); + + ptrdiff_t cmp; + if (item1_field && item2_field) + { + DBUG_ASSERT(((Item_field *) item1)->field->table == + ((Item_field *) item2)->field->table); + cmp= ((Item_field *) item1)->field->field_index - + ((Item_field *) item2)->field->field_index; + } + else if (item1_field && !item2_field) + return CMP_LT; + else if (!item1_field && item2_field) + return CMP_LT; + else + { + /* + Ok, item1_field==NULL and item2_field==NULL. + We're not able to compare Item expressions. Order them according to + their passed "weight" (which comes from Window_spec::win_spec_number): + */ + if (weight1 != weight2) + cmp= weight1 - weight2; + else + { + /* + The weight is the same. That is, the elements come from the same + window specification... This shouldn't happen. + */ + DBUG_ASSERT(0); + cmp= item1 - item2; + } + } + if (cmp == 0) { if (ord1->direction == ord2->direction) @@ -333,7 +367,9 @@ int compare_order_elements(ORDER *ord1, ORDER *ord2) static int compare_order_lists(SQL_I_List *part_list1, - SQL_I_List *part_list2) + int spec_number1, + SQL_I_List *part_list2, + int spec_number2) { if (part_list1 == part_list2) return CMP_EQ; @@ -358,7 +394,8 @@ int compare_order_lists(SQL_I_List *part_list1, if (!elem1 || !elem2) break; - if ((cmp= compare_order_elements(elem1, elem2))) + if ((cmp= compare_order_elements(elem1, spec_number1, + elem2, spec_number2))) return cmp; } if (elem1) @@ -453,7 +490,9 @@ int compare_window_spec_joined_lists(Window_spec *win_spec1, win_spec1->join_partition_and_order_lists(); win_spec2->join_partition_and_order_lists(); int cmp= compare_order_lists(win_spec1->partition_list, - win_spec2->partition_list); + win_spec1->win_spec_number, + win_spec2->partition_list, + win_spec2->win_spec_number); win_spec1->disjoin_partition_and_order_lists(); win_spec2->disjoin_partition_and_order_lists(); return cmp; @@ -471,7 +510,9 @@ int compare_window_funcs_by_window_specs(Item_window_func *win_func1, if (win_spec1 == win_spec2) return CMP_EQ; cmp= compare_order_lists(win_spec1->partition_list, - win_spec2->partition_list); + win_spec1->win_spec_number, + win_spec2->partition_list, + win_spec2->win_spec_number); if (cmp == CMP_EQ) { /* @@ -490,7 +531,9 @@ int compare_window_funcs_by_window_specs(Item_window_func *win_func1, } cmp= compare_order_lists(win_spec1->order_list, - win_spec2->order_list); + win_spec1->win_spec_number, + win_spec2->order_list, + win_spec2->win_spec_number); if (cmp != CMP_EQ) return cmp; @@ -587,7 +630,9 @@ void order_window_funcs_by_window_specs(List *win_func_list) int cmp; if (win_spec_prev->partition_list == win_spec_curr->partition_list) cmp= compare_order_lists(win_spec_prev->order_list, - win_spec_curr->order_list); + win_spec_prev->win_spec_number, + win_spec_curr->order_list, + win_spec_curr->win_spec_number); else cmp= compare_window_spec_joined_lists(win_spec_prev, win_spec_curr); if (!(CMP_LT_C <= cmp && cmp <= CMP_GT_C)) diff --git a/sql/sql_window.h b/sql/sql_window.h index 417d0bca12c..b29038fc374 100644 --- a/sql/sql_window.h +++ b/sql/sql_window.h @@ -108,6 +108,13 @@ class Window_spec : public Sql_alloc Window_spec *referenced_win_spec; + /* + Window_spec objects are numbered by the number of their appearance in the + query. This is used by compare_order_elements() to provide a predictable + ordering of PARTITION/ORDER BY clauses. + */ + int win_spec_number; + Window_spec(LEX_STRING *win_ref, SQL_I_List *part_list, SQL_I_List *ord_list, From 531935992adbf2bea4e772583d93a6c4b5bd78fd Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 2 May 2022 12:22:57 +0200 Subject: [PATCH 75/94] test fixes for FreeBSD * FreeBSD returns errno 31 (EMLINK, Too many links), not 40 (ELOOP, Too many levels of symbolic links) * (`mysqlbinlog|mysql`) was just crazy, why did it ever work? * socket_ipv6.inc check (that checked whether ipv6 is supported) only worked correctly when ipv6 was supported * perfschema.socket_summary_by_instance was changing global variables and then skip-ing the test (because on missing ipv6) --- mysql-test/main/repair_symlink-5543.result | 2 +- mysql-test/main/repair_symlink-5543.test | 6 +++--- mysql-test/main/temp_table_symlink.test | 1 + .../suite/binlog/t/binlog_mysqlbinlog_stop_never.test | 7 +------ mysql-test/suite/perfschema/include/socket_ipv6.inc | 4 ++++ mysql-test/suite/perfschema/r/socket_connect.result | 1 - .../perfschema/r/socket_summary_by_event_name_func.result | 1 - .../perfschema/t/socket_summary_by_instance_func.test | 3 +-- 8 files changed, 11 insertions(+), 14 deletions(-) diff --git a/mysql-test/main/repair_symlink-5543.result b/mysql-test/main/repair_symlink-5543.result index 2024c9f5684..4f816d407b9 100644 --- a/mysql-test/main/repair_symlink-5543.result +++ b/mysql-test/main/repair_symlink-5543.result @@ -1,6 +1,6 @@ create table t1 (a int) engine=myisam data directory='MYSQL_TMP_DIR'; insert t1 values (1); -# Some systems fail with errcode 40, or 90 (MIPS) when doing openat, +# Some systems fail with errcode 31 (FreeBSD), 40, or 90 (MIPS) when doing openat, # while others don't have openat and fail with errcode 20. repair table t1; Table Op Msg_type Msg_text diff --git a/mysql-test/main/repair_symlink-5543.test b/mysql-test/main/repair_symlink-5543.test index ac7bb497f24..747e3f6ca1c 100644 --- a/mysql-test/main/repair_symlink-5543.test +++ b/mysql-test/main/repair_symlink-5543.test @@ -9,9 +9,9 @@ eval create table t1 (a int) engine=myisam data directory='$MYSQL_TMP_DIR'; insert t1 values (1); --system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t1.TMD ---echo # Some systems fail with errcode 40, or 90 (MIPS) when doing openat, +--echo # Some systems fail with errcode 31 (FreeBSD), 40, or 90 (MIPS) when doing openat, --echo # while others don't have openat and fail with errcode 20. ---replace_regex / '.*\/t1/ 'MYSQL_TMP_DIR\/t1/ /[49]0/20/ /".*"/""/ +--replace_regex / '.*\/t1/ 'MYSQL_TMP_DIR\/t1/ /[49]0|31/20/ /".*"/""/ repair table t1; drop table t1; @@ -19,7 +19,7 @@ drop table t1; eval create table t2 (a int) engine=aria data directory='$MYSQL_TMP_DIR'; insert t2 values (1); --system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t2.TMD ---replace_regex / '.*\/t2/ 'MYSQL_TMP_DIR\/t2/ /[49]0/20/ /".*"/""/ +--replace_regex / '.*\/t2/ 'MYSQL_TMP_DIR\/t2/ /[49]0|31/20/ /".*"/""/ repair table t2; drop table t2; diff --git a/mysql-test/main/temp_table_symlink.test b/mysql-test/main/temp_table_symlink.test index 9297b472805..5bd8c5ac5bc 100644 --- a/mysql-test/main/temp_table_symlink.test +++ b/mysql-test/main/temp_table_symlink.test @@ -14,6 +14,7 @@ for (<#sql*.MYI>) { symlink "$ENV{datadir}/test/d1.MYI", sprintf "#sql$1_$2%x.MYI", hex($3)+1; symlink "$ENV{datadir}/test/d1.MYI", sprintf "#sql$1_$2%x.MAI", hex($3)+1; symlink "$ENV{datadir}/test/d1.MYI", sprintf "#sql$1_$2%x.MAI", hex($3)+2; + symlink "$ENV{datadir}/test/d1.MYI", sprintf "#sql$1_$2%x.MAI", hex($3)+3; symlink "$ENV{datadir}/test/d1.MYI", "#sql_$1_0.MAI"; } EOF diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test index d73e453ce96..b6a95c2c9be 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test @@ -43,10 +43,7 @@ DROP TABLE t1; set @@SESSION.SQL_LOG_BIN = 1; --echo # Step-3: Execute MYSQL_BINLOG with --stop-never and source it to mysql client. ---write_file $MYSQL_TMP_DIR/mysqlbinlog_stop_never.sh -(`$MYSQL_BINLOG --read-from-remote-server --stop-never --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 | $MYSQL --user=root --protocol=tcp --host=127.0.0.1 --port=$MASTER_MYPORT`) < /dev/null > /dev/null 2>&1 & -EOF ---exec /bin/bash $MYSQL_TMP_DIR/mysqlbinlog_stop_never.sh +--exec ($MYSQL_BINLOG --read-from-remote-server --stop-never --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 | $MYSQL --user=root --protocol=tcp --host=127.0.0.1 --port=$MASTER_MYPORT) < /dev/null > /dev/null 2>&1 & --echo # Step-4: Wait till dump thread transfer is completed. let $wait_condition= SELECT id from information_schema.processlist where processlist.command like '%Binlog%' and state like '%Master has sent%'; @@ -62,5 +59,3 @@ source include/wait_until_rows_count.inc; --source include/stop_dump_threads.inc DROP TABLE t1; ---remove_file $MYSQL_TMP_DIR/mysqlbinlog_stop_never.sh - diff --git a/mysql-test/suite/perfschema/include/socket_ipv6.inc b/mysql-test/suite/perfschema/include/socket_ipv6.inc index dd077a12c7a..0c9f47abe47 100644 --- a/mysql-test/suite/perfschema/include/socket_ipv6.inc +++ b/mysql-test/suite/perfschema/include/socket_ipv6.inc @@ -20,6 +20,7 @@ let $check_ipv6_just_check= 1; #============================================================================== --disable_query_log --disable_result_log +--disable_connect_log --disable_abort_on_error let $check_ipv6_supported= 1; @@ -44,6 +45,7 @@ if(!$mysql_errno) connection default; --enable_abort_on_error +--enable_connect_log --enable_result_log --enable_query_log @@ -62,6 +64,7 @@ let $check_ipv4_mapped_just_check= 1; #============================================================================== --disable_query_log --disable_result_log +--disable_connect_log --disable_abort_on_error let $check_ipv4_mapped_supported= 1; @@ -86,6 +89,7 @@ if(!$mysql_errno) connection default; --enable_abort_on_error +--enable_connect_log --enable_result_log --enable_query_log diff --git a/mysql-test/suite/perfschema/r/socket_connect.result b/mysql-test/suite/perfschema/r/socket_connect.result index 304521b044f..cbb83b94891 100644 --- a/mysql-test/suite/perfschema/r/socket_connect.result +++ b/mysql-test/suite/perfschema/r/socket_connect.result @@ -1,7 +1,6 @@ #============================================================================== # Establish the level of IPV6 support #============================================================================== -connection default; #============================================================================== # Get hostname, port number #============================================================================== diff --git a/mysql-test/suite/perfschema/r/socket_summary_by_event_name_func.result b/mysql-test/suite/perfschema/r/socket_summary_by_event_name_func.result index 455b6a2ad00..4fd3a4a237c 100644 --- a/mysql-test/suite/perfschema/r/socket_summary_by_event_name_func.result +++ b/mysql-test/suite/perfschema/r/socket_summary_by_event_name_func.result @@ -1,7 +1,6 @@ #============================================================================== # Establish the level of IPV6 support #============================================================================== -connection default; #============================================================================== # Get hostname, port number #============================================================================== diff --git a/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test b/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test index 42bcb3e4d70..445be52a089 100644 --- a/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test +++ b/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test @@ -38,8 +38,6 @@ # prepared statement. --source include/no_protocol.inc -set global session_track_schema=FALSE; - #=================================== # Set IP address defaults with respect to IPV6 support # @@ -73,6 +71,7 @@ if($my_socket_debug) --echo IPV6=$check_ipv6_supported, IPV4_MAPPED = $check_ipv4_mapped_supported, LOCALHOST = $my_localhost } #=================================== +set global session_track_schema=FALSE; --echo # The logging of commands and result sets is mostly disabled. --echo # There are some messages which help to observe the progress of the test. From db47855eb7ebc680950a96d02122287793a7d10c Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Tue, 26 Apr 2022 10:36:41 +0300 Subject: [PATCH 76/94] MDEV-12275: Add switch '--silent' to SySV init upgrade Debian script debian-start upgrades database (which can be huge) and prints lots of unnecessary information (not errors). Add '--silent' to only sport possible errors --- debian/additions/debian-start | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/additions/debian-start b/debian/additions/debian-start index 7940bbe68a5..d22463dc95c 100755 --- a/debian/additions/debian-start +++ b/debian/additions/debian-start @@ -15,7 +15,7 @@ fi MYSQL="/usr/bin/mysql --defaults-file=/etc/mysql/debian.cnf" MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" -MYUPGRADE="/usr/bin/mysql_upgrade --defaults-extra-file=/etc/mysql/debian.cnf --version-check" +MYUPGRADE="/usr/bin/mysql_upgrade --defaults-extra-file=/etc/mysql/debian.cnf --version-check --silent" MYCHECK="/usr/bin/mysqlcheck --defaults-file=/etc/mysql/debian.cnf" MYCHECK_SUBJECT="WARNING: mysqlcheck has found corrupt tables" MYCHECK_PARAMS="--all-databases --fast --silent" From 06562b84f65fe5089288f3ca180d06361bb40c8e Mon Sep 17 00:00:00 2001 From: Tuukka Pasanen Date: Fri, 22 Apr 2022 09:54:08 +0300 Subject: [PATCH 77/94] MDEV-28388: As Travis is not used anymore remove configurations files As Travis is not used anymore for CI is not wise to keep untested CI files laying around that someone can base their effort to update un-used files. --- .travis.compiler.sh | 51 ------------ .travis.yml | 194 -------------------------------------------- 2 files changed, 245 deletions(-) delete mode 100755 .travis.compiler.sh delete mode 100644 .travis.yml diff --git a/.travis.compiler.sh b/.travis.compiler.sh deleted file mode 100755 index 6b8de374219..00000000000 --- a/.travis.compiler.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh -set -v -x - -# Exclude modules from build not directly affecting the current -# test suites found in $MYSQL_TEST_SUITES, to conserve job time -# as well as disk usage - -function exclude_modules() { -# excludes for all -CMAKE_OPT="${CMAKE_OPT} -DPLUGIN_TOKUDB=NO -DPLUGIN_MROONGA=NO -DPLUGIN_SPIDER=NO -DPLUGIN_OQGRAPH=NO -DPLUGIN_PERFSCHEMA=NO -DPLUGIN_SPHINX=NO" -# exclude storage engines not being tested in current job -if [[ ! "${MYSQL_TEST_SUITES}" =~ "archive" ]]; then - CMAKE_OPT="${CMAKE_OPT} -DPLUGIN_ARCHIVE=NO" -fi -if [[ ! "${MYSQL_TEST_SUITES}" =~ "rocksdb" ]]; then - CMAKE_OPT="${CMAKE_OPT} -DPLUGIN_ROCKSDB=NO" -fi -} - -if [[ "${TRAVIS_OS_NAME}" == 'linux' ]]; then - TEST_CASE_TIMEOUT=2 - exclude_modules; - if which ccache ; then - CMAKE_OPT="${CMAKE_OPT} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" - ccache --max-size=2200M - fi - if [[ "${CXX}" == 'clang++' ]]; then - export CXX CC=${CXX/++/} - elif [[ "${CXX}" == 'g++' ]]; then - export CXX=g++-${CC_VERSION} - export CC=gcc-${CC_VERSION} - fi - if [[ ${CC_VERSION} == 6 ]]; then - wget http://mirrors.kernel.org/ubuntu/pool/universe/p/percona-xtradb-cluster-galera-2.x/percona-xtradb-cluster-galera-2.x_165-0ubuntu1_amd64.deb ; - ar vx percona-xtradb-cluster-galera-2.x_165-0ubuntu1_amd64.deb - tar -xJvf data.tar.xz - export WSREP_PROVIDER=$PWD/usr/lib/libgalera_smm.so - MYSQL_TEST_SUITES="${MYSQL_TEST_SUITES},wsrep" - fi -fi - -if [[ "${TRAVIS_OS_NAME}" == 'osx' ]]; then - TEST_CASE_TIMEOUT=20 - exclude_modules; - CMAKE_OPT="${CMAKE_OPT} -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl" - if which ccache ; then - CMAKE_OPT="${CMAKE_OPT} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache" - fi -fi - -set +v +x diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 809a08fd6a2..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,194 +0,0 @@ -# vim ft=yaml -# travis-ci.org definition - -sudo: false -dist: trusty - -git: - depth: 2 - -language: cpp -os: - - linux - - osx -osx_image: xcode12u -compiler: - - gcc - - clang - -cache: - timeout: 500 - apt: true - ccache: true - -env: - matrix: - - CC_VERSION=5 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=main - - CC_VERSION=5 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=archive,optimizer_unfixed_bugs,parts,sys_vars,unit,vcol,innodb,innodb_gis,innodb_zip,innodb_fts - - CC_VERSION=5 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=rpl - - CC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=binlog,binlog_encryption,encryption - - CC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=rocksdb,versioning - - CC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=csv,federated,funcs_1,funcs_2,gcol,handler,heap,json,maria,perfschema,plugins,multi_source,roles - -matrix: - exclude: - - os: osx - compiler: gcc - include: - - os: linux - compiler: gcc - env: - - DebPackages - addons: - apt: - packages: # make sure these match debian/control contents - - bison - - chrpath - - cmake - - debhelper - - dh-apparmor - - dh-exec - - dpatch - - gdb - - libaio-dev - - libboost-dev - - libcurl3-dev - - libdbd-mysql - - libjudy-dev - - libncurses5-dev - - libpam0g-dev - - libpcre3-dev - - libreadline-gplv2-dev - - libstemmer-dev - - libssl-dev - - libnuma-dev - - libxml2-dev - - lsb-release - - perl - - po-debconf - - psmisc - - zlib1g-dev - - libcrack2-dev - - cracklib-runtime - - libjemalloc-dev - - libsnappy-dev - - liblzma-dev - - libzmq-dev - - libdistro-info-perl - - uuid-dev - - devscripts - - fakeroot - script: - - ${CC} --version ; ${CXX} --version - # https://github.com/travis-ci/travis-ci/issues/7062 - /run/shm isn't writable or executable - # in trusty containers - - export MTR_MEM=/tmp - - env DEB_BUILD_OPTIONS="parallel=4" debian/autobake-deb.sh; - - ccache --show-stats - # Until OSX becomes a bit more stable: MDEV-12435 MDEV-16213 - allow_failures: - - os: osx - compiler: clang - env: CC_VERSION=5 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=rpl - - os: osx - compiler: clang - env: CC_VERSION=5 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=main - - os: osx - compiler: clang - env: CC_VERSION=5 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=archive,optimizer_unfixed_bugs,parts,sys_vars,unit,vcol,innodb,innodb_gis,innodb_zip,innodb_fts - - os: osx - compiler: clang - env: CC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=binlog,binlog_encryption,encryption - - os: osx - compiler: clang - env: CC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=rocksdb,versioning - - os: osx - compiler: clang - env: CC_VERSION=6 TYPE=RelWithDebInfo MYSQL_TEST_SUITES=csv,federated,funcs_1,funcs_2,gcol,handler,heap,json,maria,perfschema,plugins,multi_source,roles - -addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 - - llvm-toolchain-trusty-6.0 - packages: # make sure these include all compilers and all build dependencies (see list above) - - gcc-5 - - g++-5 - - gcc-6 - - g++-6 - - clang-5.0 - - llvm-5.0-dev - - clang-6.0 - - llvm-6.0-dev - - bison - - chrpath - - cmake - - gdb - - libaio-dev - - libboost-dev - - libcurl3-dev - - libdbd-mysql - - libjudy-dev - - libncurses5-dev - - libpam0g-dev - - libpcre3-dev - - libreadline-gplv2-dev - - libstemmer-dev - - libssl-dev - - libnuma-dev - - libxml2-dev - - lsb-release - - perl - - psmisc - - zlib1g-dev - - libcrack2-dev - - cracklib-runtime - - libjemalloc-dev - - libsnappy-dev - - liblzma-dev - - libzmq-dev - - uuid-dev - -# libsystemd-daemon-dev # https://github.com/travis-ci/apt-package-whitelist/issues/3882 - -before_install: - - if [[ "${TRAVIS_OS_NAME}" == 'osx' ]]; then - brew update; - brew install gnutls lz4 lzo xz snappy ccache jemalloc curl ossp-uuid pcre zstd; - brew link ccache; - export PATH="/usr/local/opt/ccache/libexec:$PATH"; - fi - -before_script: - - df -h - - ccache --version - - ccache --show-stats - -script: -# following modules are disabled after sourcing .travis.compiler.sh: -# clang disabled: mroonga just generates too many warnings with clang and travis stops the job -# cland disabled: tokudb has fatal warnings -# gcc/rpl: tokudb and mroonga - - source .travis.compiler.sh - - cmake . - -DCMAKE_BUILD_TYPE=${TYPE} - ${CMAKE_OPT} - -DWITH_SSL=system -DWITH_ZLIB=system - - make -j 4 - - cd mysql-test - - travis_wait 30 ./mtr --force --max-test-fail=20 --parallel=4 --testcase-timeout=${TEST_CASE_TIMEOUT} - --suite=${MYSQL_TEST_SUITES} - --skip-test-list=unstable-tests - --skip-test=binlog.binlog_unsafe - - ccache --show-stats - - df -h - -notifications: - irc: - channels: - - "chat.freenode.net#maria" - on_success: never # [always|never|change] - on_failure: never - template: - - "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}" From bee3e96da35a5811b6815c4299d87352d2bde95c Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 5 May 2022 10:11:03 +0200 Subject: [PATCH 78/94] 5.7.38 --- storage/perfschema/pfs_engine_table.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc index 232f427dd4d..dd380879fdb 100644 --- a/storage/perfschema/pfs_engine_table.cc +++ b/storage/perfschema/pfs_engine_table.cc @@ -862,7 +862,8 @@ static bool allow_drop_table_privilege() { assert(thd->lex != NULL); if ((thd->lex->sql_command != SQLCOM_TRUNCATE) && - (thd->lex->sql_command != SQLCOM_GRANT)) { + (thd->lex->sql_command != SQLCOM_GRANT) && + (thd->lex->sql_command != SQLCOM_REVOKE)) { return false; } From 8dbfaa2aa4d6158f81bba3f5a46d683912b06868 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 4 May 2022 12:24:14 +0300 Subject: [PATCH 79/94] MDEV-28437: Assertion `!eliminated' failed in Item_subselect::exec (This is the assert that was added in fix for MDEV-26047) Table elimination may remove an ON expression from an outer join. However SELECT_LEX::update_used_tables() will still call item->walk(&Item::eval_not_null_tables) for eliminated expressions. If the subquery is constant and cheap Item_cond_and will attempt to evaluate it, which will trigger an assert. The fix is not to call update_used_tables() or eval_not_null_tables() for ON expressions that were eliminated. --- mysql-test/r/subselect_innodb.result | 11 +++++++++++ mysql-test/t/subselect_innodb.test | 14 ++++++++++++++ sql/sql_lex.cc | 9 ++++++--- sql/sql_select.cc | 2 +- sql/sql_select.h | 2 ++ 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index 4796245f8e3..fd75cce00b2 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -661,3 +661,14 @@ group by (select a),(select 1) ); 1 drop table t1; +# +# MDEV-28437: Assertion `!eliminated' failed in Item_subselect::exec +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (3),(4); +SELECT 1 IN (SELECT a FROM t1 LEFT JOIN t2 ON (a = b AND EXISTS (SELECT * FROM t1))); +1 IN (SELECT a FROM t1 LEFT JOIN t2 ON (a = b AND EXISTS (SELECT * FROM t1))) +1 +drop table t1,t2; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index f42ac514d53..5d8f3dcc1b5 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -655,3 +655,17 @@ select 1 from t1 where not exists --enable_warnings drop table t1; +--echo # +--echo # MDEV-28437: Assertion `!eliminated' failed in Item_subselect::exec +--echo # +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (3),(4); + +SELECT 1 IN (SELECT a FROM t1 LEFT JOIN t2 ON (a = b AND EXISTS (SELECT * FROM t1))); + +drop table t1,t2; + +# End of 10.2 tests + diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 22ee8801e3a..8e718f2a942 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4229,7 +4229,7 @@ void SELECT_LEX::update_used_tables() } } while ((embedding= embedding->embedding)); - if (tl->on_expr) + if (tl->on_expr && !is_eliminated_table(join->eliminated_tables, tl)) { tl->on_expr->update_used_tables(); tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL); @@ -4253,8 +4253,11 @@ void SELECT_LEX::update_used_tables() if (embedding->on_expr && embedding->nested_join->join_list.head() == tl) { - embedding->on_expr->update_used_tables(); - embedding->on_expr->walk(&Item::eval_not_null_tables, 0, NULL); + if (!is_eliminated_table(join->eliminated_tables, embedding)) + { + embedding->on_expr->update_used_tables(); + embedding->on_expr->walk(&Item::eval_not_null_tables, 0, NULL); + } } tl= embedding; embedding= tl->embedding; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e9d81417ee6..82792bbc723 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -25495,7 +25495,7 @@ static void print_table_array(THD *thd, too) */ -static bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl) +bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl) { return eliminated_tables && ((tbl->table && (tbl->table->map & eliminated_tables)) || diff --git a/sql/sql_select.h b/sql/sql_select.h index f41c0df5ad8..8b61645710e 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2330,4 +2330,6 @@ int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort); JOIN_TAB *first_explain_order_tab(JOIN* join); JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab); +bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl); + #endif /* SQL_SELECT_INCLUDED */ From 84e32eff5b050b69649db942de5a74f1b3d24e6d Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Thu, 5 May 2022 18:58:00 +0300 Subject: [PATCH 80/94] MDEV-28437: Assertion `!eliminated' failed: Part #2 In SELECT_LEX::update_used_tables(), do not run the loop setting tl->table->maybe_null when tl is an eliminated table (Rationale: First, with current table elimination, tl already has maybe_null=1. Second, one should not care what flags eliminated tables had) --- sql/sql_lex.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 8e718f2a942..6191e174298 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4219,16 +4219,20 @@ void SELECT_LEX::update_used_tables() while ((tl= ti++)) { TABLE_LIST *embedding= tl; - do + if (!is_eliminated_table(join->eliminated_tables, tl)) { - bool maybe_null; - if ((maybe_null= MY_TEST(embedding->outer_join))) + do { - tl->table->maybe_null= maybe_null; - break; + bool maybe_null; + if ((maybe_null= MY_TEST(embedding->outer_join))) + { + tl->table->maybe_null= maybe_null; + break; + } } + while ((embedding= embedding->embedding)); } - while ((embedding= embedding->embedding)); + if (tl->on_expr && !is_eliminated_table(join->eliminated_tables, tl)) { tl->on_expr->update_used_tables(); From 20ae4816bba712a3faa0110c973e197d92f43b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 6 May 2022 09:30:17 +0300 Subject: [PATCH 81/94] MDEV-28478: INSERT into SPATIAL INDEX in TEMPORARY table writes log row_ins_sec_index_entry_low(): If a separate mini-transaction is needed to adjust the minimum bounding rectangle (MBR) in the parent page, we must disable redo logging if the table is a temporary table. For temporary tables, no log is supposed to be written, because the temporary tablespace will be reinitialized on server restart. rtr_update_mbr_field(): Plug a memory leak. --- .../suite/innodb_gis/r/rtree_split.result | 7 ------- .../suite/innodb_gis/r/rtree_temporary.result | 14 ++++++++++++++ mysql-test/suite/innodb_gis/t/rtree_split.test | 8 -------- .../suite/innodb_gis/t/rtree_temporary.test | 18 ++++++++++++++++++ storage/innobase/gis/gis0rtree.cc | 3 ++- storage/innobase/row/row0ins.cc | 10 +++++++--- 6 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 mysql-test/suite/innodb_gis/r/rtree_temporary.result create mode 100644 mysql-test/suite/innodb_gis/t/rtree_temporary.test diff --git a/mysql-test/suite/innodb_gis/r/rtree_split.result b/mysql-test/suite/innodb_gis/r/rtree_split.result index 2d6e8a1dfbe..df88960ba3d 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_split.result +++ b/mysql-test/suite/innodb_gis/r/rtree_split.result @@ -61,10 +61,3 @@ select count(*) from t1 where MBRWithin(t1.c2, @g1); count(*) 57344 drop table t1; -# -# MDEV-27417 Spatial index tries to update -# change buffer bookkeeping page -# -CREATE TEMPORARY TABLE t1 (c POINT NOT NULL, SPATIAL(c)) ENGINE=InnoDB; -INSERT INTO t1 SELECT PointFromText('POINT(0 0)') FROM seq_1_to_366; -DROP TABLE t1; diff --git a/mysql-test/suite/innodb_gis/r/rtree_temporary.result b/mysql-test/suite/innodb_gis/r/rtree_temporary.result new file mode 100644 index 00000000000..5ce02c881cc --- /dev/null +++ b/mysql-test/suite/innodb_gis/r/rtree_temporary.result @@ -0,0 +1,14 @@ +# +# MDEV-27417 Spatial index tries to update +# change buffer bookkeeping page +# +CREATE TEMPORARY TABLE t1 (c POINT NOT NULL, SPATIAL(c)) ENGINE=InnoDB; +INSERT INTO t1 SELECT PointFromText('POINT(0 0)') FROM seq_1_to_366; +DROP TABLE t1; +# +# MDEV-28478 Assertion mtr->get_log_mode() == MTR_LOG_NO_REDO +# +CREATE TEMPORARY TABLE t1 (c POINT NOT NULL,SPATIAL (c)) ENGINE=InnoDB; +INSERT INTO t1 SELECT POINT(0,0) FROM seq_1_to_366; +INSERT INTO t1 VALUES (POINT(1e-270,1e-130)); +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_gis/t/rtree_split.test b/mysql-test/suite/innodb_gis/t/rtree_split.test index dd46d1ecc4d..af626dba6b7 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_split.test +++ b/mysql-test/suite/innodb_gis/t/rtree_split.test @@ -72,11 +72,3 @@ select count(*) from t1 where MBRWithin(t1.c2, @g1); # Clean up. drop table t1; - ---echo # ---echo # MDEV-27417 Spatial index tries to update ---echo # change buffer bookkeeping page ---echo # -CREATE TEMPORARY TABLE t1 (c POINT NOT NULL, SPATIAL(c)) ENGINE=InnoDB; -INSERT INTO t1 SELECT PointFromText('POINT(0 0)') FROM seq_1_to_366; -DROP TABLE t1; diff --git a/mysql-test/suite/innodb_gis/t/rtree_temporary.test b/mysql-test/suite/innodb_gis/t/rtree_temporary.test new file mode 100644 index 00000000000..5c4df251970 --- /dev/null +++ b/mysql-test/suite/innodb_gis/t/rtree_temporary.test @@ -0,0 +1,18 @@ +--source include/have_innodb.inc +--source include/have_sequence.inc + +--echo # +--echo # MDEV-27417 Spatial index tries to update +--echo # change buffer bookkeeping page +--echo # +CREATE TEMPORARY TABLE t1 (c POINT NOT NULL, SPATIAL(c)) ENGINE=InnoDB; +INSERT INTO t1 SELECT PointFromText('POINT(0 0)') FROM seq_1_to_366; +DROP TABLE t1; + +--echo # +--echo # MDEV-28478 Assertion mtr->get_log_mode() == MTR_LOG_NO_REDO +--echo # +CREATE TEMPORARY TABLE t1 (c POINT NOT NULL,SPATIAL (c)) ENGINE=InnoDB; +INSERT INTO t1 SELECT POINT(0,0) FROM seq_1_to_366; +INSERT INTO t1 VALUES (POINT(1e-270,1e-130)); +DROP TABLE t1; diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index 50071bcfae4..b18642b0e3c 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, 2020, MariaDB Corporation. +Copyright (c) 2019, 2022, 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 @@ -376,6 +376,7 @@ rtr_update_mbr_field( if (!rtr_update_mbr_field_in_place(index, rec, offsets, mbr, mtr)) { + mem_heap_free(heap); return(false); } diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index cbe6577c02a..0c0214b009e 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2021, MariaDB Corporation. +Copyright (c) 2016, 2022, 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 @@ -2900,8 +2900,12 @@ row_ins_sec_index_entry_low( rtr_init_rtr_info(&rtr_info, false, &cursor, index, false); rtr_info_update_btr(&cursor, &rtr_info); - mtr_start(&mtr); - mtr.set_named_space(index->space); + mtr.start(); + if (index->table->is_temporary()) { + mtr.set_log_mode(MTR_LOG_NO_REDO); + } else { + mtr.set_named_space(index->space); + } search_mode &= ulint(~BTR_MODIFY_LEAF); search_mode |= BTR_MODIFY_TREE; err = btr_cur_search_to_nth_level( From 624cb9735e737ca3392957e2db2171c2957cf282 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Fri, 6 May 2022 10:34:27 +0300 Subject: [PATCH 82/94] Update test results after fix for MDEV-19398 --- .../encryption/r/tempfiles_encrypted.result | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/mysql-test/suite/encryption/r/tempfiles_encrypted.result b/mysql-test/suite/encryption/r/tempfiles_encrypted.result index f7b5081f625..b166d08bb92 100644 --- a/mysql-test/suite/encryption/r/tempfiles_encrypted.result +++ b/mysql-test/suite/encryption/r/tempfiles_encrypted.result @@ -4244,6 +4244,48 @@ SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ()); ERROR HY000: Expression #1 of ORDER BY contains aggregate function and applies to a UNION DROP TABLE t1; # +# MDEV-19398: Assertion `item1->type() == Item::FIELD_ITEM && +# item2->type() == Item::FIELD_ITEM' failed in compare_order_elements +# +CREATE TABLE t1 ( id varchar(10)); +INSERT INTO t1 values (1),(2),(3); +SELECT +dense_rank() over (ORDER BY avg(1)+3), +rank() over (ORDER BY avg(1)) +FROM t1 +GROUP BY nullif(id, 15532); +dense_rank() over (ORDER BY avg(1)+3) rank() over (ORDER BY avg(1)) +1 1 +1 1 +1 1 +SELECT +dense_rank() over (ORDER BY avg(1)), +rank() over (ORDER BY avg(1)) +FROM t1 +GROUP BY nullif(id, 15532); +dense_rank() over (ORDER BY avg(1)) rank() over (ORDER BY avg(1)) +1 1 +1 1 +1 1 +drop table t1; +CREATE TABLE t1 ( a char(25), b text); +INSERT INTO t1 VALUES ('foo','bar'); +SELECT +SUM(b) OVER (PARTITION BY a), +ROW_NUMBER() OVER (PARTITION BY b) +FROM t1 +GROUP BY +LEFT((SYSDATE()), 'foo') +WITH ROLLUP; +SUM(b) OVER (PARTITION BY a) ROW_NUMBER() OVER (PARTITION BY b) +NULL 1 +NULL 1 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: 'foo' +Warning 1292 Truncated incorrect INTEGER value: 'foo' +drop table t1; +# +# # End of 10.2 tests # # From 141ab971d8d31968ac7104e71801c6ec75638af3 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 4 May 2022 19:51:26 +0200 Subject: [PATCH 83/94] MDEV-28402 ASAN heap-use-after-free in create_tmp_table, Assertion `l_offset >= 0 && table->s->rec_buff_length - l_offset > 0' Make default() function follow Item_field and use get_tmp_table_item() for change_to_use_tmp_fields(). --- mysql-test/r/default.result | 18 ++++++++++++++++++ mysql-test/t/default.test | 17 +++++++++++++++++ sql/sql_select.cc | 8 +++++--- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index 0c91e6b7e08..1c792983638 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -3413,4 +3413,22 @@ SELECT 1 FROM t1 GROUP BY DEFAULT(pk); 1 1 DROP TABLE t1; +# +# MDEV-28402: ASAN heap-use-after-free in create_tmp_table, +# Assertion `l_offset >= 0 && table->s->rec_buff_length - l_offset > 0' +# +CREATE TABLE t (a INT, KEY (a)); +INSERT INTO t VALUES (1),(2); +SELECT DISTINCT DEFAULT(a), CASE a WHEN 0 THEN 1 ELSE 2 END FROM t GROUP BY a WITH ROLLUP; +DEFAULT(a) CASE a WHEN 0 THEN 1 ELSE 2 END +NULL 2 +DROP TABLE t; +CREATE TABLE t (a INT, KEY (a)); +INSERT INTO t VALUES (1),(2); +CREATE ALGORITHM=TEMPTABLE VIEW v AS SELECT * FROM t; +SELECT DISTINCT DEFAULT(a), CASE a WHEN 0 THEN 1 ELSE 2 END FROM v GROUP BY a WITH ROLLUP; +DEFAULT(a) CASE a WHEN 0 THEN 1 ELSE 2 END +NULL 2 +DROP TABLE t; +DROP VIEW v; # end of 10.2 test diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index e0233a3929a..3bc373d0313 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -2125,4 +2125,21 @@ CREATE TABLE t1 (pk varchar(36) DEFAULT uuid()); INSERT INTO t1 VALUES (),(); SELECT 1 FROM t1 GROUP BY DEFAULT(pk); DROP TABLE t1; + + +--echo # +--echo # MDEV-28402: ASAN heap-use-after-free in create_tmp_table, +--echo # Assertion `l_offset >= 0 && table->s->rec_buff_length - l_offset > 0' +--echo # +CREATE TABLE t (a INT, KEY (a)); +INSERT INTO t VALUES (1),(2); +SELECT DISTINCT DEFAULT(a), CASE a WHEN 0 THEN 1 ELSE 2 END FROM t GROUP BY a WITH ROLLUP; +DROP TABLE t; + +CREATE TABLE t (a INT, KEY (a)); +INSERT INTO t VALUES (1),(2); +CREATE ALGORITHM=TEMPTABLE VIEW v AS SELECT * FROM t; +SELECT DISTINCT DEFAULT(a), CASE a WHEN 0 THEN 1 ELSE 2 END FROM v GROUP BY a WITH ROLLUP; +DROP TABLE t; +DROP VIEW v; --echo # end of 10.2 test diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 82792bbc723..760730d799c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -23727,12 +23727,14 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, for (uint i= 0; (item= it++); i++) { Field *field; - if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) || + enum Item::Type item_type= item->type(); + if ((item->with_sum_func && item_type != Item::SUM_FUNC_ITEM) || item->with_window_func) item_field= item; - else if (item->type() == Item::FIELD_ITEM) + else if (item_type == Item::FIELD_ITEM || + item_type == Item::DEFAULT_VALUE_ITEM) item_field= item->get_tmp_table_item(thd); - else if (item->type() == Item::FUNC_ITEM && + else if (item_type == Item::FUNC_ITEM && ((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC) { field= item->get_tmp_table_field(); From 9fe3bc2aa881118def3987358935e77c39b9fdb8 Mon Sep 17 00:00:00 2001 From: Hartmut Holzgraefe Date: Fri, 29 Apr 2022 10:10:02 +0200 Subject: [PATCH 84/94] MDEV-27816 Set sql_mode before DROP IF EXISTS already Previously the correct SQL mode for a stored routine or package was only set before doing the CREATE part, this worked out for PROCEDUREs and FUNCTIONs, but with ORACLE mode specific PACKAGEs the DROP also only works in ORACLE mode. Moving the setting of the sql_mode a few lines up to happen right before the DROP statement is writen fixes this. --- client/mysqldump.c | 6 +-- mysql-test/main/ddl_i18n_koi8r.result | 16 +++---- mysql-test/main/ddl_i18n_utf8.result | 16 +++---- mysql-test/main/mysqldump-compat-102.result | 4 +- mysql-test/main/mysqldump-nl.result | 4 +- mysql-test/main/mysqldump.result | 50 +++++++++++++++------ mysql-test/main/mysqldump.test | 31 +++++++++++++ mysql-test/suite/roles/definer.result | 24 +++++----- 8 files changed, 102 insertions(+), 49 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 20f8278c9c2..991c3f528b4 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2757,6 +2757,9 @@ static uint dump_routines_for_db(char *db) create_caption_xml[i]); continue; } + + switch_sql_mode(sql_file, ";", row[1]); + if (opt_drop) fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n", routine_type[i], routine_name); @@ -2796,9 +2799,6 @@ static uint dump_routines_for_db(char *db) "--\n"); } - - switch_sql_mode(sql_file, ";", row[1]); - fprintf(sql_file, "DELIMITER ;;\n" "%s ;;\n" diff --git a/mysql-test/main/ddl_i18n_koi8r.result b/mysql-test/main/ddl_i18n_koi8r.result index 612a4a4cbff..66c85f12034 100644 --- a/mysql-test/main/ddl_i18n_koi8r.result +++ b/mysql-test/main/ddl_i18n_koi8r.result @@ -723,6 +723,8 @@ utf8_general_ci utf8_general_ci CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest1`; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -730,8 +732,6 @@ ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = koi8r */ ; /*!50003 SET character_set_results = koi8r */ ; /*!50003 SET collation_connection = koi8r_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`( INOUT 1 CHAR(10), @@ -757,6 +757,8 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -764,8 +766,6 @@ ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = koi8r */ ; /*!50003 SET character_set_results = koi8r */ ; /*!50003 SET collation_connection = koi8r_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p2`( INOUT 1 CHAR(10) CHARACTER SET utf8, @@ -799,6 +799,8 @@ ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ; CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest2`; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -806,8 +808,6 @@ ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = koi8r */ ; /*!50003 SET character_set_results = koi8r */ ; /*!50003 SET collation_connection = koi8r_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p3`( INOUT 1 CHAR(10), @@ -833,6 +833,8 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -840,8 +842,6 @@ ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = koi8r */ ; /*!50003 SET character_set_results = koi8r */ ; /*!50003 SET collation_connection = koi8r_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p4`( INOUT 1 CHAR(10) CHARACTER SET utf8, diff --git a/mysql-test/main/ddl_i18n_utf8.result b/mysql-test/main/ddl_i18n_utf8.result index 2be5413f182..78ef487cdaf 100644 --- a/mysql-test/main/ddl_i18n_utf8.result +++ b/mysql-test/main/ddl_i18n_utf8.result @@ -723,6 +723,8 @@ utf8_general_ci utf8_general_ci CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest1`; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -730,8 +732,6 @@ ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = utf8 */ ; /*!50003 SET character_set_results = utf8 */ ; /*!50003 SET collation_connection = utf8_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`( INOUT парам1 CHAR(10), @@ -757,6 +757,8 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -764,8 +766,6 @@ ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = utf8 */ ; /*!50003 SET character_set_results = utf8 */ ; /*!50003 SET collation_connection = utf8_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p2`( INOUT парам1 CHAR(10) CHARACTER SET utf8, @@ -799,6 +799,8 @@ ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ; CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER SET cp866 */; USE `mysqltest2`; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -806,8 +808,6 @@ ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = utf8 */ ; /*!50003 SET character_set_results = utf8 */ ; /*!50003 SET collation_connection = utf8_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p3`( INOUT парам1 CHAR(10), @@ -833,6 +833,8 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -840,8 +842,6 @@ ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*!50003 SET character_set_client = utf8 */ ; /*!50003 SET character_set_results = utf8 */ ; /*!50003 SET collation_connection = utf8_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p4`( INOUT парам1 CHAR(10) CHARACTER SET utf8, diff --git a/mysql-test/main/mysqldump-compat-102.result b/mysql-test/main/mysqldump-compat-102.result index b58c33927cf..1789f74f034 100644 --- a/mysql-test/main/mysqldump-compat-102.result +++ b/mysql-test/main/mysqldump-compat-102.result @@ -77,6 +77,8 @@ $$ -- -- Dumping routines for database 'db1_mdev17429' -- +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; /*!50003 DROP PROCEDURE IF EXISTS `p1` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -84,8 +86,6 @@ $$ /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; DELIMITER ;; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"(a INT) AS BEGIN diff --git a/mysql-test/main/mysqldump-nl.result b/mysql-test/main/mysqldump-nl.result index d2d0e09546b..89fb3144867 100644 --- a/mysql-test/main/mysqldump-nl.result +++ b/mysql-test/main/mysqldump-nl.result @@ -64,14 +64,14 @@ SET character_set_client = @saved_cs_client; -- Dumping routines for database 'mysqltest1 -- 1tsetlqsym' -- +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `sp`() select * from `v1 diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index 9f1432f8f70..b5ab596370e 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -2777,6 +2777,8 @@ LOCK TABLES `t1` WRITE; INSERT INTO `t1` VALUES (1),(2),(3),(4),(5); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP FUNCTION IF EXISTS `bug9056_func1` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -2784,8 +2786,6 @@ UNLOCK TABLES; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11) RETURN a+b ;; @@ -2794,6 +2794,8 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP FUNCTION IF EXISTS `bug9056_func2` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -2801,8 +2803,6 @@ DELIMITER ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1) CHARSET latin1 begin @@ -2814,6 +2814,8 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI' */ ; /*!50003 DROP PROCEDURE IF EXISTS `a'b` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -2821,8 +2823,6 @@ DELIMITER ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI' */ ; DELIMITER ;; CREATE DEFINER="root"@"localhost" PROCEDURE "a'b"() select 1 ;; @@ -2831,6 +2831,8 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc1` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -2838,8 +2840,6 @@ DELIMITER ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT) BEGIN SELECT a+b INTO c; end ;; @@ -2848,6 +2848,8 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc2` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -2855,8 +2857,6 @@ DELIMITER ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `bug9056_proc2`(OUT a INT) BEGIN @@ -3852,14 +3852,14 @@ create procedure mysqldump_test_db.sp1() select 'hello'; -- insufficient privileges to SHOW CREATE PROCEDURE `sp1` -- does user2 have permissions on mysql.proc? +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`user1`@`%` PROCEDURE `sp1`() select 'hello' ;; @@ -5427,6 +5427,8 @@ CREATE DATABASE `a\"'``b`; USE `a\"'``b`; CREATE PROCEDURE p1() BEGIN END; ALTER DATABASE `a\"'``b` COLLATE utf8_general_ci; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = '' */ ; ALTER DATABASE `a\"'``b` CHARACTER SET latin1 COLLATE latin1_swedish_ci ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -5434,8 +5436,6 @@ ALTER DATABASE `a\"'``b` CHARACTER SET latin1 COLLATE latin1_swedish_ci ; /*!50003 SET character_set_client = utf8 */ ; /*!50003 SET character_set_results = utf8 */ ; /*!50003 SET collation_connection = utf8_general_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = '' */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() BEGIN END ;; @@ -6328,4 +6328,26 @@ SETVAL(`seq_t_i`, 1, 0) 1 DROP DATABASE IF EXISTS test1; DROP DATABASE IF EXISTS test2; +# +# MDEV-27186 Server fails to load a dump, taken on the same version +# Oracle mode with packages +# +CREATE DATABASE test1; +CREATE DATABASE test2; +USE test1; +SET @save_sql_mode=@@sql_mode; +SET sql_mode=ORACLE; +CREATE OR REPLACE PACKAGE pkg AS +END; +$$ +# Dump database 1 +# Restore from database 1 to database 2 +use test2; +SHOW CREATE PACKAGE pkg; +Package sql_mode Create Package character_set_client collation_connection Database Collation +pkg PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT CREATE DEFINER="root"@"localhost" PACKAGE "pkg" AS +END utf8 utf8_general_ci latin1_swedish_ci +DROP DATABASE test1; +DROP DATABASE test2; +SET sql_mode=@save_sql_mode; # End of 10.3 tests diff --git a/mysql-test/main/mysqldump.test b/mysql-test/main/mysqldump.test index 3e88ff3bc39..aeae62664d9 100644 --- a/mysql-test/main/mysqldump.test +++ b/mysql-test/main/mysqldump.test @@ -2885,4 +2885,35 @@ INSERT INTO t VALUES (1,1),(2,2),(3,3),(4,4); DROP DATABASE IF EXISTS test1; DROP DATABASE IF EXISTS test2; +--echo # +--echo # MDEV-27186 Server fails to load a dump, taken on the same version +--echo # Oracle mode with packages +--echo # + +CREATE DATABASE test1; +CREATE DATABASE test2; +USE test1; +SET @save_sql_mode=@@sql_mode; +SET sql_mode=ORACLE; + +DELIMITER $$; +CREATE OR REPLACE PACKAGE pkg AS +END; +$$ + +DELIMITER ;$$ + +--echo # Dump database 1 +--exec $MYSQL_DUMP --routines test1 > $MYSQLTEST_VARDIR/tmp/dumptest1.sql +--echo # Restore from database 1 to database 2 + +--exec $MYSQL test2 < $MYSQLTEST_VARDIR/tmp/dumptest1.sql +use test2; +SHOW CREATE PACKAGE pkg; + +DROP DATABASE test1; +DROP DATABASE test2; +SET sql_mode=@save_sql_mode; +--remove_file $MYSQLTEST_VARDIR/tmp/dumptest1.sql + --echo # End of 10.3 tests diff --git a/mysql-test/suite/roles/definer.result b/mysql-test/suite/roles/definer.result index 30911265436..a5551e7dede 100644 --- a/mysql-test/suite/roles/definer.result +++ b/mysql-test/suite/roles/definer.result @@ -438,14 +438,14 @@ DELIMITER ;; /*!50003 SET collation_connection = @saved_col_connection */ ;; DELIMITER ; /*!50106 SET TIME_ZONE= @save_time_zone */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`role1` FUNCTION `fn1`() RETURNS int(11) return (select sum(a+b) from t1) ;; @@ -454,14 +454,14 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`role2` FUNCTION `fn2`() RETURNS int(11) return (select sum(a+b) from t1) ;; @@ -470,14 +470,14 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`role3`@`%` FUNCTION `fn3`() RETURNS int(11) return (select sum(a+b) from t1) ;; @@ -486,14 +486,14 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`role1` PROCEDURE `pr1`() insert t1 values (111, 222, 333) ;; @@ -502,14 +502,14 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`role2`@`%` PROCEDURE `pr2`() insert t1 values (111, 222, 333) ;; @@ -518,14 +518,14 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; CREATE DEFINER=`role3`@`%` PROCEDURE `pr3`() insert t1 values (111, 222, 333) ;; From 221ced92aa02d42d26a5a4945a0e90ba5dcbcbfa Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 6 May 2022 17:44:33 +1000 Subject: [PATCH 85/94] MDEV-4875 Can't restore a mysqldump if --add-drop-database meets general_log or slow query log when the log_output=TABLE. When this happens, we temporary disable by changing log_output until we've created the general_log and slow_log tables again. Move in xml mode until after the transaction_registry. General_log and slow_log tables where moved to be first to be dumped so that the disabling of the general/slow queries is minimal. --- client/mysqldump.c | 100 ++++++++---- mysql-test/main/mysqldump.result | 266 +++++++++++++++++++++---------- mysql-test/main/mysqldump.test | 60 +++++++ 3 files changed, 305 insertions(+), 121 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 991c3f528b4..6cdc3db3c08 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -5229,6 +5229,55 @@ int init_dumping_views(char *qdatabase __attribute__((unused))) } /* init_dumping_views */ +/* +mysql specific database initialization. + +SYNOPSIS + init_dumping_mysql_tables + + protections around dumping general/slow query log + qdatabase quoted name of the "mysql" database + +RETURN VALUES + 0 Success. + 1 Failure. +*/ +static int init_dumping_mysql_tables(char *qdatabase) +{ + DBUG_ENTER("init_dumping_mysql_tables"); + + if (opt_drop_database) + fprintf(md_result_file, + "\n/*!50106 SET @save_log_output=@@LOG_OUTPUT*/;\n" + "/*M!100203 EXECUTE IMMEDIATE IF(@@LOG_OUTPUT='TABLE' AND (@@SLOW_QUERY_LOG=1 OR @@GENERAL_LOG=1)," + "\"SET GLOBAL LOG_OUTPUT='NONE'\", \"DO 0\") */;\n"); + + DBUG_RETURN(init_dumping_tables(qdatabase)); +} + + +static void dump_first_mysql_tables(char *database) +{ + char table_type[NAME_LEN]; + char ignore_flag; + DBUG_ENTER("dump_first_mysql_tables"); + + if (!get_table_structure((char *) "general_log", + database, table_type, &ignore_flag) ) + verbose_msg("-- Warning: get_table_structure() failed with some internal " + "error for 'general_log' table\n"); + if (!get_table_structure((char *) "slow_log", + database, table_type, &ignore_flag) ) + verbose_msg("-- Warning: get_table_structure() failed with some internal " + "error for 'slow_log' table\n"); + /* general and slow query logs exist now */ + if (opt_drop_database) + fprintf(md_result_file, + "\n/*!50106 SET GLOBAL LOG_OUTPUT=@save_log_output*/;\n\n"); + DBUG_VOID_RETURN; +} + + /* Table Specific database initialization. @@ -5335,7 +5384,6 @@ static int dump_all_tables_in_db(char *database) char table_buff[NAME_LEN*2+3]; char hash_key[2*NAME_LEN+2]; /* "db.tablename" */ char *afterdot; - my_bool general_log_table_exists= 0, slow_log_table_exists=0; my_bool transaction_registry_table_exists= 0; int using_mysql_db= !my_strcasecmp(charset_info, database, "mysql"); DBUG_ENTER("dump_all_tables_in_db"); @@ -5343,11 +5391,15 @@ static int dump_all_tables_in_db(char *database) afterdot= strmov(hash_key, database); *afterdot++= '.'; - if (init_dumping(database, init_dumping_tables)) + if (init_dumping(database, using_mysql_db ? init_dumping_mysql_tables + : init_dumping_tables)) DBUG_RETURN(1); if (opt_xml) print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS); + if (using_mysql_db) + dump_first_mysql_tables(database); + if (lock_tables) { DYNAMIC_STRING query; @@ -5436,24 +5488,16 @@ static int dump_all_tables_in_db(char *database) else { /* - If general_log and slow_log exists in the 'mysql' database, + If transaction_registry exists in the 'mysql' database, we should dump the table structure. But we cannot call get_table_structure() here as 'LOCK TABLES' query got executed above on the session and that 'LOCK TABLES' query does not contain - 'general_log' and 'slow_log' tables. (you cannot acquire lock - on log tables). Hence mark the existence of these log tables here and + 'transaction_registry'. Hence mark the existence of the table here and after 'UNLOCK TABLES' query is executed on the session, get the table structure from server and dump it in the file. */ - if (using_mysql_db) - { - if (!my_strcasecmp(charset_info, table, "general_log")) - general_log_table_exists= 1; - else if (!my_strcasecmp(charset_info, table, "slow_log")) - slow_log_table_exists= 1; - else if (!my_strcasecmp(charset_info, table, "transaction_registry")) - transaction_registry_table_exists= 1; - } + if (using_mysql_db && !my_strcasecmp(charset_info, table, "transaction_registry")) + transaction_registry_table_exists= 1; } } @@ -5474,39 +5518,25 @@ static int dump_all_tables_in_db(char *database) DBUG_PRINT("info", ("Dumping routines for database %s", database)); dump_routines_for_db(database); } - if (opt_xml) - { - fputs("\n", md_result_file); - check_io(md_result_file); - } if (lock_tables) (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"); if (using_mysql_db) { - char table_type[NAME_LEN]; - char ignore_flag; - if (general_log_table_exists) - { - if (!get_table_structure((char *) "general_log", - database, table_type, &ignore_flag) ) - verbose_msg("-- Warning: get_table_structure() failed with some internal " - "error for 'general_log' table\n"); - } - if (slow_log_table_exists) - { - if (!get_table_structure((char *) "slow_log", - database, table_type, &ignore_flag) ) - verbose_msg("-- Warning: get_table_structure() failed with some internal " - "error for 'slow_log' table\n"); - } if (transaction_registry_table_exists) { + char table_type[NAME_LEN]; + char ignore_flag; if (!get_table_structure((char *) "transaction_registry", database, table_type, &ignore_flag) ) verbose_msg("-- Warning: get_table_structure() failed with some internal " "error for 'transaction_registry' table\n"); } } + if (opt_xml) + { + fputs("\n", md_result_file); + check_io(md_result_file); + } if (flush_privileges && using_mysql_db) { fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n"); diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index b5ab596370e..1ddda58e368 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -5738,34 +5738,6 @@ DROP TABLE t1; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `innodb_index_stats`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `innodb_index_stats` ( - `database_name` varchar(64) COLLATE utf8_bin NOT NULL, - `table_name` varchar(199) COLLATE utf8_bin NOT NULL, - `index_name` varchar(64) COLLATE utf8_bin NOT NULL, - `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `stat_name` varchar(64) COLLATE utf8_bin NOT NULL, - `stat_value` bigint(20) unsigned NOT NULL, - `sample_size` bigint(20) unsigned DEFAULT NULL, - `stat_description` varchar(1024) COLLATE utf8_bin NOT NULL, - PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; -/*!40101 SET character_set_client = @saved_cs_client */; -DROP TABLE IF EXISTS `innodb_table_stats`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `innodb_table_stats` ( - `database_name` varchar(64) COLLATE utf8_bin NOT NULL, - `table_name` varchar(199) COLLATE utf8_bin NOT NULL, - `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), - `n_rows` bigint(20) unsigned NOT NULL, - `clustered_index_size` bigint(20) unsigned NOT NULL, - `sum_of_other_index_sizes` bigint(20) unsigned NOT NULL, - PRIMARY KEY (`database_name`,`table_name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; -/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE IF NOT EXISTS `general_log` ( @@ -5795,6 +5767,34 @@ CREATE TABLE IF NOT EXISTS `slow_log` ( `rows_affected` int(11) NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `innodb_index_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_index_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `index_name` varchar(64) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `stat_name` varchar(64) COLLATE utf8_bin NOT NULL, + `stat_value` bigint(20) unsigned NOT NULL, + `sample_size` bigint(20) unsigned DEFAULT NULL, + `stat_description` varchar(1024) COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`database_name`,`table_name`,`index_name`,`stat_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `innodb_table_stats`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `innodb_table_stats` ( + `database_name` varchar(64) COLLATE utf8_bin NOT NULL, + `table_name` varchar(199) COLLATE utf8_bin NOT NULL, + `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `n_rows` bigint(20) unsigned NOT NULL, + `clustered_index_size` bigint(20) unsigned NOT NULL, + `sum_of_other_index_sizes` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`database_name`,`table_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE IF NOT EXISTS `transaction_registry` ( @@ -5833,6 +5833,35 @@ CREATE TABLE IF NOT EXISTS `transaction_registry` ( /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` int(11) NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -5873,35 +5902,6 @@ LOCK TABLES `innodb_table_stats` WRITE; UNLOCK TABLES; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE IF NOT EXISTS `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), - `user_host` mediumtext NOT NULL, - `thread_id` bigint(21) unsigned NOT NULL, - `server_id` int(10) unsigned NOT NULL, - `command_type` varchar(64) NOT NULL, - `argument` mediumtext NOT NULL -) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; -/*!40101 SET character_set_client = @saved_cs_client */; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE IF NOT EXISTS `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), - `user_host` mediumtext NOT NULL, - `query_time` time(6) NOT NULL, - `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, - `db` varchar(512) NOT NULL, - `last_insert_id` int(11) NOT NULL, - `insert_id` int(11) NOT NULL, - `server_id` int(10) unsigned NOT NULL, - `sql_text` mediumtext NOT NULL, - `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL -) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; -/*!40101 SET character_set_client = @saved_cs_client */; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE IF NOT EXISTS `transaction_registry` ( `transaction_id` bigint(20) unsigned NOT NULL, `commit_id` bigint(20) unsigned NOT NULL, @@ -5938,6 +5938,35 @@ CREATE TABLE IF NOT EXISTS `transaction_registry` ( /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; +/*!40101 SET character_set_client = @saved_cs_client */; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE IF NOT EXISTS `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` int(11) NOT NULL, + `rows_examined` int(11) NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` int(11) NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -5978,35 +6007,6 @@ LOCK TABLES `innodb_table_stats` WRITE; UNLOCK TABLES; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE IF NOT EXISTS `general_log` ( - `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), - `user_host` mediumtext NOT NULL, - `thread_id` bigint(21) unsigned NOT NULL, - `server_id` int(10) unsigned NOT NULL, - `command_type` varchar(64) NOT NULL, - `argument` mediumtext NOT NULL -) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; -/*!40101 SET character_set_client = @saved_cs_client */; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE IF NOT EXISTS `slow_log` ( - `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), - `user_host` mediumtext NOT NULL, - `query_time` time(6) NOT NULL, - `lock_time` time(6) NOT NULL, - `rows_sent` int(11) NOT NULL, - `rows_examined` int(11) NOT NULL, - `db` varchar(512) NOT NULL, - `last_insert_id` int(11) NOT NULL, - `insert_id` int(11) NOT NULL, - `server_id` int(10) unsigned NOT NULL, - `sql_text` mediumtext NOT NULL, - `thread_id` bigint(21) unsigned NOT NULL, - `rows_affected` int(11) NOT NULL -) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; -/*!40101 SET character_set_client = @saved_cs_client */; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; CREATE TABLE IF NOT EXISTS `transaction_registry` ( `transaction_id` bigint(20) unsigned NOT NULL, `commit_id` bigint(20) unsigned NOT NULL, @@ -6350,4 +6350,98 @@ END utf8 utf8_general_ci latin1_swedish_ci DROP DATABASE test1; DROP DATABASE test2; SET sql_mode=@save_sql_mode; +# +# MDEV-4875 Can't restore a mysqldump if --add-drop-database meets general_log +# +CREATE DATABASE test1; +# Dump mysql database +DROP VIEW IF EXISTS mysql.user; +DROP TABLE IF EXISTS mysql.global_priv; +DROP TABLE IF EXISTS mysql.user; +DROP TABLE IF EXISTS mysql.time_zone_transition_type; +DROP TABLE IF EXISTS mysql.time_zone_transition; +DROP TABLE IF EXISTS mysql.time_zone_name; +DROP TABLE IF EXISTS mysql.time_zone_leap_second; +DROP TABLE IF EXISTS mysql.time_zone; +DROP TABLE IF EXISTS mysql.tables_priv; +DROP TABLE IF EXISTS mysql.table_stats; +DROP TABLE IF EXISTS mysql.servers; +DROP TABLE IF EXISTS mysql.roles_mapping; +DROP TABLE IF EXISTS mysql.proxies_priv; +DROP TABLE IF EXISTS mysql.procs_priv; +DROP TABLE IF EXISTS mysql.proc; +DROP TABLE IF EXISTS mysql.plugin; +DROP TABLE IF EXISTS mysql.innodb_table_stats; +DROP TABLE IF EXISTS mysql.innodb_index_stats; +DROP TABLE IF EXISTS mysql.index_stats; +DROP TABLE IF EXISTS mysql.host; +DROP TABLE IF EXISTS mysql.help_topic; +DROP TABLE IF EXISTS mysql.help_relation; +DROP TABLE IF EXISTS mysql.help_keyword; +DROP TABLE IF EXISTS mysql.help_category; +DROP TABLE IF EXISTS mysql.gtid_slave_pos; +DROP TABLE IF EXISTS mysql.func; +DROP TABLE IF EXISTS mysql.event; +DROP TABLE IF EXISTS mysql.db; +DROP TABLE IF EXISTS mysql.columns_priv; +DROP TABLE IF EXISTS mysql.column_stats; +# Abbreviated contents + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/*!50106 SET GLOBAL LOG_OUTPUT=@save_log_output*/; + + + + + + + + + + + + + + + + + + +SET @save_general_log=@@GENERAL_LOG; +SET GLOBAL LOG_OUTPUT='TABLE', GLOBAL GENERAL_LOG=1; +# Restore mysql database while general log is active +# No failure at this stage is the object of the test +SELECT @@GLOBAL.LOG_OUTPUT, @@GLOBAL.GENERAL_LOG; +@@GLOBAL.LOG_OUTPUT @@GLOBAL.GENERAL_LOG +TABLE 1 +SET GLOBAL LOG_OUTPUT=DEFAULT, GLOBAL GENERAL_LOG=@save_general_log; +TRUNCATE TABLE mysql.general_log; +DROP DATABASE test1; # End of 10.3 tests diff --git a/mysql-test/main/mysqldump.test b/mysql-test/main/mysqldump.test index aeae62664d9..bf98a44bc34 100644 --- a/mysql-test/main/mysqldump.test +++ b/mysql-test/main/mysqldump.test @@ -2916,4 +2916,64 @@ DROP DATABASE test2; SET sql_mode=@save_sql_mode; --remove_file $MYSQLTEST_VARDIR/tmp/dumptest1.sql +--echo # +--echo # MDEV-4875 Can't restore a mysqldump if --add-drop-database meets general_log +--echo # + +CREATE DATABASE test1; +--echo # Dump mysql database +--exec $MYSQL_DUMP --add-drop-database --databases mysql test1 > $MYSQLTEST_VARDIR/tmp/dumptest1.sql + +--disable_warnings +DROP VIEW IF EXISTS mysql.user; +DROP TABLE IF EXISTS mysql.global_priv; +DROP TABLE IF EXISTS mysql.user; +--enable_warnings +#DROP TABLE IF EXISTS mysql.transaction_registry; +#DROP TABLE IF EXISTS mysql.slow_log; +#DROP TABLE IF EXISTS mysql.general_log; +DROP TABLE IF EXISTS mysql.time_zone_transition_type; +DROP TABLE IF EXISTS mysql.time_zone_transition; +DROP TABLE IF EXISTS mysql.time_zone_name; +DROP TABLE IF EXISTS mysql.time_zone_leap_second; +DROP TABLE IF EXISTS mysql.time_zone; +DROP TABLE IF EXISTS mysql.tables_priv; +DROP TABLE IF EXISTS mysql.table_stats; +DROP TABLE IF EXISTS mysql.servers; +DROP TABLE IF EXISTS mysql.roles_mapping; +DROP TABLE IF EXISTS mysql.proxies_priv; +DROP TABLE IF EXISTS mysql.procs_priv; +DROP TABLE IF EXISTS mysql.proc; +DROP TABLE IF EXISTS mysql.plugin; +DROP TABLE IF EXISTS mysql.innodb_table_stats; +DROP TABLE IF EXISTS mysql.innodb_index_stats; +DROP TABLE IF EXISTS mysql.index_stats; +DROP TABLE IF EXISTS mysql.host; +DROP TABLE IF EXISTS mysql.help_topic; +DROP TABLE IF EXISTS mysql.help_relation; +DROP TABLE IF EXISTS mysql.help_keyword; +DROP TABLE IF EXISTS mysql.help_category; +DROP TABLE IF EXISTS mysql.gtid_slave_pos; +DROP TABLE IF EXISTS mysql.func; +DROP TABLE IF EXISTS mysql.event; +DROP TABLE IF EXISTS mysql.db; +DROP TABLE IF EXISTS mysql.columns_priv; +DROP TABLE IF EXISTS mysql.column_stats; + +--echo # Abbreviated contents +--replace_regex /Create_time="[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}"/Create_time="TIMESTAMP"/ +--exec $MYSQL_DUMP --xml --skip-comments --no-data --add-drop-database --databases mysql test1 + +SET @save_general_log=@@GENERAL_LOG; +SET GLOBAL LOG_OUTPUT='TABLE', GLOBAL GENERAL_LOG=1; + +--echo # Restore mysql database while general log is active +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/dumptest1.sql +--echo # No failure at this stage is the object of the test +SELECT @@GLOBAL.LOG_OUTPUT, @@GLOBAL.GENERAL_LOG; +SET GLOBAL LOG_OUTPUT=DEFAULT, GLOBAL GENERAL_LOG=@save_general_log; +TRUNCATE TABLE mysql.general_log; +DROP DATABASE test1; +--remove_file $MYSQLTEST_VARDIR/tmp/dumptest1.sql + --echo # End of 10.3 tests From 16e276721a54663bbeaaed74003593fff7b35244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 6 May 2022 17:40:55 +0300 Subject: [PATCH 86/94] MDEV-28478 fixup: Declare a constexpr member function const --- storage/innobase/include/buf0types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/include/buf0types.h b/storage/innobase/include/buf0types.h index e2d733c6c13..327e2e2498e 100644 --- a/storage/innobase/include/buf0types.h +++ b/storage/innobase/include/buf0types.h @@ -174,7 +174,7 @@ public: m_id= (m_id & ~uint64_t{0} << 32) | page_no; } - constexpr ulonglong raw() { return m_id; } + constexpr ulonglong raw() const { return m_id; } private: /** The page identifier */ From a5dc12eefd4bea1c3f77d02c55d0d459b4ae0566 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 3 May 2022 22:38:20 +0300 Subject: [PATCH 87/94] MDEV-28310 Missing binlog data for INSERT .. ON DUPLICATE KEY UPDATE MDEV-21810 MBR: Unexpected "Unsafe statement" warning for unsafe IODKU MDEV-17614 fixes to replication unsafety for INSERT ON DUP KEY UPDATE on two or more unique key table left a flaw. The fixes checked the safety condition per each inserted record with the idea to catch a user-created value to an autoincrement column and when that succeeds the autoincrement column would become the source of unsafety too. It was not expected that after a duplicate error the next record's write_set may become different and the unsafe decision for that specific record will be computed to screw the Query's binlogging state and when @@binlog_format is MIXED nothing gets bin-logged. This case has been already fixed in 10.5.2 by 91ab42a823 that relocated/optimized THD::decide_logging_format_low() out of the record insert loop. The safety decision is computed once and at the right time. Pertinent parts of the commit are cherry-picked. Also a spurious warning about unsafety is removed when MIXED @@binlog_format; original MDEV-17614 test result corrected. The original test of MDEV-17614 is extended and made more readable. --- mysql-test/suite/rpl/r/rpl_iodku,stmt.rdiff | 27 ++++++ mysql-test/suite/rpl/r/rpl_iodku.result | 32 +++++++ mysql-test/suite/rpl/r/rpl_mdev_17614.result | 72 +++++++++++++++ .../suite/rpl/r/rpl_unsafe_statements.result | 5 - mysql-test/suite/rpl/t/rpl_iodku.test | 50 ++++++++++ mysql-test/suite/rpl/t/rpl_mdev_17614.test | 73 ++++++++++++--- .../suite/rpl/t/rpl_unsafe_statements.test | 2 +- sql/sql_class.cc | 91 +++++++++++++------ sql/sql_class.h | 20 ++-- sql/sql_insert.cc | 6 +- 10 files changed, 323 insertions(+), 55 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_iodku,stmt.rdiff create mode 100644 mysql-test/suite/rpl/r/rpl_iodku.result create mode 100644 mysql-test/suite/rpl/t/rpl_iodku.test diff --git a/mysql-test/suite/rpl/r/rpl_iodku,stmt.rdiff b/mysql-test/suite/rpl/r/rpl_iodku,stmt.rdiff new file mode 100644 index 00000000000..e31f1e5d991 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_iodku,stmt.rdiff @@ -0,0 +1,27 @@ +--- r/rpl_iodku.result 2022-05-04 18:51:24.956414404 +0300 ++++ r/rpl_iodku,stmt.reject 2022-05-04 18:51:49.520106231 +0300 +@@ -1,10 +1,15 @@ + include/master-slave.inc + [connection master] ++call mtr.add_suppression("Unsafe statement written to the binary log using statement"); + CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT, c INT, + UNIQUE (a), UNIQUE (b)) ENGINE=innodb; + INSERT INTO t1 (`a`,`c`) VALUES (1,1), (2,1) ON DUPLICATE KEY UPDATE c = 1; ++Warnings: ++Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe + # UNSAFE + INSERT INTO t1 (`a`,`c`) VALUES (3, 1),(2,1), (1,1) ON DUPLICATE KEY UPDATE c = a * 10 + VALUES(c); ++Warnings: ++Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe + SELECT * from t1; + id a b c + 1 1 NULL 11 +@@ -17,6 +22,8 @@ + INSERT INTO t1 VALUES (1,10,1); + # eligable for the statement format run unsafe warning + INSERT INTO t1 VALUES (2,20,2) ON DUPLICATE KEY UPDATE c = 100; ++Warnings: ++Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe + # not eligable: no warning in the statement format run + INSERT INTO t1 (`a`,`c`) VALUES (3, 1) ON DUPLICATE KEY UPDATE c = 99; + SELECT * from t1; diff --git a/mysql-test/suite/rpl/r/rpl_iodku.result b/mysql-test/suite/rpl/r/rpl_iodku.result new file mode 100644 index 00000000000..55348da1439 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_iodku.result @@ -0,0 +1,32 @@ +include/master-slave.inc +[connection master] +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT, c INT, +UNIQUE (a), UNIQUE (b)) ENGINE=innodb; +INSERT INTO t1 (`a`,`c`) VALUES (1,1), (2,1) ON DUPLICATE KEY UPDATE c = 1; +# UNSAFE +INSERT INTO t1 (`a`,`c`) VALUES (3, 1),(2,1), (1,1) ON DUPLICATE KEY UPDATE c = a * 10 + VALUES(c); +SELECT * from t1; +id a b c +1 1 NULL 11 +2 2 NULL 21 +3 3 NULL 1 +connection slave; +include/diff_tables.inc [master:t1,slave:t1] +connection master; +CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, UNIQUE (a), UNIQUE (b)) ENGINE=innodb; +INSERT INTO t1 VALUES (1,10,1); +# eligable for the statement format run unsafe warning +INSERT INTO t1 VALUES (2,20,2) ON DUPLICATE KEY UPDATE c = 100; +# not eligable: no warning in the statement format run +INSERT INTO t1 (`a`,`c`) VALUES (3, 1) ON DUPLICATE KEY UPDATE c = 99; +SELECT * from t1; +a b c +1 10 1 +2 20 2 +3 NULL 1 +connection slave; +include/diff_tables.inc [master:t1,slave:t1] +connection master; +DROP TABLE t1; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_mdev_17614.result b/mysql-test/suite/rpl/r/rpl_mdev_17614.result index 39057334926..ba077111522 100644 --- a/mysql-test/suite/rpl/r/rpl_mdev_17614.result +++ b/mysql-test/suite/rpl/r/rpl_mdev_17614.result @@ -1,5 +1,6 @@ include/master-slave.inc [connection master] +# Case 1: UNSAFE call mtr.add_suppression("Unsafe statement written to the binary log using statement format"); CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT, UNIQUE(b), c int) engine=innodb; @@ -37,6 +38,7 @@ drop table t1; connection slave; start slave; include/wait_for_slave_to_start.inc +# Case 2: UNSAFE connection master; CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT, UNIQUE(b), c int) engine=innodb; @@ -45,8 +47,12 @@ connection master; INSERT INTO t1 VALUES (default, 1, 1); BEGIN; INSERT INTO t1 VALUES (default, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe connection master1; INSERT INTO t1 VALUES(default, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe connection master; COMMIT; SELECT * FROM t1; @@ -62,6 +68,7 @@ a b c connection master; drop table t1; connection slave; +# Case 3A: UNSAFE connection master; CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, UNIQUE(b), c int, d int ) engine=innodb; @@ -93,6 +100,67 @@ a b c d connection master; drop table t1; connection slave; +# Case 3B: UNSAFE - all column specified. +connection master; +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, +UNIQUE(b), c int, d int ) engine=innodb; +connection slave; +connection master; +INSERT INTO t1 VALUES (1, 1, 1, 1); +BEGIN; +INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE c=VALUES(c); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe +connection master1; +INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE c=VALUES(c); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe +connection master; +COMMIT; +SELECT * FROM t1; +a b c d +1 1 1 1 +2 NULL 2 2 +3 NULL 2 3 +connection slave; +#same data as master +SELECT * FROM t1; +a b c d +1 1 1 1 +2 NULL 2 2 +3 NULL 2 3 +connection master; +drop table t1; +connection slave; +# Case 3C: SAFE - only one unique key (PK) specified. +connection master; +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, +UNIQUE(b), c int, d int ) engine=innodb; +connection slave; +connection master; +INSERT INTO t1 VALUES (1, 1, 1, 1); +BEGIN; +INSERT INTO t1 (`a`, `c`, `d`) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE c=99; +connection master1; +INSERT INTO t1 (`a`, `c`, `d`) VALUES(3, 2, 3) ON DUPLICATE KEY UPDATE c=100; +connection master; +COMMIT; +SELECT * FROM t1; +a b c d +1 1 1 1 +2 NULL 2 2 +3 NULL 2 3 +connection slave; +#same data as master +SELECT * FROM t1; +a b c d +1 1 1 1 +2 NULL 2 2 +3 NULL 2 3 +connection master; +drop table t1; +connection slave; +# Case 4: UNSAFE connection master; CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT, UNIQUE(b), c int) engine=innodb; @@ -101,8 +169,12 @@ connection master; INSERT INTO t1 VALUES (1, 1, 1); BEGIN; INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe connection master1; INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe connection master; COMMIT; SELECT * FROM t1; diff --git a/mysql-test/suite/rpl/r/rpl_unsafe_statements.result b/mysql-test/suite/rpl/r/rpl_unsafe_statements.result index 0ce94ca63d0..ca790f5d148 100644 --- a/mysql-test/suite/rpl/r/rpl_unsafe_statements.result +++ b/mysql-test/suite/rpl/r/rpl_unsafe_statements.result @@ -1,6 +1,5 @@ include/master-slave.inc [connection master] -call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TRIGGER trig1 AFTER INSERT ON t1 @@ -50,13 +49,9 @@ connection master; DROP TABLE t1; CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB; INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; -Warnings: -Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe START TRANSACTION; LOCK TABLES t1 WRITE; INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; -Warnings: -Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe UNLOCK TABLES; COMMIT; connection slave; diff --git a/mysql-test/suite/rpl/t/rpl_iodku.test b/mysql-test/suite/rpl/t/rpl_iodku.test new file mode 100644 index 00000000000..815b927c350 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_iodku.test @@ -0,0 +1,50 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +if (`select @@binlog_format = "statement"`) +{ + call mtr.add_suppression("Unsafe statement written to the binary log using statement"); +} + +## MDEV-28310 loss of binlog event for multi-record IODKU +# Check that the duplicate key error does not cause +# loss of replication event for IODKU that specifies values +# for at least two unique columns per record. +# "Implicit" NULL value of the auto-increment column also counts. + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT, c INT, + UNIQUE (a), UNIQUE (b)) ENGINE=innodb; +INSERT INTO t1 (`a`,`c`) VALUES (1,1), (2,1) ON DUPLICATE KEY UPDATE c = 1; +--echo # UNSAFE +# because of two keys involved: a UK and PK even though implicitly via auto-inc +INSERT INTO t1 (`a`,`c`) VALUES (3, 1),(2,1), (1,1) ON DUPLICATE KEY UPDATE c = a * 10 + VALUES(c); +SELECT * from t1; + +--sync_slave_with_master +--let $diff_tables = master:t1,slave:t1 +--source include/diff_tables.inc + +## MDEV-21810 MBR: Unexpected "Unsafe statement" warning for unsafe IODKU +# Unnecessary unsafe statement warning is not error-logged anymore. + + +--connection master +CREATE OR REPLACE TABLE t1 (a INT, b INT, c INT, UNIQUE (a), UNIQUE (b)) ENGINE=innodb; +INSERT INTO t1 VALUES (1,10,1); +--echo # eligable for the statement format run unsafe warning +INSERT INTO t1 VALUES (2,20,2) ON DUPLICATE KEY UPDATE c = 100; +--echo # not eligable: no warning in the statement format run +INSERT INTO t1 (`a`,`c`) VALUES (3, 1) ON DUPLICATE KEY UPDATE c = 99; +SELECT * from t1; + +--sync_slave_with_master +--let $diff_tables = master:t1,slave:t1 +--source include/diff_tables.inc + +# Cleanup +--connection master +DROP TABLE t1; +--sync_slave_with_master + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev_17614.test b/mysql-test/suite/rpl/t/rpl_mdev_17614.test index 9b86c8c15b5..c11aad3305e 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev_17614.test +++ b/mysql-test/suite/rpl/t/rpl_mdev_17614.test @@ -2,15 +2,22 @@ source include/have_debug.inc; source include/have_innodb.inc; -- source include/have_binlog_format_statement.inc source include/master-slave.inc; -# MDEV-17614 -# INSERT on dup key update is replication unsafe -# There can be three case -# 1. 2 unique key, Replication is unsafe. -# 2. 2 unique key , with one auto increment key, Safe to replicate because Innodb will acquire gap lock -# 3. n no of unique keys (n>1) but insert is only in 1 unique key -# 4. 2 unique key , with one auto increment key(but user gives auto inc value), unsafe to replicate +# MDEV-17614 INSERT on dup key update is replication unsafe +# +# The following cases are tested below: +# 1. 2 unique key, replication is UNSAFE +# 2. 2 unique key, with one auto increment key and implicit value to it. +# It is UNSAFE because autoinc column values of being inserted records +# are revealed dynamically, so unknown at the binlog-format decision time +# and hence this pessimistic expectation +# 3. 2 unique keys +# A. insert is only in 1 unique key, still all colums are specified => UNSAFE +# B. both unique keys are specified => UNSAFE +# C. only one unique key is specified => SAFE (motivated by MDEV-28310) +# 4. 2 unique key, with one auto increment key(but user gives auto inc value) => +# UNSAFE to replicate -# Case 1 +--echo # Case 1: UNSAFE call mtr.add_suppression("Unsafe statement written to the binary log using statement format"); CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT, UNIQUE(b), c int) engine=innodb; @@ -42,7 +49,8 @@ drop table t1; connection slave; start slave; --source include/wait_for_slave_to_start.inc -# Case 2 + +--echo # Case 2: UNSAFE --connection master CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT, UNIQUE(b), c int) engine=innodb; @@ -64,7 +72,7 @@ connection master; drop table t1; --sync_slave_with_master -# Case 3 +--echo # Case 3A: UNSAFE --connection master CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, UNIQUE(b), c int, d int ) engine=innodb; @@ -85,7 +93,50 @@ connection master; drop table t1; --sync_slave_with_master -# Case 4 +--echo # Case 3B: UNSAFE - all column specified. +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, +UNIQUE(b), c int, d int ) engine=innodb; +sync_slave_with_master; +connection master; +INSERT INTO t1 VALUES (1, 1, 1, 1); +BEGIN; +INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE c=VALUES(c); + --connection master1 + INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE c=VALUES(c); +--connection master +COMMIT; +SELECT * FROM t1; +--sync_slave_with_master +--echo #same data as master +SELECT * FROM t1; +connection master; +drop table t1; +--sync_slave_with_master + + +--echo # Case 3C: SAFE - only one unique key (PK) specified. +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, +UNIQUE(b), c int, d int ) engine=innodb; +sync_slave_with_master; +connection master; +INSERT INTO t1 VALUES (1, 1, 1, 1); +BEGIN; +INSERT INTO t1 (`a`, `c`, `d`) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE c=99; + --connection master1 + INSERT INTO t1 (`a`, `c`, `d`) VALUES(3, 2, 3) ON DUPLICATE KEY UPDATE c=100; +--connection master +COMMIT; +SELECT * FROM t1; +--sync_slave_with_master +--echo #same data as master +SELECT * FROM t1; +connection master; +drop table t1; +--sync_slave_with_master + +--echo # Case 4: UNSAFE --connection master CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT, UNIQUE(b), c int) engine=innodb; diff --git a/mysql-test/suite/rpl/t/rpl_unsafe_statements.test b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test index aa0bd076398..cbb4b54a220 100644 --- a/mysql-test/suite/rpl/t/rpl_unsafe_statements.test +++ b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test @@ -24,7 +24,7 @@ --source include/have_innodb.inc --source include/have_binlog_format_mixed.inc --source include/master-slave.inc -call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + # Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS # Statement is unsafe because it invokes a trigger or a # stored function that inserts into an AUTO_INCREMENT column. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index aa64e42e144..67373c99966 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -6285,47 +6285,84 @@ int THD::decide_logging_format(TABLE_LIST *tables) DBUG_RETURN(0); } -int THD::decide_logging_format_low(TABLE *table) + +/* + Reconsider logging format in case of INSERT...ON DUPLICATE KEY UPDATE + for tables with more than one unique keys in case of MIXED binlog format. + + Unsafe means that a master could execute the statement differently than + the slave. + This could can happen in the following cases: + - The unique check are done in different order on master or slave + (different engine or different key order). + - There is a conflict on another key than the first and before the + statement is committed, another connection commits a row that conflicts + on an earlier unique key. Example follows: + + Below a and b are unique keys, the table has a row (1,1,0) + connection 1: + INSERT INTO t1 set a=2,b=1,c=0 ON DUPLICATE KEY UPDATE c=1; + connection 2: + INSERT INTO t1 set a=2,b=2,c=0; + + If 2 commits after 1 has been executed but before 1 has committed + (and are thus put before the other in the binary log), one will + get different data on the slave: + (1,1,1),(2,2,1) instead of (1,1,1),(2,2,0) +*/ + +void THD::reconsider_logging_format_for_iodup(TABLE *table) { - /* - INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys - can be unsafe. - */ - if(wsrep_binlog_format() <= BINLOG_FORMAT_STMT && - !is_current_stmt_binlog_format_row() && - !lex->is_stmt_unsafe() && - lex->sql_command == SQLCOM_INSERT && - lex->duplicates == DUP_UPDATE) + DBUG_ENTER("reconsider_logging_format_for_iodup"); + enum_binlog_format bf= (enum_binlog_format) wsrep_binlog_format(); + + DBUG_ASSERT(lex->duplicates == DUP_UPDATE); + + if (bf <= BINLOG_FORMAT_STMT && + !is_current_stmt_binlog_format_row()) { + KEY *end= table->s->key_info + table->s->keys; uint unique_keys= 0; - uint keys= table->s->keys, i= 0; - Field *field; - for (KEY* keyinfo= table->s->key_info; - i < keys && unique_keys <= 1; i++, keyinfo++) - if (keyinfo->flags & HA_NOSAME && - !(keyinfo->key_part->field->flags & AUTO_INCREMENT_FLAG && - //User given auto inc can be unsafe - !keyinfo->key_part->field->val_int())) + + for (KEY *keyinfo= table->s->key_info; keyinfo < end ; keyinfo++) + { + if (keyinfo->flags & HA_NOSAME) { + /* + We assume that the following cases will guarantee that the + key is unique if a key part is not set: + - The key part is an autoincrement (autogenerated) + - The key part has a default value that is null and it not + a virtual field that will be calculated later. + */ for (uint j= 0; j < keyinfo->user_defined_key_parts; j++) { - field= keyinfo->key_part[j].field; - if(!bitmap_is_set(table->write_set,field->field_index)) - goto exit; + Field *field= keyinfo->key_part[j].field; + if (!bitmap_is_set(table->write_set, field->field_index)) + { + /* Check auto_increment */ + if (field == table->next_number_field) + goto exit; + if (field->is_real_null() && !field->default_value) + goto exit; + } } - unique_keys++; + if (unique_keys++) + break; exit:; } - + } if (unique_keys > 1) { - lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS); - binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags(); + if (bf == BINLOG_FORMAT_STMT && !lex->is_stmt_unsafe()) + { + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS); + binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags(); + } set_current_stmt_binlog_format_row_if_mixed(); - return 1; } } - return 0; + DBUG_VOID_RETURN; } /* diff --git a/sql/sql_class.h b/sql/sql_class.h index cceefb1793c..e3d9bc9ded0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4294,18 +4294,18 @@ public: mdl_context.release_transactional_locks(); } int decide_logging_format(TABLE_LIST *tables); - /* - In Some cases when decide_logging_format is called it does not have all - information to decide the logging format. So that cases we call decide_logging_format_2 - at later stages in execution. - One example would be binlog format for IODKU but column with unique key is not inserted. - We dont have inserted columns info when we call decide_logging_format so on later stage we call - decide_logging_format_low - @returns 0 if no format is changed - 1 if there is change in binlog format + /* + In Some cases when decide_logging_format is called it does not have + all information to decide the logging format. So that cases we call + decide_logging_format_2 at later stages in execution. + + One example would be binlog format for insert on duplicate key + (IODKU) but column with unique key is not inserted. We do not have + inserted columns info when we call decide_logging_format so on + later stage we call reconsider_logging_format_for_iodup() */ - int decide_logging_format_low(TABLE *table); + void reconsider_logging_format_for_iodup(TABLE *table); enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE}; void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 13dbbaed539..5137e7230d4 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -943,6 +943,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, goto values_loop_end; } } + if (duplic == DUP_UPDATE) + { + restore_record(table,s->default_values); // Get empty record + thd->reconsider_logging_format_for_iodup(table); + } do { DBUG_PRINT("info", ("iteration %llu", iteration)); @@ -1051,7 +1056,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, break; } - thd->decide_logging_format_low(table); #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) { From 0db27eff27dba9a2bf12653a20e503e029397b9a Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 7 May 2022 08:28:19 +1000 Subject: [PATCH 88/94] MDEV-27816: Set sql_mode before DROP IF EXISTS already (postfix) Test compat/oracle.sp-package-mysqldump needed re-record. --- .../compat/oracle/r/sp-package-mysqldump.result | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result b/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result index 21bead42b0a..24211c6318e 100644 --- a/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result +++ b/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result @@ -45,6 +45,8 @@ $$ /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; /*!50003 DROP PROCEDURE IF EXISTS `p1` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -52,8 +54,6 @@ $$ /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; DELIMITER ;; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"() AS @@ -65,6 +65,8 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; /*!50003 DROP PACKAGE IF EXISTS `pkg1` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -72,8 +74,6 @@ DELIMITER ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; DELIMITER ;; CREATE DEFINER="root"@"localhost" PACKAGE "pkg1" AS PROCEDURE p1; @@ -84,6 +84,8 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; /*!50003 DROP PACKAGE IF EXISTS `pkg2` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -91,8 +93,6 @@ DELIMITER ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; DELIMITER ;; CREATE DEFINER="root"@"localhost" PACKAGE "pkg2" AS PROCEDURE p1; @@ -103,6 +103,8 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; /*!50003 DROP PACKAGE BODY IF EXISTS `pkg1` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -110,8 +112,6 @@ DELIMITER ; /*!50003 SET character_set_client = latin1 */ ; /*!50003 SET character_set_results = latin1 */ ; /*!50003 SET collation_connection = latin1_swedish_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT' */ ; DELIMITER ;; CREATE DEFINER="root"@"localhost" PACKAGE BODY "pkg1" AS PROCEDURE p1 AS From e9a28940c5124aaeb0715718251b8802d2ee2c59 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 8 May 2022 00:42:43 +0200 Subject: [PATCH 89/94] these tests need ipv6 --- mysql-test/main/mysql_client_test_comp.test | 3 ++- mysql-test/main/mysql_client_test_nonblock.test | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/mysql_client_test_comp.test b/mysql-test/main/mysql_client_test_comp.test index 13a9d4944a4..f8bd80fc48a 100644 --- a/mysql-test/main/mysql_client_test_comp.test +++ b/mysql-test/main/mysql_client_test_comp.test @@ -1,7 +1,8 @@ # run mysql_client_test with performance schema # No need to run this with embedded server --- source include/not_embedded.inc +--source include/not_embedded.inc +--source include/check_ipv6.inc # need to have the dynamic loading turned on for the client plugin tests --source include/have_plugin_auth.inc diff --git a/mysql-test/main/mysql_client_test_nonblock.test b/mysql-test/main/mysql_client_test_nonblock.test index 19489bf9e0e..73e7a6d378d 100644 --- a/mysql-test/main/mysql_client_test_nonblock.test +++ b/mysql-test/main/mysql_client_test_nonblock.test @@ -2,7 +2,8 @@ # This runs the mysql_client_test using the non-blocking API. # The non-blocking API is not supported in the embedded server. --- source include/not_embedded.inc +--source include/not_embedded.inc +--source include/check_ipv6.inc # This test is slow on buildbot. --source include/big_test.inc From 79660e59ee8fcd23f928c72dc77682b875bd58ce Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 8 May 2022 13:00:35 +0200 Subject: [PATCH 90/94] can't use Item_default_value as a field if it's an expression OR a blob Fixed failing main.default on Windows (to trigger an assert the test needed a debug build without safemalloc, as 0xa5 happened to have the important bit set "correctly") --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 23e69b32e39..6d8d389b81d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -17343,7 +17343,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case Item::DEFAULT_VALUE_ITEM: { Field *field= ((Item_default_value*) item)->field; - if (field->default_value && (field->flags & BLOB_FLAG)) + if (field->default_value || (field->flags & BLOB_FLAG)) { /* We have to use a copy function when using a blob with default value From a2dd86df9cacb041b3bb1fd6818459b33056a8c3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 9 May 2022 12:16:35 +0200 Subject: [PATCH 91/94] cleanup: test --- mysql-test/main/default.result | 21 +++++++++++++++---- mysql-test/main/default.test | 37 +++++++++++++++++----------------- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/mysql-test/main/default.result b/mysql-test/main/default.result index cbd18cdf9a8..bd5ffba0d46 100644 --- a/mysql-test/main/default.result +++ b/mysql-test/main/default.result @@ -1,5 +1,3 @@ -drop table if exists t1,t2,t3,t4,t5,t6; -drop database if exists mysqltest; set sql_mode=""; CREATE TABLE t1 (a varchar(30) binary NOT NULL DEFAULT ' ', b varchar(1) binary NOT NULL DEFAULT ' ', @@ -3135,7 +3133,9 @@ t3 CREATE TABLE `t3` ( `max(c)` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1, t2, t3; +# # MDEV-11359: Implement IGNORE for bulk operation +# create table t1 (a int primary key default 0, b int default 3); insert into t1 values (1, ignore); insert into t1 values (2, ignore); @@ -3354,6 +3354,9 @@ a b 30 31 drop table t1; set sql_mode=default; +# +# MDEV-10201 Bad results for CREATE TABLE t1 (a INT DEFAULT b, b INT DEFAULT 4) +# create table t1 (a int default b, b int default 4, t text); insert t1 (b, t) values (5, '1 column is omitted'); insert t1 values (default, 5, '2 column gets DEFAULT, keyword'); @@ -3376,8 +3379,14 @@ a b t 5 5 8 reversed, also expression DEFAULT(0)+0 5 5 9 reversed, the value of the DEFAULT(a), that is b drop table t1; +# +# MDEV-10352 Server crashes in Field::set_default on CREATE TABLE +# create table t1 (col1 int default(-(default(col1)))); ERROR 01000: Expression for field `col1` is referring to uninitialized field `col1` +# +# MDEV-10354 Assertion `! is_set()' failed in Diagnostics_area::set_ok_status on CREATE TABLE with invalid default +# create table t1 (col int default (yearweek((exp(710))))); ERROR 22003: DOUBLE value is out of range in 'exp(710)' # @@ -3422,7 +3431,9 @@ DEFAULT(a) CASE a WHEN 0 THEN 1 ELSE 2 END NULL 2 DROP TABLE t; DROP VIEW v; -# end of 10.2 test +# +# End of 10.2 test +# # # MDEV-22703 DEFAULT() on a BLOB column can overwrite the default # record, which can cause crashes when accessing already released @@ -3438,4 +3449,6 @@ length(DEFAULT(h)) 25 INSERT INTO t1 () VALUES (); drop table t1; -# end of 10.3 test +# +# End of 10.3 test +# diff --git a/mysql-test/main/default.test b/mysql-test/main/default.test index 1230f67c7d2..a88817230e3 100644 --- a/mysql-test/main/default.test +++ b/mysql-test/main/default.test @@ -1,16 +1,10 @@ --source include/have_innodb.inc -# -# test of already fixed bugs -# ---disable_warnings -drop table if exists t1,t2,t3,t4,t5,t6; -drop database if exists mysqltest; - # # Bug 10838 # Insert causes warnings for no default values and corrupts tables # +--disable_warnings set sql_mode=""; CREATE TABLE t1 (a varchar(30) binary NOT NULL DEFAULT ' ', b varchar(1) binary NOT NULL DEFAULT ' ', @@ -1891,7 +1885,9 @@ show create table t2; show create table t3; drop table t1, t2, t3; +--echo # --echo # MDEV-11359: Implement IGNORE for bulk operation +--echo # create table t1 (a int primary key default 0, b int default 3); insert into t1 values (1, ignore); insert into t1 values (2, ignore); @@ -2071,9 +2067,9 @@ select * from t1; drop table t1; set sql_mode=default; -# -# MDEV-10201 Bad results for CREATE TABLE t1 (a INT DEFAULT b, b INT DEFAULT 4) -# +--echo # +--echo # MDEV-10201 Bad results for CREATE TABLE t1 (a INT DEFAULT b, b INT DEFAULT 4) +--echo # create table t1 (a int default b, b int default 4, t text); insert t1 (b, t) values (5, '1 column is omitted'); insert t1 values (default, 5, '2 column gets DEFAULT, keyword'); @@ -2088,15 +2084,15 @@ insert t1 (t,b,a) values ('9 reversed, the value of the DEFAULT(a), that is b', select * from t1 order by t; drop table t1; -# -# MDEV-10352 Server crashes in Field::set_default on CREATE TABLE -# +--echo # +--echo # MDEV-10352 Server crashes in Field::set_default on CREATE TABLE +--echo # --error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD create table t1 (col1 int default(-(default(col1)))); -# -# MDEV-10354 Assertion `! is_set()' failed in Diagnostics_area::set_ok_status on CREATE TABLE with invalid default -# +--echo # +--echo # MDEV-10354 Assertion `! is_set()' failed in Diagnostics_area::set_ok_status on CREATE TABLE with invalid default +--echo # --error ER_DATA_OUT_OF_RANGE create table t1 (col int default (yearweek((exp(710))))); @@ -2126,7 +2122,6 @@ INSERT INTO t1 VALUES (),(); SELECT 1 FROM t1 GROUP BY DEFAULT(pk); DROP TABLE t1; - --echo # --echo # MDEV-28402: ASAN heap-use-after-free in create_tmp_table, --echo # Assertion `l_offset >= 0 && table->s->rec_buff_length - l_offset > 0' @@ -2142,7 +2137,9 @@ CREATE ALGORITHM=TEMPTABLE VIEW v AS SELECT * FROM t; SELECT DISTINCT DEFAULT(a), CASE a WHEN 0 THEN 1 ELSE 2 END FROM v GROUP BY a WITH ROLLUP; DROP TABLE t; DROP VIEW v; ---echo # end of 10.2 test +--echo # +--echo # End of 10.2 test +--echo # --echo # --echo # MDEV-22703 DEFAULT() on a BLOB column can overwrite the default @@ -2160,4 +2157,6 @@ SELECT length(DEFAULT(h)) FROM t1; INSERT INTO t1 () VALUES (); drop table t1; ---echo # end of 10.3 test +--echo # +--echo # End of 10.3 test +--echo # From a8e57906d185bfbb2e4afd296dd26ae53577aa3c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 9 May 2022 12:16:04 +0200 Subject: [PATCH 92/94] 10.4 specific fixes for DEFAULT() --- mysql-test/main/default.result | 13 +++++++++++++ mysql-test/main/default.test | 12 ++++++++++++ sql/item.cc | 23 +++++++++++++++++++++++ sql/item.h | 2 ++ sql/sql_select.cc | 5 ++++- 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/default.result b/mysql-test/main/default.result index bd5ffba0d46..55b448229b5 100644 --- a/mysql-test/main/default.result +++ b/mysql-test/main/default.result @@ -3412,6 +3412,7 @@ INSERT INTO t1 VALUES (),(); SELECT 1 FROM t1 GROUP BY DEFAULT(pk); 1 1 +1 DROP TABLE t1; # # MDEV-28402: ASAN heap-use-after-free in create_tmp_table, @@ -3452,3 +3453,15 @@ drop table t1; # # End of 10.3 test # +# +# MDEV-26423: MariaDB server crash in Create_tmp_table::finalize +# +CREATE TABLE t1 (pk text DEFAULT length(uuid())); +INSERT INTO t1 VALUES (),(); +SELECT 1 FROM t1 GROUP BY DEFAULT(pk); +1 +1 +DROP TABLE t1; +# +# End of 10.4 test +# diff --git a/mysql-test/main/default.test b/mysql-test/main/default.test index a88817230e3..3064209a4a2 100644 --- a/mysql-test/main/default.test +++ b/mysql-test/main/default.test @@ -2160,3 +2160,15 @@ drop table t1; --echo # --echo # End of 10.3 test --echo # + +--echo # +--echo # MDEV-26423: MariaDB server crash in Create_tmp_table::finalize +--echo # +CREATE TABLE t1 (pk text DEFAULT length(uuid())); +INSERT INTO t1 VALUES (),(); +SELECT 1 FROM t1 GROUP BY DEFAULT(pk); +DROP TABLE t1; + +--echo # +--echo # End of 10.4 test +--echo # diff --git a/sql/item.cc b/sql/item.cc index a791d5bf8ca..f3eb7bcd741 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9525,6 +9525,12 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) return Item_field::save_in_field(field_arg, no_conversions); } +void Item_default_value::save_in_result_field(bool no_conversions) +{ + calculate(); + Item_field::save_in_result_field(no_conversions); +} + double Item_default_value::val_result() { calculate(); @@ -9584,6 +9590,23 @@ table_map Item_default_value::used_tables() const return field->default_value->expr->used_tables(); } +bool Item_default_value::register_field_in_read_map(void *arg) +{ + TABLE *table= (TABLE *) arg; + int res= 0; + if (!table || (table && table == field->table)) + { + if (field->default_value && field->default_value->expr) + res= field->default_value->expr->walk(&Item::register_field_in_read_map,1,arg); + } + else if (result_field && table == result_field->table) + { + bitmap_set_bit(table->read_set, result_field->field_index); + } + + return res; +} + /** This method like the walk method traverses the item tree, but at the same time it can replace some nodes in the tree. diff --git a/sql/item.h b/sql/item.h index f074ea1e3da..52febaa3031 100644 --- a/sql/item.h +++ b/sql/item.h @@ -6490,6 +6490,7 @@ public: bool send(Protocol *protocol, st_value *buffer); int save_in_field(Field *field_arg, bool no_conversions); + void save_in_result_field(bool no_conversions); bool save_in_param(THD *thd, Item_param *param) { // It should not be possible to have "EXECUTE .. USING DEFAULT(a)" @@ -6509,6 +6510,7 @@ public: bool update_vcol_processor(void *arg) { return 0; } bool check_field_expression_processor(void *arg); bool check_func_default_processor(void *arg) { return true; } + bool register_field_in_read_map(void *arg); bool walk(Item_processor processor, bool walk_subquery, void *args) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1b8147a6cfb..534d75b20d7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -18094,7 +18094,10 @@ Field *Item_default_value::create_tmp_field_ex(TABLE *table, as the we have to calculate the default value before we can use it. */ get_tmp_field_src(src, param); - return tmp_table_field_from_field_type(table); + Field *result= tmp_table_field_from_field_type(table); + if (result && param->modify_item()) + result_field= result; + return result; } /* Same code as in Item_field::create_tmp_field_ex, except no default field From 16cebed54065ad9e18953aa86d48f6007d53c2d3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 9 May 2022 17:20:48 +0200 Subject: [PATCH 93/94] fix plugin.multiauth test for FreeBSD remove AIX support, as 10.4 is not tested on AIX, so cannot test a regex --- mysql-test/suite/plugins/r/multiauth,aix.rdiff | 14 -------------- mysql-test/suite/plugins/r/multiauth.result | 2 +- mysql-test/suite/plugins/t/multiauth.test | 3 +-- 3 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 mysql-test/suite/plugins/r/multiauth,aix.rdiff diff --git a/mysql-test/suite/plugins/r/multiauth,aix.rdiff b/mysql-test/suite/plugins/r/multiauth,aix.rdiff deleted file mode 100644 index 0a2570cbd89..00000000000 --- a/mysql-test/suite/plugins/r/multiauth,aix.rdiff +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/mysql-test/suite/plugins/r/multiauth.result b/mysql-test/suite/plugins/r/multiauth.result -index aed46ac8964..24bb0a24f03 100644 ---- a/mysql-test/suite/plugins/r/multiauth.result -+++ b/mysql-test/suite/plugins/r/multiauth.result -@@ -181,7 +181,8 @@ show create user mysqltest1; - CREATE USER for mysqltest1@% - CREATE USER `mysqltest1`@`%` IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' - # no plugin = failure --mysqltest: Could not open connection 'default': 1045 Plugin client_ed25519 could not be loaded: /no/client_ed25519.so: cannot open shared object file: No such file or directory -+mysqltest: Could not open connection 'default': 1045 Plugin client_ed25519 could not be loaded: Could not load module /no/client_ed25519.so. -+System error: No such file or directory - alter user mysqltest1 identified via ed25519 as password("good") OR mysql_native_password as password("works"); - show create user mysqltest1; - CREATE USER for mysqltest1@% diff --git a/mysql-test/suite/plugins/r/multiauth.result b/mysql-test/suite/plugins/r/multiauth.result index 8e19433322d..75b604555a7 100644 --- a/mysql-test/suite/plugins/r/multiauth.result +++ b/mysql-test/suite/plugins/r/multiauth.result @@ -180,7 +180,7 @@ show create user mysqltest1; CREATE USER for mysqltest1@% CREATE USER `mysqltest1`@`%` IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' # no plugin = failure -mysqltest: Could not open connection 'default': 1045 Plugin client_ed25519 could not be loaded: /no/client_ed25519.so: cannot open shared object file: No such file or directory +mysqltest: Could not open connection 'default': 1045 Plugin client_ed25519 could not be loaded: no such file alter user mysqltest1 identified via ed25519 as password("good") OR mysql_native_password as password("works"); show create user mysqltest1; CREATE USER for mysqltest1@% diff --git a/mysql-test/suite/plugins/t/multiauth.test b/mysql-test/suite/plugins/t/multiauth.test index 87970e2c781..10558f322cf 100644 --- a/mysql-test/suite/plugins/t/multiauth.test +++ b/mysql-test/suite/plugins/t/multiauth.test @@ -1,5 +1,4 @@ --source include/not_ubsan.inc ---source include/platform.inc # # MDEV-11340 Allow multiple alternative authentication methods for the same user # @@ -182,7 +181,7 @@ eval $dreplace, mysqltest1; create user mysqltest1 identified via ed25519 as password("good"); show create user mysqltest1; --echo # no plugin = failure ---replace_result $plugindir +--replace_regex /loaded: .*client_ed25519.so: cannot open shared object file: No such file or directory/loaded: no such file/ /loaded: Cannot open.*client_ed25519.so./loaded: no such file/ --error 1 --exec $try_auth -u mysqltest1 -pgood --plugin-dir=$plugindir/no alter user mysqltest1 identified via ed25519 as password("good") OR mysql_native_password as password("works"); From fe3d07cab82b2215dc64f52ac93122072c33d021 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 10 May 2022 11:46:05 +0200 Subject: [PATCH 94/94] fix plugins.multiauth for AIX --- mysql-test/suite/plugins/t/multiauth.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/plugins/t/multiauth.test b/mysql-test/suite/plugins/t/multiauth.test index 4bf3424ee9d..86c98a5d5c3 100644 --- a/mysql-test/suite/plugins/t/multiauth.test +++ b/mysql-test/suite/plugins/t/multiauth.test @@ -186,7 +186,8 @@ eval $dreplace, mysqltest1; create user mysqltest1 identified via ed25519 as password("good"); show create user mysqltest1; --echo # no plugin = failure ---replace_regex /loaded: .*client_ed25519.so: cannot open shared object file: No such file or directory/loaded: no such file/ /loaded: Cannot open.*client_ed25519.so./loaded: no such file/ /loaded: .*Could not load module.*directory/loaded: no such file/ +# covers Linux (1st re), FreeBSD (2nd), AIX (3rd and 4th) +--replace_regex /loaded: .*client_ed25519.so: cannot open shared object file: No such file or directory/loaded: no such file/ /loaded: Cannot open.*client_ed25519.so./loaded: no such file/ /loaded: .*Could not load module.*client_ed25519.so.\n/loaded: no such file/ /System error: No such file or directory// --error 1 --exec $try_auth -u mysqltest1 -pgood --plugin-dir=$plugindir/no alter user mysqltest1 identified via ed25519 as password("good") OR mysql_native_password as password("works");