From 58cd2a8dedd78b25ada0996dee2bd3e0520c17b6 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 29 Mar 2022 13:44:14 +0300 Subject: MDEV-19525 remove ER_VERS_FIELD_WRONG_TYPE from init_from_binary_frm_image() Throw ER_NOT_FORM_FILE if this is wrong FRM data (warning with ER_VERS_FIELD_WRONG_TYPE is still printed for deeper knowledge of what was happened). Keep ER_VERS_FIELD_WRONG_TYPE for creating partitioned table with trx-versioning. Tested by MDEV-15951 in trx_id.test --- mysql-test/suite/versioning/r/debug.result | 14 +++++++++++++- mysql-test/suite/versioning/t/debug.test | 13 ++++++++++++- sql/table.cc | 13 ++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/versioning/r/debug.result b/mysql-test/suite/versioning/r/debug.result index 72bd1f18a68..20e21ff2811 100644 --- a/mysql-test/suite/versioning/r/debug.result +++ b/mysql-test/suite/versioning/r/debug.result @@ -50,5 +50,17 @@ t4 CREATE TABLE `t4` ( `row_end` timestamp(6) GENERATED ALWAYS AS ROW END, PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING -set global debug_dbug=@old_dbug; drop table t1, t2, t3, t4; +# +# MDEV-19525 remove ER_VERS_FIELD_WRONG_TYPE from init_from_binary_frm_image() +# +create table t1 (x int) with system versioning; +set debug_dbug='+d,error_vers_wrong_type'; +show create table t1; +ERROR HY000: Incorrect information in file: './test/t1.frm' +show warnings; +Level Code Message +Warning 4110 `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1` +Error 1033 Incorrect information in file: './test/t1.frm' +drop table t1; +set global debug_dbug=@old_dbug; diff --git a/mysql-test/suite/versioning/t/debug.test b/mysql-test/suite/versioning/t/debug.test index c6d5bd60861..59dde0d26fb 100644 --- a/mysql-test/suite/versioning/t/debug.test +++ b/mysql-test/suite/versioning/t/debug.test @@ -30,6 +30,17 @@ set debug_dbug='+d,sysvers_show'; show create table t3; create table t4 (a int); show create table t4; +drop table t1, t2, t3, t4; + +--echo # +--echo # MDEV-19525 remove ER_VERS_FIELD_WRONG_TYPE from init_from_binary_frm_image() +--echo # +create table t1 (x int) with system versioning; +set debug_dbug='+d,error_vers_wrong_type'; +--replace_result $MYSQLTEST_VARDIR . master-data// '' '\\' '/' +--error ER_NOT_FORM_FILE +show create table t1; +show warnings; +drop table t1; set global debug_dbug=@old_dbug; -drop table t1, t2, t3, t4; diff --git a/sql/table.cc b/sql/table.cc index 2ab947d69cd..7d022ba8ca3 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2082,6 +2082,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (flags & VERS_SYSTEM_FIELD) { + if (DBUG_EVALUATE_IF("error_vers_wrong_type", 1, 0)) + field_type= MYSQL_TYPE_BLOB; + switch (field_type) { case MYSQL_TYPE_TIMESTAMP2: @@ -2094,9 +2097,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } /* Fallthrough */ default: - my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), fieldnames.type_names[i], - versioned == VERS_TIMESTAMP ? "TIMESTAMP(6)" : "BIGINT(20) UNSIGNED", - table_name.str); + my_error(ER_VERS_FIELD_WRONG_TYPE, + (field_type == MYSQL_TYPE_LONGLONG ? + MYF(0) : MYF(ME_WARNING)), + fieldnames.type_names[i], + (versioned == VERS_TIMESTAMP ? + "TIMESTAMP(6)" : "BIGINT(20) UNSIGNED"), + table_name.str); goto err; } } -- cgit v1.2.1 From 1e859d4abcfd7e3b2c238e5dc8c909254661082a Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 29 Mar 2022 13:44:14 +0300 Subject: MDEV-22973 Assertion in compare_record upon multi-update involving versioned table via view records_are_comparable() requires this condition: bitmap_is_subset(table->write_set, table->read_set) On first iteration vers_update_fields() changes write_set and read_set. On second iteration the above condition fails. Added missing read bit for ROW_START. Also reorganized bitmap_set_bit() so it is called only when needed. --- mysql-test/suite/versioning/r/update.result | 11 +++++++++++ mysql-test/suite/versioning/t/update.test | 13 +++++++++++++ sql/table.cc | 7 ++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result index d123331cc8c..1db5682c69b 100644 --- a/mysql-test/suite/versioning/r/update.result +++ b/mysql-test/suite/versioning/r/update.result @@ -410,3 +410,14 @@ select check_row_ts(row_start, row_end) from t1 for system_time all where row_st check_row_ts(row_start, row_end) CURRENT ROW drop table t1; +# +# MDEV-22973 Assertion in compare_record upon multi-update involving versioned table via view +# +create or replace table t1 (a int, primary key (a)) engine=myisam; +insert into t1 values (0); +create or replace table t2 (pk int, b int, primary key (pk), key(b)) engine=innodb with system versioning; +insert into t2 values (1, 0), (2, 0); +create or replace view v as select a, b from t1, t2; +update v set b= null where a = 0 order by b; +drop view v; +drop table t1, t2; diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test index 058d2f4c865..edf4e4598ab 100644 --- a/mysql-test/suite/versioning/t/update.test +++ b/mysql-test/suite/versioning/t/update.test @@ -336,4 +336,17 @@ select row_start from t1 into @r; select check_row_ts(row_start, row_end) from t1 for system_time all where row_start = @r; drop table t1; +--echo # +--echo # MDEV-22973 Assertion in compare_record upon multi-update involving versioned table via view +--echo # +create or replace table t1 (a int, primary key (a)) engine=myisam; +insert into t1 values (0); +create or replace table t2 (pk int, b int, primary key (pk), key(b)) engine=innodb with system versioning; +insert into t2 values (1, 0), (2, 0); +create or replace view v as select a, b from t1, t2; +update v set b= null where a = 0 order by b; +# cleanup +drop view v; +drop table t1, t2; + source suite/versioning/common_finish.inc; diff --git a/sql/table.cc b/sql/table.cc index 7d022ba8ca3..08d91678b25 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8161,9 +8161,6 @@ void TABLE::evaluate_update_default_function() void TABLE::vers_update_fields() { - bitmap_set_bit(write_set, vers_start_field()->field_index); - bitmap_set_bit(write_set, vers_end_field()->field_index); - if (!vers_write) { file->column_bitmaps_signal(); @@ -8172,17 +8169,21 @@ void TABLE::vers_update_fields() if (versioned(VERS_TIMESTAMP)) { + bitmap_set_bit(write_set, vers_start_field()->field_index); if (vers_start_field()->store_timestamp(in_use->query_start(), in_use->query_start_sec_part())) { DBUG_ASSERT(0); } vers_start_field()->set_has_explicit_value(); + bitmap_set_bit(read_set, vers_start_field()->field_index); } + bitmap_set_bit(write_set, vers_end_field()->field_index); vers_end_field()->set_max(); vers_end_field()->set_has_explicit_value(); bitmap_set_bit(read_set, vers_end_field()->field_index); + file->column_bitmaps_signal(); if (vfield) update_virtual_fields(file, VCOL_UPDATE_FOR_READ); -- cgit v1.2.1 From 33ff18627ea009709bb0ba55b68f873e6c6c784c Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Mon, 28 Mar 2022 19:16:14 +0300 Subject: MDEV-27835 innochecksum -S crashes for encrypted .ibd tablespace As main() invokes parse_page() when -S or -D are set, it can be a case when parse_page() is invoked when -D filename is not set, that is why any attempt to write to page dump file must be done only if the file name is set with -D. The bug is caused by 2ef7a5a13a988842450cbeeaceaf0ea1a78a3c27 (MDEV-13443). --- extra/innochecksum.cc | 48 +++++++++++------------ mysql-test/suite/encryption/r/innochecksum.result | 2 +- mysql-test/suite/encryption/t/innochecksum.test | 4 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index 06001fd451b..4b287e918e6 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -886,7 +886,7 @@ parse_page( is_leaf = (!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL))); - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tIndex page\t\t\t|" "\tindex id=%llu,", cur_page_num, id); @@ -939,7 +939,7 @@ parse_page( index.total_data_bytes += data_bytes; index.pages_in_size_range[size_range_id] ++; } - } else { + } else if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tEncrypted Index page\t\t\t|" "\tkey_version " UINT32PF ",%s\n", cur_page_num, key_version, str); } @@ -950,20 +950,20 @@ parse_page( page_type.n_fil_page_undo_log++; undo_page_type = mach_read_from_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE); - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tUndo log page\t\t\t|", cur_page_num); } if (undo_page_type == TRX_UNDO_INSERT) { page_type.n_undo_insert++; - if (page_type_dump) { + if (file) { fprintf(file, "\t%s", "Insert Undo log page"); } } else if (undo_page_type == TRX_UNDO_UPDATE) { page_type.n_undo_update++; - if (page_type_dump) { + if (file) { fprintf(file, "\t%s", "Update undo log page"); } @@ -974,7 +974,7 @@ parse_page( switch (undo_page_type) { case TRX_UNDO_ACTIVE: page_type.n_undo_state_active++; - if (page_type_dump) { + if (file) { fprintf(file, ", %s", "Undo log of " "an active transaction"); } @@ -982,7 +982,7 @@ parse_page( case TRX_UNDO_CACHED: page_type.n_undo_state_cached++; - if (page_type_dump) { + if (file) { fprintf(file, ", %s", "Page is " "cached for quick reuse"); } @@ -990,7 +990,7 @@ parse_page( case TRX_UNDO_TO_FREE: page_type.n_undo_state_to_free++; - if (page_type_dump) { + if (file) { fprintf(file, ", %s", "Insert undo " "segment that can be freed"); } @@ -998,7 +998,7 @@ parse_page( case TRX_UNDO_TO_PURGE: page_type.n_undo_state_to_purge++; - if (page_type_dump) { + if (file) { fprintf(file, ", %s", "Will be " "freed in purge when all undo" "data in it is removed"); @@ -1007,7 +1007,7 @@ parse_page( case TRX_UNDO_PREPARED: page_type.n_undo_state_prepared++; - if (page_type_dump) { + if (file) { fprintf(file, ", %s", "Undo log of " "an prepared transaction"); } @@ -1017,14 +1017,14 @@ parse_page( page_type.n_undo_state_other++; break; } - if(page_type_dump) { + if(file) { fprintf(file, ", %s\n", str); } break; case FIL_PAGE_INODE: page_type.n_fil_page_inode++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tInode page\t\t\t|" "\t%s\n",cur_page_num, str); } @@ -1032,7 +1032,7 @@ parse_page( case FIL_PAGE_IBUF_FREE_LIST: page_type.n_fil_page_ibuf_free_list++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tInsert buffer free list" " page\t|\t%s\n", cur_page_num, str); } @@ -1040,7 +1040,7 @@ parse_page( case FIL_PAGE_TYPE_ALLOCATED: page_type.n_fil_page_type_allocated++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tFreshly allocated " "page\t\t|\t%s\n", cur_page_num, str); } @@ -1048,7 +1048,7 @@ parse_page( case FIL_PAGE_IBUF_BITMAP: page_type.n_fil_page_ibuf_bitmap++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tInsert Buffer " "Bitmap\t\t|\t%s\n", cur_page_num, str); } @@ -1056,7 +1056,7 @@ parse_page( case FIL_PAGE_TYPE_SYS: page_type.n_fil_page_type_sys++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tSystem page\t\t\t|" "\t%s\n", cur_page_num, str); } @@ -1064,7 +1064,7 @@ parse_page( case FIL_PAGE_TYPE_TRX_SYS: page_type.n_fil_page_type_trx_sys++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tTransaction system " "page\t\t|\t%s\n", cur_page_num, str); } @@ -1072,7 +1072,7 @@ parse_page( case FIL_PAGE_TYPE_FSP_HDR: page_type.n_fil_page_type_fsp_hdr++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tFile Space " "Header\t\t|\t%s\n", cur_page_num, str); } @@ -1080,7 +1080,7 @@ parse_page( case FIL_PAGE_TYPE_XDES: page_type.n_fil_page_type_xdes++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tExtent descriptor " "page\t\t|\t%s\n", cur_page_num, str); } @@ -1088,7 +1088,7 @@ parse_page( case FIL_PAGE_TYPE_BLOB: page_type.n_fil_page_type_blob++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tBLOB page\t\t\t|\t%s\n", cur_page_num, str); } @@ -1096,7 +1096,7 @@ parse_page( case FIL_PAGE_TYPE_ZBLOB: page_type.n_fil_page_type_zblob++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tCompressed BLOB " "page\t\t|\t%s\n", cur_page_num, str); } @@ -1104,7 +1104,7 @@ parse_page( case FIL_PAGE_TYPE_ZBLOB2: page_type.n_fil_page_type_zblob2++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tSubsequent Compressed " "BLOB page\t|\t%s\n", cur_page_num, str); } @@ -1112,7 +1112,7 @@ parse_page( case FIL_PAGE_PAGE_COMPRESSED: page_type.n_fil_page_type_page_compressed++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tPage compressed " "page\t|\t%s\n", cur_page_num, str); } @@ -1120,7 +1120,7 @@ parse_page( case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: page_type.n_fil_page_type_page_compressed_encrypted++; - if (page_type_dump) { + if (file) { fprintf(file, "#::" UINT32PF "\t\t|\t\tPage compressed encrypted " "page\t|\t%s\n", cur_page_num, str); } diff --git a/mysql-test/suite/encryption/r/innochecksum.result b/mysql-test/suite/encryption/r/innochecksum.result index 2c1279cd232..213be3a7f76 100644 --- a/mysql-test/suite/encryption/r/innochecksum.result +++ b/mysql-test/suite/encryption/r/innochecksum.result @@ -14,7 +14,7 @@ CREATE TABLE t6 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT) ENGINE=InnoDB; # to redo apply the pages of t1.ibd at the time of recovery. # We want SQL to initiate the first access to t1.ibd. # Wait until disconnected. -# Run innochecksum on t1 +# Run innochecksum on t1, check -S does not cause crash for encrypted file # Run innochecksum on t2 # Run innochecksum on t3 # Run innochecksum on t4 diff --git a/mysql-test/suite/encryption/t/innochecksum.test b/mysql-test/suite/encryption/t/innochecksum.test index 5423a70f5d9..c2e125368b1 100644 --- a/mysql-test/suite/encryption/t/innochecksum.test +++ b/mysql-test/suite/encryption/t/innochecksum.test @@ -68,9 +68,9 @@ shutdown_server; --echo # Wait until disconnected. --source include/wait_until_disconnected.inc ---echo # Run innochecksum on t1 -- disable_result_log ---exec $INNOCHECKSUM $t1_IBD +--echo # Run innochecksum on t1, check -S does not cause crash for encrypted file +--exec $INNOCHECKSUM -S $t1_IBD --echo # Run innochecksum on t2 -- cgit v1.2.1 From d59b16dd9605d7caecb454fb9efdaa4dfc5770cc Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Tue, 29 Mar 2022 14:58:19 +0200 Subject: Galera test failure on galera_bf_abort_ps_bind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a possible crash on my_free() due to the use of strdup() versus my_strdup(), and a memory leak. Reviewed-by: Jan Lindström --- client/mysqltest.cc | 5 ++++- mysql-test/suite/galera/disabled.def | 2 +- mysql-test/suite/galera/r/galera_bf_abort_ps_bind.result | 1 + mysql-test/suite/galera/t/galera_bf_abort_ps_bind.test | 2 ++ wsrep-lib | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 814c07ba60f..0f910d00927 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -8535,7 +8535,10 @@ void run_prepare_stmt(struct st_connection *cn, struct st_command *command, cons separate string */ if (!disable_warnings) + { append_warnings(&ds_prepare_warnings, mysql); + dynstr_free(&ds_prepare_warnings); + } end: DBUG_VOID_RETURN; } @@ -8611,7 +8614,7 @@ void run_bind_stmt(struct st_connection *cn, struct st_command *command, else { ps_params[i].buffer_type= MYSQL_TYPE_STRING; - ps_params[i].buffer= strdup(p); + ps_params[i].buffer= my_strdup(p, MYF(MY_WME)); ps_params[i].buffer_length= (unsigned long)strlen(p); } } diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 6db86abaa3b..6e8ee8e17a4 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -36,4 +36,4 @@ partition : MDEV-19958 Galera test failure on galera.partition query_cache: MDEV-15805 Test failure on galera.query_cache versioning_trx_id: MDEV-18590: galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch galera_bf_abort_at_after_statement : Unstable -galera_bf_abort_ps_bind : MDEV-28193 Galera test failure on galera_bf_abort_ps_bind + diff --git a/mysql-test/suite/galera/r/galera_bf_abort_ps_bind.result b/mysql-test/suite/galera/r/galera_bf_abort_ps_bind.result index adc7da58eae..02f4dd25f7c 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_ps_bind.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_ps_bind.result @@ -28,6 +28,7 @@ PS_execute; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction PS_execute; commit; +PS_close; select * from t; i j 1 node2 diff --git a/mysql-test/suite/galera/t/galera_bf_abort_ps_bind.test b/mysql-test/suite/galera/t/galera_bf_abort_ps_bind.test index a840f612a82..072a68fc79d 100644 --- a/mysql-test/suite/galera/t/galera_bf_abort_ps_bind.test +++ b/mysql-test/suite/galera/t/galera_bf_abort_ps_bind.test @@ -53,6 +53,8 @@ update t set j='node2' where i=1; --PS_execute commit; +--PS_close + select * from t; drop table t; diff --git a/wsrep-lib b/wsrep-lib index edd141127c1..23fb8624624 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit edd141127c11d78ef073f9f3ca61708821f20b32 +Subproject commit 23fb8624624c9144c77f3874647fa0f7394b0aa8 -- cgit v1.2.1 From bdba1d46bbf08044274cbb5a94a6cb395485c0af Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Sun, 27 Mar 2022 14:02:34 +0700 Subject: MDEV-19631: Assertion `0' failed in st_select_lex_unit::optimize or different plan upon 2nd execution of PS with EXPLAIN Second execution of a prepared statement for a query containing a constant subquery with union that can be optimized away, could result in server abnormal termination for debug build or incorrect result set output for release build. For example, the following test case crashes a server built with debug on second run of the statement EXECUTE stmt CREATE TABLE t1 (a INT); PREPARE stmt FROM 'EXPLAIN SELECT * FROM t1 HAVING 6 IN ( SELECT 6 UNION SELECT 5 )'; EXECUTE stmt; EXECUTE stmt; The reason for incorrect result set output or abnormal server termination is careless working with the data member fake_select_lex->options inside the function mysql_explain_union(). Once the flag SELECT_DESCRIBE is set in the data member fake_select_lex->option before calling the methods SELECT_LEX_UNIT::prepare/SELECT_LEX_UNIT::execute the original value of the option is no longer restored. As a consequence, next time the prepared statement is re-executed we have the fake_select_lex with the flag SELECT_DESCRIBE set in the data member fake_select_lex->option, that is incorrect. In result, the method Item_subselect::assigned() is not invoked during evaluation of a constant condition (constant subquery with union) that being performed on OPTIMIZE phase of query handling. This leads to the fact that records in the temporary table are not deleted before calling table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL) in the method st_select_lex_unit::optimize(). In result table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL) returns error and DBUG_ASSERT(0) is fired. Stack trace to the line where the error generated on re-enabling indexes for next subselect iteration is below: st_select_lex_unit::optimize (at sql_union.cc:954) handler::ha_enable_indexes (at handler.cc:4338) ha_heap::enable_indexes (at ha_heap.cc:519) heap_enable_indexes (at hp_clear.c:164) The code snippet to clarify raising the error is also listed: int heap_enable_indexes(HP_INFO *info) { int error= 0; HP_SHARE *share= info->s; if (share->data_length || share->index_length) error= HA_ERR_CRASHED; <<== set error the value HA_ERR_CRASHED since share->data_length != 0 To fix this issue the original value of unit->fake_select_lex->options has to be saved before setting the flag SELECT_DESCRIBE and restored on return from invocation of SELECT_LEX_UNIT::prepare/SELECT_LEX_UNIT::execute --- mysql-test/r/ps.result | 22 ++++++++++++++++++++++ mysql-test/t/ps.test | 13 +++++++++++++ sql/sql_select.cc | 6 ++++++ 3 files changed, 41 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 1cd41e5b3a4..81167bc85c0 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -5487,5 +5487,27 @@ a DEALLOCATE PREPARE stmt; DROP VIEW v1; DROP TABLE t1; +# +# MDEV-19631: Assertion `0' failed in st_select_lex_unit::optimize or +# different plan upon 2nd execution of PS with EXPLAIN +# +CREATE TABLE t1 (a INT); +PREPARE stmt FROM 'EXPLAIN SELECT * FROM t1 HAVING 6 IN ( SELECT 6 UNION SELECT 5 )'; +EXECUTE stmt; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +# Without the patch the second execution of the 'stmt' prepared statement +# would result in server crash. +EXECUTE stmt; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +DEALLOCATE PREPARE stmt; +DROP TABLE t1; # End of 10.2 tests # diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 4097d28a949..81d8e8e0fed 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -4976,6 +4976,19 @@ DEALLOCATE PREPARE stmt; DROP VIEW v1; DROP TABLE t1; +--echo # +--echo # MDEV-19631: Assertion `0' failed in st_select_lex_unit::optimize or +--echo # different plan upon 2nd execution of PS with EXPLAIN +--echo # +CREATE TABLE t1 (a INT); +PREPARE stmt FROM 'EXPLAIN SELECT * FROM t1 HAVING 6 IN ( SELECT 6 UNION SELECT 5 )'; +EXECUTE stmt; +--echo # Without the patch the second execution of the 'stmt' prepared statement +--echo # would result in server crash. +EXECUTE stmt; +# Cleanup +DEALLOCATE PREPARE stmt; +DROP TABLE t1; --echo # End of 10.2 tests --echo # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a3e8b453897..22d3597de16 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -25400,14 +25400,20 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) if (unit->is_union() || unit->fake_select_lex) { + ulonglong save_options= 0; + if (unit->union_needs_tmp_table() && unit->fake_select_lex) { + save_options= unit->fake_select_lex->options; unit->fake_select_lex->select_number= FAKE_SELECT_LEX_ID; // just for initialization unit->fake_select_lex->type= "UNION RESULT"; unit->fake_select_lex->options|= SELECT_DESCRIBE; } if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE))) res= unit->exec(); + + if (unit->union_needs_tmp_table() && unit->fake_select_lex) + unit->fake_select_lex->options= save_options; } else { -- cgit v1.2.1 From bb4dd70e7c6509ed9bf8c38d44dffb6d2fcca415 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Mon, 28 Mar 2022 15:03:09 +0530 Subject: MDEV-13005: Fixing bugs in SEQUENCE, part 3, 1/5 Task 1: If table is added to list using option TL_OPTION_SEQUENCE (done when we have sequence functions) then then we are dealing with sequence instead of table. So global table list will have sequence set to true. This is used to check and give correct error message about unknown sequence instead of table doesn't exist. --- mysql-test/suite/sql_sequence/alter.result | 5 ++--- mysql-test/suite/sql_sequence/alter.test | 3 ++- mysql-test/suite/sql_sequence/create.result | 12 ++++++++++-- mysql-test/suite/sql_sequence/create.test | 14 ++++++++++++-- mysql-test/suite/sql_sequence/next.result | 2 +- mysql-test/suite/sql_sequence/next.test | 2 +- sql/handler.cc | 4 +++- 7 files changed, 31 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index 612e2201d26..e0acc1c1b23 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -211,10 +211,9 @@ alter sequence t1 minvalue=100; ERROR 42S02: 'test.t1' is not a SEQUENCE drop table t1; alter sequence if exists t1 minvalue=100; -Warnings: -Note 4091 Unknown SEQUENCE: 'test.t1' +ERROR 42S02: Unknown SEQUENCE: 't1' alter sequence t1 minvalue=100; -ERROR 42S02: Table 'test.t1' doesn't exist +ERROR 42S02: Unknown SEQUENCE: 't1' create sequence t1; alter sequence t1; 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 '' at line 1 diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index 53f71018337..a5e6245d609 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -119,8 +119,9 @@ create table t1 (a int); alter sequence t1 minvalue=100; drop table t1; +--error ER_UNKNOWN_SEQUENCES alter sequence if exists t1 minvalue=100; ---error ER_NO_SUCH_TABLE +--error ER_UNKNOWN_SEQUENCES alter sequence t1 minvalue=100; create sequence t1; diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index 5a53a66c9a8..65a4697a6ca 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -478,7 +478,7 @@ next value for t1 1 drop temporary table t1; select previous value for t1; -ERROR 42S02: Table 'test.t1' doesn't exist +ERROR 42S02: Unknown SEQUENCE: 't1' CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10; select next value for t1; next value for t1 @@ -507,7 +507,7 @@ next value for t1 1 drop temporary table t1; select previous value for t1; -ERROR 42S02: Table 'test.t1' doesn't exist +ERROR 42S02: Unknown SEQUENCE: 't1' CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10 engine=innodb; select next value for t1; next value for t1 @@ -687,3 +687,11 @@ set global innodb_force_primary_key=default; ALTER TABLE s1 ADD PRIMARY KEY (next_not_cached_value); ERROR HY000: Sequence 'test.s1' table structure is invalid (Sequence tables cannot have any keys) DROP SEQUENCE s1; +# +# Beginning of 10.4 Test +# +# MDEV-13005: Fixing bugs in SEQUENCE, part 3 +# +# Task 1: +SET @x = PREVIOUS VALUE FOR x; +ERROR 42S02: Unknown SEQUENCE: 'x' diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index ac3aae845cd..9d69924ca71 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -382,7 +382,7 @@ drop view v1; CREATE TEMPORARY SEQUENCE t1; select next value for t1; drop temporary table t1; ---error ER_NO_SUCH_TABLE +--error ER_UNKNOWN_SEQUENCES select previous value for t1; CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10; select next value for t1; @@ -398,7 +398,7 @@ drop sequence t1; CREATE TEMPORARY SEQUENCE t1 engine=innodb; select next value for t1; drop temporary table t1; ---error ER_NO_SUCH_TABLE +--error ER_UNKNOWN_SEQUENCES select previous value for t1; CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10 engine=innodb; select next value for t1; @@ -515,3 +515,13 @@ set global innodb_force_primary_key=default; --error ER_SEQUENCE_INVALID_TABLE_STRUCTURE ALTER TABLE s1 ADD PRIMARY KEY (next_not_cached_value); DROP SEQUENCE s1; + +--echo # +--echo # Beginning of 10.4 Test +--echo # +--echo # MDEV-13005: Fixing bugs in SEQUENCE, part 3 +--echo # + +--echo # Task 1: +--error ER_UNKNOWN_SEQUENCES +SET @x = PREVIOUS VALUE FOR x; diff --git a/mysql-test/suite/sql_sequence/next.result b/mysql-test/suite/sql_sequence/next.result index 76991fbe68c..9d55921006b 100644 --- a/mysql-test/suite/sql_sequence/next.result +++ b/mysql-test/suite/sql_sequence/next.result @@ -387,7 +387,7 @@ previous value for t1 1 drop sequence t1; select previous value for t1; -ERROR 42S02: Table 'test.t1' doesn't exist +ERROR 42S02: Unknown SEQUENCE: 't1' CREATE SEQUENCE t1 start with 5 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle; select previous value for t1; previous value for t1 diff --git a/mysql-test/suite/sql_sequence/next.test b/mysql-test/suite/sql_sequence/next.test index 9f0eebdf774..a80f9fad561 100644 --- a/mysql-test/suite/sql_sequence/next.test +++ b/mysql-test/suite/sql_sequence/next.test @@ -166,7 +166,7 @@ select previous value for t1; flush tables; select previous value for t1; drop sequence t1; ---error ER_NO_SUCH_TABLE +--error ER_UNKNOWN_SEQUENCES select previous value for t1; CREATE SEQUENCE t1 start with 5 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle; select previous value for t1; diff --git a/sql/handler.cc b/sql/handler.cc index 4aff21851a6..1b914012355 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5469,7 +5469,9 @@ int ha_discover_table(THD *thd, TABLE_SHARE *share) else found= plugin_foreach(thd, discover_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, share); - + + if (thd->lex->query_tables && thd->lex->query_tables->sequence && !found) + my_error(ER_UNKNOWN_SEQUENCES, MYF(0),share->table_name.str); if (!found) open_table_error(share, OPEN_FRM_OPEN_ERROR, ENOENT); // not found -- cgit v1.2.1 From 0b9842a3e766ec56ff3e14bec387dc639677c4db Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Mon, 28 Mar 2022 15:08:25 +0530 Subject: MDEV-13005: Fixing bugs in SEQUENCE, part 3, 2/5 Task 2: changed the error message and made it more reusable. --- mysql-test/suite/sql_sequence/alter.result | 6 +++--- mysql-test/suite/sql_sequence/aria.result | 2 +- mysql-test/suite/sql_sequence/create.result | 11 +++++++---- mysql-test/suite/sql_sequence/create.test | 4 ++++ mysql-test/suite/sql_sequence/gtid.result | 10 +++++----- mysql-test/suite/sql_sequence/other.result | 6 +++--- mysql-test/suite/sql_sequence/replication.result | 12 ++++++------ sql/share/errmsg-utf8.txt | 2 +- 8 files changed, 30 insertions(+), 23 deletions(-) diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index e0acc1c1b23..90de2ebfcc0 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -29,7 +29,7 @@ select * from t1; next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count 3 -100 9223372036854775806 50 1 0 0 0 alter sequence t1 minvalue=100 start=100; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options alter sequence t1 minvalue=100 start=100 restart=100; show create sequence t1; Table Create Table @@ -200,11 +200,11 @@ next_not_cached_value minimum_value maximum_value start_value increment cache_si drop sequence t1; CREATE SEQUENCE t1 engine=myisam; alter sequence t1 minvalue=100; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options drop sequence t1; CREATE SEQUENCE t1 engine=myisam; alter sequence t1 minvalue=25 maxvalue=20; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options drop sequence t1; create table t1 (a int); alter sequence t1 minvalue=100; diff --git a/mysql-test/suite/sql_sequence/aria.result b/mysql-test/suite/sql_sequence/aria.result index b39d85d58ca..cfc7d946772 100644 --- a/mysql-test/suite/sql_sequence/aria.result +++ b/mysql-test/suite/sql_sequence/aria.result @@ -53,7 +53,7 @@ next value for s1 drop sequence s1; CREATE SEQUENCE t1; alter sequence t1 minvalue=100; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options alter sequence t1 minvalue=100 start=100 restart=100; rename table t1 to t2; select next value for t2; diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index 65a4697a6ca..a7138756b11 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -167,11 +167,11 @@ drop sequence if exists t1; Warnings: Note 4091 Unknown SEQUENCE: 'test.t1' create sequence t1 start with 10 maxvalue=9; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options create sequence t1 minvalue= 100 maxvalue=10; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options create sequence t1 start with 9 minvalue=10; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options create or replace sequence t1 maxvalue=13, increment by -1; 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 ' increment by -1' at line 1 create or replace sequence t1 start with= 10 maxvalue=13; @@ -183,7 +183,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp create or replace sequence t1 start with 10 min_value=1 NO MINVALUE; 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 'NO MINVALUE' at line 1 create sequence t1 start with 10 maxvalue=9223372036854775807; -ERROR HY000: Sequence 'test.t1' values are conflicting +ERROR HY000: Sequence 'test.t1' has out of range value for options create sequence t1 start with 10 minvalue=-9223372036854775808; 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 '9223372036854775808' at line 1 create sequence t1 RESTART WITH 10; @@ -695,3 +695,6 @@ DROP SEQUENCE s1; # Task 1: SET @x = PREVIOUS VALUE FOR x; ERROR 42S02: Unknown SEQUENCE: 'x' +# Task 2: +CREATE SEQUENCE x START WITH 1 INCREMENT BY 123456789012345678; +ERROR HY000: Sequence 'test.x' has out of range value for options diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index 9d69924ca71..39fb5a9c9cd 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -525,3 +525,7 @@ DROP SEQUENCE s1; --echo # Task 1: --error ER_UNKNOWN_SEQUENCES SET @x = PREVIOUS VALUE FOR x; + +--echo # Task 2: +--error ER_SEQUENCE_INVALID_DATA +CREATE SEQUENCE x START WITH 1 INCREMENT BY 123456789012345678; diff --git a/mysql-test/suite/sql_sequence/gtid.result b/mysql-test/suite/sql_sequence/gtid.result index 8ca9a397354..495e4b806b7 100644 --- a/mysql-test/suite/sql_sequence/gtid.result +++ b/mysql-test/suite/sql_sequence/gtid.result @@ -109,28 +109,28 @@ maxvalue 100000 increment by 1 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options create sequence s2 start with 1 minvalue 5 maxvalue 5 increment by 1 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options create sequence s2 start with 1 minvalue 5 maxvalue 4 increment by 1 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options create sequence s2 start with 1 minvalue 5 maxvalue 4 increment by 0 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options ########################################### global read lock prevent query sequence ########################################### @@ -314,7 +314,7 @@ next_not_cached_value minimum_value maximum_value start_value increment cache_si update s_t set next_not_cached_value= 11,start_value=10, minimum_value=11; ERROR HY000: Storage engine SEQUENCE of the table `s_db`.`s_t` doesn't have this option ALTER SEQUENCE s_t restart with 11 start=10 minvalue=11; -ERROR HY000: Sequence 's_db.s_t' values are conflicting +ERROR HY000: Sequence 's_db.s_t' has out of range value for options commit; create table t_1(id int); insert into t_1 value(1111); diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result index 643233149d2..8ac766702d3 100644 --- a/mysql-test/suite/sql_sequence/other.result +++ b/mysql-test/suite/sql_sequence/other.result @@ -50,9 +50,9 @@ ERROR HY000: Field 'maximum_value' doesn't have a default value insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0); ERROR HY000: Table 's1' is specified twice, both as a target for 'INSERT' and as a separate source for data insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0); -ERROR HY000: Sequence 'test.s1' values are conflicting +ERROR HY000: Sequence 'test.s1' has out of range value for options insert into s1 values(0,9223372036854775806,1,1,1,1000,0,0); -ERROR HY000: Sequence 'test.s1' values are conflicting +ERROR HY000: Sequence 'test.s1' has out of range value for options select * from s1; next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count 1 1 9223372036854775806 1 1 1000 0 0 @@ -67,7 +67,7 @@ select * from s1; next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count 2000 1 9223372036854775806 1 1 1000 0 0 insert into s2 values(0, 1, 10, 1, 2, 1, 1, 0); -ERROR HY000: Sequence 'test.s2' values are conflicting +ERROR HY000: Sequence 'test.s2' has out of range value for options select * from s1; next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count 2000 1 9223372036854775806 1 1 1000 0 0 diff --git a/mysql-test/suite/sql_sequence/replication.result b/mysql-test/suite/sql_sequence/replication.result index 7bf0eac8c47..c429b74b4cd 100644 --- a/mysql-test/suite/sql_sequence/replication.result +++ b/mysql-test/suite/sql_sequence/replication.result @@ -227,28 +227,28 @@ maxvalue 100000 increment by 1 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options create sequence s2 start with 1 minvalue 5 maxvalue 5 increment by 1 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options create sequence s2 start with 1 minvalue 5 maxvalue 4 increment by 1 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options create sequence s2 start with 1 minvalue 5 maxvalue 4 increment by 0 nocache nocycle; -ERROR HY000: Sequence 's_db.s2' values are conflicting +ERROR HY000: Sequence 's_db.s2' has out of range value for options ########################################### global read lock prevent query sequence ########################################### @@ -412,12 +412,12 @@ select * from s_t; next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count 16 1 20 1 1 5 1 0 alter sequence s_t minvalue=11 maxvalue=9; -ERROR HY000: Sequence 's_db.s_t' values are conflicting +ERROR HY000: Sequence 's_db.s_t' has out of range value for options select * from s_t; next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count 16 1 20 1 1 5 1 0 alter sequence s_t restart= 12 start=10 minvalue=11 maxvalue=20; -ERROR HY000: Sequence 's_db.s_t' values are conflicting +ERROR HY000: Sequence 's_db.s_t' has out of range value for options select * from s_t; next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count 16 1 20 1 1 5 1 0 diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 4b744140afb..d913563dae3 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7762,7 +7762,7 @@ ER_END_IDENTIFIER_DOES_NOT_MATCH ER_SEQUENCE_RUN_OUT eng "Sequence '%-.64s.%-.64s' has run out" ER_SEQUENCE_INVALID_DATA - eng "Sequence '%-.64s.%-.64s' values are conflicting" + eng "Sequence '%-.64s.%-.64s' has out of range value for options" ER_SEQUENCE_INVALID_TABLE_STRUCTURE eng "Sequence '%-.64s.%-.64s' table structure is invalid (%s)" ER_SEQUENCE_ACCESS_ERROR -- cgit v1.2.1 From c6eeacd10f87eb437097d755d8dd29211ebdab87 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Mon, 28 Mar 2022 15:12:33 +0530 Subject: MDEV-13005: Fixing bugs in SEQUENCE, part 3, 3/5 Task 3: Added an additional condition for SEQUENCE option to check if cache < 0. --- mysql-test/suite/sql_sequence/create.result | 3 +++ mysql-test/suite/sql_sequence/create.test | 4 ++++ sql/sql_sequence.cc | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index a7138756b11..e80400023e7 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -698,3 +698,6 @@ ERROR 42S02: Unknown SEQUENCE: 'x' # Task 2: CREATE SEQUENCE x START WITH 1 INCREMENT BY 123456789012345678; ERROR HY000: Sequence 'test.x' has out of range value for options +# Task 3: +CREATE SEQUENCE seq1 START WITH 1 cache -1; +ERROR HY000: Sequence 'test.seq1' has out of range value for options diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index 39fb5a9c9cd..766282be781 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -529,3 +529,7 @@ SET @x = PREVIOUS VALUE FOR x; --echo # Task 2: --error ER_SEQUENCE_INVALID_DATA CREATE SEQUENCE x START WITH 1 INCREMENT BY 123456789012345678; + +--echo # Task 3: +--error ER_SEQUENCE_INVALID_DATA +CREATE SEQUENCE seq1 START WITH 1 cache -1; diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index 03f2f1b117f..367fbad144c 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -121,7 +121,7 @@ bool sequence_definition::check_and_adjust(bool set_reserved_until) start >= min_value && max_value != LONGLONG_MAX && min_value != LONGLONG_MIN && - cache < (LONGLONG_MAX - max_increment) / max_increment && + cache >= 0 && cache < (LONGLONG_MAX - max_increment) / max_increment && ((real_increment > 0 && reserved_until >= min_value) || (real_increment < 0 && reserved_until <= max_value))) DBUG_RETURN(FALSE); -- cgit v1.2.1 From a8e7e7c0b4a66a9e92c03b0fe084e98393bafdce Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Mon, 28 Mar 2022 15:18:42 +0530 Subject: MDEV-13005: Fixing bugs in SEQUENCE, part 3, 4/5 Task 4 and 5: Already fixed when I started working on bug. Task 4 correctly gives syntax error ('(' and ')' are not part of create sequence syntax). Task 5 also gives correct error because s1 is table not sequence. Fails with ER_NOT_SEQUENCE2 --- mysql-test/suite/sql_sequence/create.result | 10 ++++++++++ mysql-test/suite/sql_sequence/create.test | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index e80400023e7..a2f63042cd6 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -701,3 +701,13 @@ ERROR HY000: Sequence 'test.x' has out of range value for options # Task 3: CREATE SEQUENCE seq1 START WITH 1 cache -1; ERROR HY000: Sequence 'test.seq1' has out of range value for options +# Task 4: +CREATE TEMPORARY TABLE s1 (s1 INT); +DROP TEMPORARY SEQUENCE s1; +ERROR 42S02: 'test.s1' is not a SEQUENCE +DROP TEMPORARY TABLE s1; +# Task 5: +CREATE TEMPORARY TABLE s1 (s1 INT); +CREATE TEMPORARY SEQUENCE s1 (s1 INT); +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 '(s1 INT)' at line 1 +DROP TEMPORARY TABLE s1; diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index 766282be781..7e0c8f373dd 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -533,3 +533,15 @@ CREATE SEQUENCE x START WITH 1 INCREMENT BY 123456789012345678; --echo # Task 3: --error ER_SEQUENCE_INVALID_DATA CREATE SEQUENCE seq1 START WITH 1 cache -1; + +--echo # Task 4: +CREATE TEMPORARY TABLE s1 (s1 INT); +--error ER_NOT_SEQUENCE2 +DROP TEMPORARY SEQUENCE s1; +DROP TEMPORARY TABLE s1; + +--echo # Task 5: +CREATE TEMPORARY TABLE s1 (s1 INT); +--error ER_PARSE_ERROR +CREATE TEMPORARY SEQUENCE s1 (s1 INT); +DROP TEMPORARY TABLE s1; -- cgit v1.2.1 From 2eaaa8874fbc5212a3813e150d437b36ec34f22e Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Mon, 28 Mar 2022 15:45:29 +0530 Subject: MDEV-13005: Fixing bugs in SEQUENCE, part 3, 5/5 Task 6: We can find the .frm type of file. If it is sequence then is_sequence passed to dd_frm_type() will be true. Since there is already a check to give error message if we trigger is on temporary table or view, an additional condition is added to check if .frm is sequence (is_sequence==true) and error message is changed to show "Trigger's '%-.192s' is view, temporary table or sequence" instead of "Trigger's '%-.192s' is view or temporary table". --- mysql-test/main/trigger.result | 2 +- mysql-test/suite/funcs_1/r/innodb_trig_0407.result | 2 +- mysql-test/suite/funcs_1/r/memory_trig_0407.result | 2 +- mysql-test/suite/funcs_1/r/myisam_trig_0407.result | 2 +- mysql-test/suite/sql_sequence/create.result | 6 ++++++ mysql-test/suite/sql_sequence/create.test | 8 ++++++++ sql/share/errmsg-utf8.txt | 4 ++-- sql/sql_trigger.cc | 12 ++++++++++-- 8 files changed, 30 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/trigger.result b/mysql-test/main/trigger.result index 756fd8591dd..571d78aa9e2 100644 --- a/mysql-test/main/trigger.result +++ b/mysql-test/main/trigger.result @@ -319,7 +319,7 @@ drop table t1; drop table t3; create temporary table t1 (i int); create trigger trg before insert on t1 for each row set @a:=1; -ERROR HY000: Trigger's 't1' is view or temporary table +ERROR HY000: Trigger's 't1' is view, temporary table or sequence drop table t1; create table t1 (x1col char); create trigger tx1 before insert on t1 for each row set new.x1col = 'x'; diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result index 4753efd1794..b2ea135e011 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result @@ -237,7 +237,7 @@ Testcase 3.5.5.2: Create temporary table t1_temp (f1 bigint signed, f2 bigint unsigned); Create trigger trg2 before INSERT on t1_temp for each row set new.f2=9999; -ERROR HY000: Trigger's 't1_temp' is view or temporary table +ERROR HY000: Trigger's 't1_temp' is view, temporary table or sequence drop table t1_temp; Testcase 3.5.5.3: diff --git a/mysql-test/suite/funcs_1/r/memory_trig_0407.result b/mysql-test/suite/funcs_1/r/memory_trig_0407.result index c21c206f118..48858e8787a 100644 --- a/mysql-test/suite/funcs_1/r/memory_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/memory_trig_0407.result @@ -237,7 +237,7 @@ Testcase 3.5.5.2: Create temporary table t1_temp (f1 bigint signed, f2 bigint unsigned); Create trigger trg2 before INSERT on t1_temp for each row set new.f2=9999; -ERROR HY000: Trigger's 't1_temp' is view or temporary table +ERROR HY000: Trigger's 't1_temp' is view, temporary table or sequence drop table t1_temp; Testcase 3.5.5.3: diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result index c21c206f118..48858e8787a 100644 --- a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result @@ -237,7 +237,7 @@ Testcase 3.5.5.2: Create temporary table t1_temp (f1 bigint signed, f2 bigint unsigned); Create trigger trg2 before INSERT on t1_temp for each row set new.f2=9999; -ERROR HY000: Trigger's 't1_temp' is view or temporary table +ERROR HY000: Trigger's 't1_temp' is view, temporary table or sequence drop table t1_temp; Testcase 3.5.5.3: diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index a2f63042cd6..beb1561f9d5 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -711,3 +711,9 @@ CREATE TEMPORARY TABLE s1 (s1 INT); CREATE TEMPORARY SEQUENCE s1 (s1 INT); 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 '(s1 INT)' at line 1 DROP TEMPORARY TABLE s1; +# Task 6: +CREATE SEQUENCE seq1 START WITH 2; +CREATE TRIGGER s1 BEFORE UPDATE ON seq1 FOR EACH ROW SET @a= 5; +ERROR HY000: Trigger's 'seq1' is view, temporary table or sequence +DROP SEQUENCE seq1; +# End of 10.4 test diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index 7e0c8f373dd..aa58b0c5fec 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -545,3 +545,11 @@ CREATE TEMPORARY TABLE s1 (s1 INT); --error ER_PARSE_ERROR CREATE TEMPORARY SEQUENCE s1 (s1 INT); DROP TEMPORARY TABLE s1; + +--echo # Task 6: +CREATE SEQUENCE seq1 START WITH 2; +--error ER_TRG_ON_VIEW_OR_TEMP_TABLE +CREATE TRIGGER s1 BEFORE UPDATE ON seq1 FOR EACH ROW SET @a= 5; +DROP SEQUENCE seq1; + +--echo # End of 10.4 test diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index d913563dae3..40d99ec86b3 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -5421,8 +5421,8 @@ ER_TRG_DOES_NOT_EXIST ger "Trigger existiert nicht" hindi "TRIGGER मौजूद नहीं है" ER_TRG_ON_VIEW_OR_TEMP_TABLE - eng "Trigger's '%-.192s' is view or temporary table" - ger "'%-.192s' des Triggers ist View oder temporäre Tabelle" + eng "Trigger's '%-.192s' is view, temporary table or sequence" + hindi "'%-.192s' एक व्यू, टेम्पररी टेबल या सीक्वेंस है" ER_TRG_CANT_CHANGE_ROW eng "Updating of %s row is not allowed in %strigger" ger "Aktualisieren einer %s-Zeile ist in einem %s-Trigger nicht erlaubt" diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 08cc2113706..8df3cdc6a2e 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -413,6 +413,11 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) bool lock_upgrade_done= FALSE; MDL_ticket *mdl_ticket= NULL; Query_tables_list backup; + char path[FN_REFLEN + 1]; + char engine_name_buf[NAME_CHAR_LEN + 1]; + LEX_CSTRING engine_name= { engine_name_buf, 0 }; + bool is_sequence= 0; + DBUG_ENTER("mysql_create_or_drop_trigger"); /* Charset of the buffer for statement must be system one. */ @@ -529,8 +534,11 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) /* We should have only one table in table list. */ DBUG_ASSERT(tables->next_global == 0); - /* We do not allow creation of triggers on temporary tables. */ - if (create && thd->find_tmp_table_share(tables)) + build_table_filename(path, sizeof(path) - 1, tables->db.str, tables->alias.str, ".frm", 0); + tables->required_type= dd_frm_type(NULL, path, &engine_name, &is_sequence); + + /* We do not allow creation of triggers on temporary tables or sequence. */ + if (is_sequence || (create && thd->find_tmp_table_share(tables))) { my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias.str); goto end; -- cgit v1.2.1 From 35425cfc55b461176f3e1c60d0435595b772ff3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 30 Mar 2022 15:57:08 +0300 Subject: Cleanup: Remove some unused functions --- sql/ha_partition.h | 6 +- sql/handler.cc | 189 +----------------------------------- sql/handler.h | 86 +--------------- storage/federatedx/ha_federatedx.cc | 2 +- 4 files changed, 4 insertions(+), 279 deletions(-) diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 2fccc37ec1f..3e481d9d67c 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -3,7 +3,7 @@ /* Copyright (c) 2005, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2021, MariaDB Corporation. + Copyright (c) 2009, 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 @@ -793,10 +793,6 @@ public: NOTE: This cannot be cached since it can depend on TRANSACTION ISOLATION LEVEL which is dynamic, see bug#39084. - HA_READ_RND_SAME: - Not currently used. (Means that the handler supports the rnd_same() call) - (MyISAM, HEAP) - HA_TABLE_SCAN_ON_INDEX: Used to avoid scanning full tables on an index. If this flag is set then the handler always has a primary key (hidden if not defined) and this diff --git a/sql/handler.cc b/sql/handler.cc index 87592beb5d3..8ac6375ed7c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, MariaDB Corporation. + Copyright (c) 2009, 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 @@ -2531,11 +2531,6 @@ double handler::keyread_time(uint index, uint ranges, ha_rows rows) len*rows/(stats.block_size+1)/TIME_FOR_COMPARE ; } -void **handler::ha_data(THD *thd) const -{ - return thd_ha_data(thd, ht); -} - THD *handler::ha_thd(void) const { DBUG_ASSERT(!table || !table->in_use || table->in_use == current_thd); @@ -6271,17 +6266,6 @@ void handler::unlock_shared_ha_data() mysql_mutex_unlock(&table_share->LOCK_ha_data); } -/** @brief - Dummy function which accept information about log files which is not need - by handlers -*/ -void signal_log_not_needed(struct handlerton, char *log_file) -{ - DBUG_ENTER("signal_log_not_needed"); - DBUG_PRINT("enter", ("logfile '%s'", log_file)); - DBUG_VOID_RETURN; -} - void handler::set_lock_type(enum thr_lock_type lock) { table->reginfo.lock_type= lock; @@ -6384,177 +6368,6 @@ void ha_fake_trx_id(THD *thd) #endif /* WITH_WSREP */ -#ifdef TRANS_LOG_MGM_EXAMPLE_CODE -/* - Example of transaction log management functions based on assumption that logs - placed into a directory -*/ -#include -#include -int example_of_iterator_using_for_logs_cleanup(handlerton *hton) -{ - void *buffer; - int res= 1; - struct handler_iterator iterator; - struct handler_log_file_data data; - - if (!hton->create_iterator) - return 1; /* iterator creator is not supported */ - - if ((*hton->create_iterator)(hton, HA_TRANSACTLOG_ITERATOR, &iterator) != - HA_ITERATOR_OK) - { - /* error during creation of log iterator or iterator is not supported */ - return 1; - } - while((*iterator.next)(&iterator, (void*)&data) == 0) - { - printf("%s\n", data.filename.str); - if (data.status == HA_LOG_STATUS_FREE && - mysql_file_delete(INSTRUMENT_ME, - data.filename.str, MYF(MY_WME))) - goto err; - } - res= 0; -err: - (*iterator.destroy)(&iterator); - return res; -} - - -/* - Here we should get info from handler where it save logs but here is - just example, so we use constant. - IMHO FN_ROOTDIR ("/") is safe enough for example, because nobody has - rights on it except root and it consist of directories only at lest for - *nix (sorry, can't find windows-safe solution here, but it is only example). -*/ -#define fl_dir FN_ROOTDIR - - -/** @brief - Dummy function to return log status should be replaced by function which - really detect the log status and check that the file is a log of this - handler. -*/ -enum log_status fl_get_log_status(char *log) -{ - MY_STAT stat_buff; - if (mysql_file_stat(INSTRUMENT_ME, log, &stat_buff, MYF(0))) - return HA_LOG_STATUS_INUSE; - return HA_LOG_STATUS_NOSUCHLOG; -} - - -struct fl_buff -{ - LEX_STRING *names; - enum log_status *statuses; - uint32 entries; - uint32 current; -}; - - -int fl_log_iterator_next(struct handler_iterator *iterator, - void *iterator_object) -{ - struct fl_buff *buff= (struct fl_buff *)iterator->buffer; - struct handler_log_file_data *data= - (struct handler_log_file_data *) iterator_object; - if (buff->current >= buff->entries) - return 1; - data->filename= buff->names[buff->current]; - data->status= buff->statuses[buff->current]; - buff->current++; - return 0; -} - - -void fl_log_iterator_destroy(struct handler_iterator *iterator) -{ - my_free(iterator->buffer); -} - - -/** @brief - returns buffer, to be assigned in handler_iterator struct -*/ -enum handler_create_iterator_result -fl_log_iterator_buffer_init(struct handler_iterator *iterator) -{ - MY_DIR *dirp; - struct fl_buff *buff; - char *name_ptr; - uchar *ptr; - FILEINFO *file; - uint32 i; - - /* to be able to make my_free without crash in case of error */ - iterator->buffer= 0; - - if (!(dirp = my_dir(fl_dir, MYF(MY_THREAD_SPECIFIC)))) - { - return HA_ITERATOR_ERROR; - } - if ((ptr= (uchar*)my_malloc(ALIGN_SIZE(sizeof(fl_buff)) + - ((ALIGN_SIZE(sizeof(LEX_STRING)) + - sizeof(enum log_status) + - + FN_REFLEN + 1) * - (uint) dirp->number_off_files), - MYF(MY_THREAD_SPECIFIC))) == 0) - { - return HA_ITERATOR_ERROR; - } - buff= (struct fl_buff *)ptr; - buff->entries= buff->current= 0; - ptr= ptr + (ALIGN_SIZE(sizeof(fl_buff))); - buff->names= (LEX_STRING*) (ptr); - ptr= ptr + ((ALIGN_SIZE(sizeof(LEX_STRING)) * - (uint) dirp->number_off_files)); - buff->statuses= (enum log_status *)(ptr); - name_ptr= (char *)(ptr + (sizeof(enum log_status) * - (uint) dirp->number_off_files)); - for (i=0 ; i < (uint) dirp->number_off_files ; i++) - { - enum log_status st; - file= dirp->dir_entry + i; - if ((file->name[0] == '.' && - ((file->name[1] == '.' && file->name[2] == '\0') || - file->name[1] == '\0'))) - continue; - if ((st= fl_get_log_status(file->name)) == HA_LOG_STATUS_NOSUCHLOG) - continue; - name_ptr= strxnmov(buff->names[buff->entries].str= name_ptr, - FN_REFLEN, fl_dir, file->name, NullS); - buff->names[buff->entries].length= (name_ptr - - buff->names[buff->entries].str); - buff->statuses[buff->entries]= st; - buff->entries++; - } - - iterator->buffer= buff; - iterator->next= &fl_log_iterator_next; - iterator->destroy= &fl_log_iterator_destroy; - my_dirend(dirp); - return HA_ITERATOR_OK; -} - - -/* An example of a iterator creator */ -enum handler_create_iterator_result -fl_create_iterator(enum handler_iterator_type type, - struct handler_iterator *iterator) -{ - switch(type) { - case HA_TRANSACTLOG_ITERATOR: - return fl_log_iterator_buffer_init(iterator); - default: - return HA_ITERATOR_UNSUPPORTED; - } -} -#endif /*TRANS_LOG_MGM_EXAMPLE_CODE*/ - - bool HA_CREATE_INFO::check_conflicting_charset_declarations(CHARSET_INFO *cs) { if ((used_fields & HA_CREATE_USED_DEFAULT_CHARSET) && diff --git a/sql/handler.h b/sql/handler.h index 27836f1735f..9bbe8e2fe5e 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -783,31 +783,6 @@ typedef bool (stat_print_fn)(THD *thd, const char *type, size_t type_len, enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; extern MYSQL_PLUGIN_IMPORT st_plugin_int *hton2plugin[MAX_HA]; -/* Transaction log maintains type definitions */ -enum log_status -{ - HA_LOG_STATUS_FREE= 0, /* log is free and can be deleted */ - HA_LOG_STATUS_INUSE= 1, /* log can't be deleted because it is in use */ - HA_LOG_STATUS_NOSUCHLOG= 2 /* no such log (can't be returned by - the log iterator status) */ -}; -/* - Function for signaling that the log file changed its state from - LOG_STATUS_INUSE to LOG_STATUS_FREE - - Now it do nothing, will be implemented as part of new transaction - log management for engines. - TODO: implement the function. -*/ -void signal_log_not_needed(struct handlerton, char *log_file); -/* - Data of transaction log iterator. -*/ -struct handler_log_file_data { - LEX_STRING filename; - enum log_status status; -}; - /* Definitions for engine-specific table/field/index options in the CREATE TABLE. @@ -922,46 +897,6 @@ typedef struct st_ha_create_table_option { struct st_mysql_sys_var *var; } ha_create_table_option; -enum handler_iterator_type -{ - /* request of transaction log iterator */ - HA_TRANSACTLOG_ITERATOR= 1 -}; -enum handler_create_iterator_result -{ - HA_ITERATOR_OK, /* iterator created */ - HA_ITERATOR_UNSUPPORTED, /* such type of iterator is not supported */ - HA_ITERATOR_ERROR /* error during iterator creation */ -}; - -/* - Iterator structure. Can be used by handler/handlerton for different purposes. - - Iterator should be created in the way to point "before" the first object - it iterate, so next() call move it to the first object or return !=0 if - there is nothing to iterate through. -*/ -struct handler_iterator { - /* - Moves iterator to next record and return 0 or return !=0 - if there is no records. - iterator_object will be filled by this function if next() returns 0. - Content of the iterator_object depend on iterator type. - */ - int (*next)(struct handler_iterator *, void *iterator_object); - /* - Free resources allocated by iterator, after this call iterator - is not usable. - */ - void (*destroy)(struct handler_iterator *); - /* - Pointer to buffer for the iterator to use. - Should be allocated by function which created the iterator and - destroyed by freed by above "destroy" call - */ - void *buffer; -}; - class handler; class group_by_handler; struct Query; @@ -1223,22 +1158,6 @@ struct handlerton const char *query, uint query_length, const char *db, const char *table_name); - /* - Get log status. - If log_status is null then the handler do not support transaction - log information (i.e. log iterator can't be created). - (see example of implementation in handler.cc, TRANS_LOG_MGM_EXAMPLE_CODE) - - */ - enum log_status (*get_log_status)(handlerton *hton, char *log); - - /* - Iterators creator. - Presence of the pointer should be checked before using - */ - enum handler_create_iterator_result - (*create_iterator)(handlerton *hton, enum handler_iterator_type type, - struct handler_iterator *fill_this_in); void (*abort_transaction)(handlerton *hton, THD *bf_thd, THD *victim_thd, my_bool signal); int (*set_checkpoint)(handlerton *hton, const XID* xid); @@ -3291,15 +3210,13 @@ public: inline int ha_read_first_row(uchar *buf, uint primary_key); /** - The following 3 function is only needed for tables that may be + The following 2 function is only needed for tables that may be internal temporary tables during joins. */ virtual int remember_rnd_pos() { return HA_ERR_WRONG_COMMAND; } virtual int restart_rnd_next(uchar *buf) { return HA_ERR_WRONG_COMMAND; } - virtual int rnd_same(uchar *buf, uint inx) - { return HA_ERR_WRONG_COMMAND; } virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key) @@ -3970,7 +3887,6 @@ public: TABLE_SHARE* get_table_share() { return table_share; } protected: /* Service methods for use by storage engines. */ - void **ha_data(THD *) const; THD *ha_thd(void) const; /** diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 65947c730e0..80497ec4e76 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1720,7 +1720,7 @@ ha_rows ha_federatedx::records_in_range(uint inx, key_range *start_key, federatedx_txn *ha_federatedx::get_txn(THD *thd, bool no_create) { - federatedx_txn **txnp= (federatedx_txn **) ha_data(thd); + federatedx_txn **txnp= (federatedx_txn **) thd_ha_data(thd, ht); if (!*txnp && !no_create) *txnp= new federatedx_txn(); return *txnp; -- cgit v1.2.1 From c1ab0e6fc6b390965e03867bd010b58b1c5cf29e Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Wed, 30 Mar 2022 19:27:44 +0300 Subject: MDEV-27343 Useless warning "InnoDB: Allocated tablespace ID for , old maximum was 0" during backup stage mariabackup does not load dictionary during backup, but it loads tablespaces, that is why fil_system.max_assigned_id is not set with dict_check_tablespaces_and_store_max_id(). There is no sense to issue the warning during backup. --- mysql-test/suite/mariabackup/full_backup.result | 1 + mysql-test/suite/mariabackup/full_backup.test | 9 ++++++++- storage/innobase/fil/fil0fil.cc | 10 ++++++---- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/mariabackup/full_backup.result b/mysql-test/suite/mariabackup/full_backup.result index c387f5328a7..954151bbad7 100644 --- a/mysql-test/suite/mariabackup/full_backup.result +++ b/mysql-test/suite/mariabackup/full_backup.result @@ -1,6 +1,7 @@ CREATE TABLE t(i INT) ENGINE INNODB; INSERT INTO t VALUES(1); # xtrabackup backup +NOT FOUND /InnoDB: Allocated tablespace ID/ in backup.log INSERT INTO t VALUES(2); # xtrabackup prepare # shutdown server diff --git a/mysql-test/suite/mariabackup/full_backup.test b/mysql-test/suite/mariabackup/full_backup.test index d1d2ea21c08..66bed34cf3d 100644 --- a/mysql-test/suite/mariabackup/full_backup.test +++ b/mysql-test/suite/mariabackup/full_backup.test @@ -4,11 +4,18 @@ CREATE TABLE t(i INT) ENGINE INNODB; INSERT INTO t VALUES(1); echo # xtrabackup backup; let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +--let $backup_log=$MYSQLTEST_VARDIR/tmp/backup.log --disable_result_log -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir > $backup_log 2>&1; --enable_result_log +# The following warning must not appear after MDEV-27343 fix +--let SEARCH_PATTERN=InnoDB: Allocated tablespace ID +--let SEARCH_FILE=$backup_log +--source include/search_pattern_in_file.inc +--remove_file $backup_log + INSERT INTO t VALUES(2); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 6980078f87d..f65a7428482 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1418,10 +1418,12 @@ fil_space_create( if (!fil_system->space_id_reuse_warned) { fil_system->space_id_reuse_warned = true; - - ib::warn() << "Allocated tablespace ID " << id - << " for " << name << ", old maximum was " - << fil_system->max_assigned_id; + if (srv_operation != SRV_OPERATION_BACKUP) { + ib::warn() << "Allocated tablespace ID " << id + << " for " << name + << ", old maximum was " + << fil_system->max_assigned_id; + } } fil_system->max_assigned_id = id; -- cgit v1.2.1 From 69be3c13b66f75a0f093b0685d28ea793266b172 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 31 Mar 2022 15:40:17 +0300 Subject: Fixed unlikely assert/crash if initialization of translog failed This was noticed as part of verifying MDEV-28186 "crash on startup after crash while regular use" but is probably not related to the users issue. Still good to have it fixed --- storage/maria/ma_loghandler.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 9de4480062b..8455cbb80de 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -8936,20 +8936,23 @@ void translog_hard_group_commit(my_bool mode) void translog_sync() { - uint32 max= get_current_logfile()->number; - uint32 min; DBUG_ENTER("ma_translog_sync"); - min= soft_sync_min; - if (!min) - min= max; + /* The following is only true if initalization of translog succeded */ + if (log_descriptor.open_files.elements != 0) + { + uint32 max= get_current_logfile()->number; + uint32 min; - translog_sync_files(min, max, sync_log_dir >= TRANSLOG_SYNC_DIR_ALWAYS); + min= soft_sync_min; + if (!min) + min= max; + translog_sync_files(min, max, sync_log_dir >= TRANSLOG_SYNC_DIR_ALWAYS); + } DBUG_VOID_RETURN; } - /** @brief set rate for group commit -- cgit v1.2.1 From c62843a055f52b27230926b12d9ee4f7aa68e1a0 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Thu, 31 Mar 2022 13:00:46 -0600 Subject: MDEV-25580: rpl.rpl_semi_sync_slave_compressed_protocol crashes because of wrong packet rpl.rpl_semi_sync_slave_compressed_protocol.test was manually re-enabled only in 10.3 but left disabled in 10.4+. The fix went into 10.3+, but the test was left disabled in later versions. This commit re-enables the test in 10.4+. --- mysql-test/suite/rpl/disabled.def | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/suite/rpl/disabled.def b/mysql-test/suite/rpl/disabled.def index bdc01f9efcb..548cff54834 100644 --- a/mysql-test/suite/rpl/disabled.def +++ b/mysql-test/suite/rpl/disabled.def @@ -14,6 +14,5 @@ rpl_partition_archive : MDEV-5077 2013-09-27 svoj Cannot exchange partition rpl_row_binlog_max_cache_size : MDEV-11092 rpl_row_index_choice : MDEV-11666 rpl_semi_sync_after_sync : fails after MDEV-16172 -rpl_semi_sync_slave_compressed_protocol : MDEV-25580 2021-05-05 Sujatha rpl_auto_increment_update_failure : disabled for now rpl_current_user : waits for MDEV-22374 fix -- cgit v1.2.1 From 49aee1a153a8401b0e8fc42bc73d7d42ab1be18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 1 Apr 2022 13:29:31 +0300 Subject: MDEV-28210 : SIGSEGV in the test galera.galera_sst_rsync2 We should make sure that wsrep exists before calling wsrep->post_rollback --- sql/wsrep_hton.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 05be257cbcb..1e302734df8 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -1,4 +1,4 @@ -/* Copyright 2008-2015 Codership Oy +/* Copyright 2008-2022 Codership Oy 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 @@ -155,7 +155,7 @@ void wsrep_post_commit(THD* thd, bool all) */ if (all && thd->wsrep_conflict_state != MUST_REPLAY && thd->wsrep_conflict_state != REPLAYING && - wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle)) + wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle)) { WSREP_WARN("post_rollback fail: %llu %d", (long long)thd->thread_id, thd->get_stmt_da()->status()); -- cgit v1.2.1 From 1118b66a22bbbe832b6429d7d1b3478119980f21 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Tue, 8 Sep 2020 00:01:09 +0200 Subject: MDEV-23626: CONNECT VIR tables return inconsistent error for UPDATE - Before the patch UPDATE error message for VIR tables was different from TRUNCATE,UPDATE,DELETE Reviewed by: , vicentiu@mariadb.org --- storage/connect/connect.cc | 7 +++++++ storage/connect/mysql-test/connect/r/general.result | 14 ++++++++++++++ storage/connect/mysql-test/connect/t/general.test | 17 +++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc index ee62e0cd03e..8aceee61f36 100644 --- a/storage/connect/connect.cc +++ b/storage/connect/connect.cc @@ -297,6 +297,13 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2, PTDB utp; if (!(utp = tdbp->Duplicate(g))) { + /* If table type is of type virtual retrieve global parameter as it was.*/ + if (tdbp->GetAmType() == TYPE_AM_VIR) { + if (tdbp->OpenDB(g)) { + printf("%s\n", g->Message); + throw 7; + } + } sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName()); throw 4; } // endif tp diff --git a/storage/connect/mysql-test/connect/r/general.result b/storage/connect/mysql-test/connect/r/general.result index ed2c903145d..ef023b7c8d9 100644 --- a/storage/connect/mysql-test/connect/r/general.result +++ b/storage/connect/mysql-test/connect/r/general.result @@ -16,3 +16,17 @@ SELECT * FROM t1; a 10 DROP TABLE t1; +# +# MDEV-23626: CONNECT VIR tables return inconsistent error for UPDATE +# +CREATE TABLE numbers +ENGINE=CONNECT, +TABLE_TYPE=VIR, +BLOCK_SIZE=3; +TRUNCATE TABLE numbers; +ERROR HY000: Got error 174 'Virtual tables are read only' from CONNECT +DELETE FROM numbers WHERE n = 1; +ERROR HY000: Got error 174 'Virtual tables are read only' from CONNECT +UPDATE numbers SET n = 10 WHERE n = 1; +ERROR HY000: Got error 174 'Virtual tables are read only' from CONNECT +DROP TABLE numbers; diff --git a/storage/connect/mysql-test/connect/t/general.test b/storage/connect/mysql-test/connect/t/general.test index 34e5d4c7b6d..e2f228738cf 100644 --- a/storage/connect/mysql-test/connect/t/general.test +++ b/storage/connect/mysql-test/connect/t/general.test @@ -14,3 +14,20 @@ SELECT * FROM t1; ALTER TABLE t1 TABLE_TYPE=NON_EXISTING; SELECT * FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-23626: CONNECT VIR tables return inconsistent error for UPDATE +--echo # + +CREATE TABLE numbers +ENGINE=CONNECT, +TABLE_TYPE=VIR, +BLOCK_SIZE=3; + +--error ER_GET_ERRMSG +TRUNCATE TABLE numbers; +--error ER_GET_ERRMSG +DELETE FROM numbers WHERE n = 1; +--error ER_GET_ERRMSG +UPDATE numbers SET n = 10 WHERE n = 1; +DROP TABLE numbers; -- cgit v1.2.1 From 8c169f5e03441324d935b68335f0894ec51b0b60 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Sat, 2 Apr 2022 16:43:51 +0700 Subject: MDEV-28220: Assert failure in sp_head::~sp_head on parsing a syntax incorrect statement CREATE SEQUENCE ... RESTART inside CREATE PROCEDURE/CREATE FUNCTION This bug report is about the same issue as MDEV-28129 and MDEV-21173. The issue is that the macros YYABORT is called instead of MYSQL_YYABORT on parse error. In result the method LEX::cleanup_lex_after_parse_error is not called to clean up data structures created on parsing of the statement. --- mysql-test/main/sp.result | 13 +++++++++++++ mysql-test/main/sp.test | 15 +++++++++++++++ sql/sql_yacc.yy | 4 ++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 6e8ae437d8b..70fe91863a3 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8921,4 +8921,17 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp BEGIN RETURN ''; END' at line 2 +# +# MDEV-28220: Assert failure in sp_head::~sp_head on parsing a syntax incorrect statement CREATE SEQUENCE ... RESTART inside CREATE PROCEDURE/CREATE FUNCTION + +# Specifying the RESTART clause for the statement CREATE SEQUENCE is a syntax error. +# Check that CREATE PROCEDURE doesn't crash server if the statement +# CREATE SEQUNCE ... RESTART is specified in its body. +# +CREATE PROCEDURE sp1() CREATE SEQUENCE s1 START WITH 300 INCREMENT BY 30 RESTART; +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 'RESTART' at line 1 +# CREATE SEQUNCE ... RESTART and CREATE SEQUNCE ... RESTART WITH ... are +# handled by different grammar rules, so check the both cases. +CREATE PROCEDURE sp1() CREATE SEQUENCE s1 START WITH 300 INCREMENT BY 30 RESTART WITH 100; +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 'RESTART' at line 1 # End of 10.3 tests diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index f311baccd08..d167c1e8f73 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10474,4 +10474,19 @@ END; $$ DELIMITER ;$$ +--echo # +--echo # MDEV-28220: Assert failure in sp_head::~sp_head on parsing a syntax incorrect statement CREATE SEQUENCE ... RESTART inside CREATE PROCEDURE/CREATE FUNCTION +--echo + +--echo # Specifying the RESTART clause for the statement CREATE SEQUENCE is a syntax error. +--echo # Check that CREATE PROCEDURE doesn't crash server if the statement +--echo # CREATE SEQUNCE ... RESTART is specified in its body. +--echo # +--error ER_PARSE_ERROR +CREATE PROCEDURE sp1() CREATE SEQUENCE s1 START WITH 300 INCREMENT BY 30 RESTART; +--echo # CREATE SEQUNCE ... RESTART and CREATE SEQUNCE ... RESTART WITH ... are +--echo # handled by different grammar rules, so check the both cases. +--error ER_PARSE_ERROR +CREATE PROCEDURE sp1() CREATE SEQUENCE s1 START WITH 300 INCREMENT BY 30 RESTART WITH 100; + --echo # End of 10.3 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a427c7a40c5..3770488f3f4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3037,7 +3037,7 @@ sequence_def: if (unlikely(Lex->sql_command != SQLCOM_ALTER_SEQUENCE)) { thd->parse_error(ER_SYNTAX_ERROR, "RESTART"); - YYABORT; + MYSQL_YYABORT; } if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_restart)) @@ -3049,7 +3049,7 @@ sequence_def: if (unlikely(Lex->sql_command != SQLCOM_ALTER_SEQUENCE)) { thd->parse_error(ER_SYNTAX_ERROR, "RESTART"); - YYABORT; + MYSQL_YYABORT; } if (unlikely(Lex->create_info.seq_create_info->used_fields & seq_field_used_restart)) -- cgit v1.2.1 From 75b9014fedd8bb85d15501a2281fbade6b56fe78 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 1 Apr 2022 16:07:12 +1100 Subject: MDEV-26136: Correct AIX/macOS cast warning (my_time.h) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tv_usec is a (suseconds_t) so we cast to it. Prevents the AIX(gcc-10) warning: include/my_time.h: In function 'void my_timeval_trunc(timeval*, uint)': include/my_time.h:249:65: warning: conversion from 'long int' to 'suseconds_t' {aka 'int'} may change value [-Wconversion] 249 | tv->tv_usec-= my_time_fraction_remainder(tv->tv_usec, decimals); | macOS is: conversion from 'long int' to '__darwin_suseconds_t' {aka 'int'} may change value On Windows suseconds_t isn't defined so we use the existing long return type of my_time_fraction_remainder. Reviewed by Marko Mäkelä Closes: #2079 --- include/my_time.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/my_time.h b/include/my_time.h index eeb790cdb54..9fb3bf199bf 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -220,9 +220,12 @@ static inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals) { ltime->second_part-= my_time_fraction_remainder(ltime->second_part, decimals); } +#ifdef _WIN32 +#define suseconds_t long +#endif static inline void my_timeval_trunc(struct timeval *tv, uint decimals) { - tv->tv_usec-= my_time_fraction_remainder(tv->tv_usec, decimals); + tv->tv_usec-= (suseconds_t) my_time_fraction_remainder(tv->tv_usec, decimals); } -- cgit v1.2.1 From d271fbd392b02ff8b98d552aef7164270c9d66fd Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 4 Apr 2022 08:50:24 +0400 Subject: MDEV-28224 error: cannot initialize return object of type 'bool' with an rvalue of type 'nullptr_t' Fixing a typo in the fix for MDEV-19804, wrong return value in a bool function: < return NULL; > return true; The problem was found because it did not compile on some platforms. Strangley, it did not have visible problems on other platforms, which did not fail to compile, although "return NULL" should compile to "return false" rather than "return true". --- sql/sql_lex.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c70fef9709f..7f1b362d91d 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -7906,18 +7906,18 @@ bool LEX::call_statement_start(THD *thd, const LEX_CSTRING &db, if (check_db_name((LEX_STRING*) const_cast(&db))) { my_error(ER_WRONG_DB_NAME, MYF(0), db.str); - return NULL; + return true; } if (check_routine_name(&pkg) || check_routine_name(&proc)) - return NULL; + return true; // Concat `pkg` and `name` to `pkg.name` LEX_CSTRING pkg_dot_proc; if (q_pkg_proc.make_qname(thd->mem_root, &pkg_dot_proc) || check_ident_length(&pkg_dot_proc) || !(spname= new (thd->mem_root) sp_name(&db, &pkg_dot_proc, true))) - return NULL; + return true; sp_handler_package_function.add_used_routine(thd->lex, thd, spname); sp_handler_package_body.add_used_routine(thd->lex, thd, &q_db_pkg); -- cgit v1.2.1 From 0ffaf19c53ccd102a369016cd01dec38ee9ac5a7 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 4 Apr 2022 09:45:29 +0400 Subject: Adding a "const" qualifier to arguments of create_func(), create_native() etc The "const" qualifier was obviously forgotten. This change will also simpily fixing of MDEV-27744. --- plugin/versioning/versioning.cc | 8 +- sql/item_create.cc | 334 ++++++++++++++++++++++++---------------- sql/item_create.h | 15 +- 3 files changed, 215 insertions(+), 142 deletions(-) diff --git a/plugin/versioning/versioning.cc b/plugin/versioning/versioning.cc index 56f8f1f5a1d..fd0e7099666 100644 --- a/plugin/versioning/versioning.cc +++ b/plugin/versioning/versioning.cc @@ -29,7 +29,8 @@ template class Create_func_trt : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_trt s_singleton; @@ -43,7 +44,7 @@ Create_func_trt Create_func_trt::s_singleton; template Item* -Create_func_trt::create_native(THD *thd, LEX_CSTRING *name, +Create_func_trt::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -102,7 +103,8 @@ template class Create_func_trt_trx_sees : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list) + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; diff --git a/sql/item_create.cc b/sql/item_create.cc index 657397c41dd..52e0312f89b 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -49,7 +49,7 @@ class Create_func_arg0 : public Create_func { public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, List *item_list); /** @@ -74,7 +74,8 @@ protected: class Create_func_arg1 : public Create_func { public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, + List *item_list); /** Builder method, with one argument. @@ -99,7 +100,8 @@ protected: class Create_func_arg2 : public Create_func { public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, + List *item_list); /** Builder method, with two arguments. @@ -124,7 +126,8 @@ protected: class Create_func_arg3 : public Create_func { public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, + List *item_list); /** Builder method, with three arguments. @@ -150,7 +153,9 @@ protected: class Create_sp_func : public Create_qfunc { public: - virtual Item *create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name, + virtual Item *create_with_db(THD *thd, + const LEX_CSTRING *db, + const LEX_CSTRING *name, bool use_explicit_name, List *item_list); static Create_sp_func s_singleton; @@ -173,7 +178,8 @@ protected: class Create_func_no_geom : public Create_func { public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, + List *item_list); /** Singleton. */ static Create_func_no_geom s_singleton; @@ -319,7 +325,8 @@ protected: class Create_func_atan : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_atan s_singleton; @@ -553,7 +560,8 @@ protected: class Create_func_concat : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_concat s_singleton; @@ -566,7 +574,8 @@ protected: class Create_func_concat_operator_oracle : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_concat_operator_oracle s_singleton; @@ -592,7 +601,8 @@ protected: class Create_func_decode_oracle : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_decode_oracle s_singleton; @@ -605,7 +615,8 @@ protected: class Create_func_concat_ws : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_concat_ws s_singleton; @@ -830,7 +841,8 @@ protected: class Create_func_des_decrypt : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_des_decrypt s_singleton; @@ -843,7 +855,8 @@ protected: class Create_func_des_encrypt : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_des_encrypt s_singleton; @@ -911,7 +924,8 @@ class Create_func_distance : public Create_func_arg2 class Create_func_distance_sphere: public Create_native_func { public: - Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_distance_sphere s_singleton; protected: @@ -925,7 +939,8 @@ class Create_func_distance_sphere: public Create_native_func class Create_func_elt : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_elt s_singleton; @@ -951,7 +966,8 @@ protected: class Create_func_encrypt : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_encrypt s_singleton; @@ -1047,7 +1063,8 @@ protected: class Create_func_export_set : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_export_set s_singleton; @@ -1075,7 +1092,8 @@ protected: class Create_func_field : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_field s_singleton; @@ -1114,7 +1132,8 @@ protected: class Create_func_format : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_format s_singleton; @@ -1166,7 +1185,8 @@ protected: class Create_func_from_unixtime : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_from_unixtime s_singleton; @@ -1180,7 +1200,8 @@ protected: class Create_func_geometry_from_text : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_geometry_from_text s_singleton; @@ -1195,7 +1216,8 @@ protected: class Create_func_geometry_from_wkb : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_geometry_from_wkb s_singleton; @@ -1210,7 +1232,8 @@ protected: class Create_func_geometry_from_json : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_geometry_from_json s_singleton; @@ -1223,7 +1246,8 @@ protected: class Create_func_as_geojson : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_as_geojson s_singleton; @@ -1310,7 +1334,8 @@ protected: class Create_func_greatest : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_greatest s_singleton; @@ -1736,7 +1761,8 @@ protected: class Create_func_json_detailed: public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_detailed s_singleton; @@ -1801,7 +1827,8 @@ protected: class Create_func_json_keys: public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_keys s_singleton; @@ -1814,7 +1841,8 @@ protected: class Create_func_json_contains: public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_contains s_singleton; @@ -1827,7 +1855,8 @@ protected: class Create_func_json_contains_path : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_contains_path s_singleton; @@ -1840,7 +1869,8 @@ protected: class Create_func_json_extract : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_extract s_singleton; @@ -1853,7 +1883,8 @@ protected: class Create_func_json_search : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_search s_singleton; @@ -1866,7 +1897,8 @@ protected: class Create_func_json_array : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_array s_singleton; @@ -1879,7 +1911,8 @@ protected: class Create_func_json_array_append : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_array_append s_singleton; @@ -1892,7 +1925,8 @@ protected: class Create_func_json_array_insert : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_array_insert s_singleton; @@ -1905,7 +1939,8 @@ protected: class Create_func_json_insert : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_insert s_singleton; @@ -1918,7 +1953,8 @@ protected: class Create_func_json_set : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_set s_singleton; @@ -1931,7 +1967,8 @@ protected: class Create_func_json_replace : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_replace s_singleton; @@ -1944,7 +1981,8 @@ protected: class Create_func_json_remove : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_remove s_singleton; @@ -1957,7 +1995,8 @@ protected: class Create_func_json_object : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_object s_singleton; @@ -1970,7 +2009,8 @@ protected: class Create_func_json_length : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_length s_singleton; @@ -1983,7 +2023,8 @@ protected: class Create_func_json_merge : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_merge s_singleton; @@ -1996,7 +2037,8 @@ protected: class Create_func_json_merge_patch : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_json_merge_patch s_singleton; @@ -2048,7 +2090,8 @@ protected: class Create_func_last_insert_id : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_last_insert_id s_singleton; @@ -2074,7 +2117,8 @@ protected: class Create_func_least : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_least s_singleton; @@ -2166,7 +2210,8 @@ protected: class Create_func_locate : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_locate s_singleton; @@ -2179,7 +2224,8 @@ protected: class Create_func_log : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_log s_singleton; @@ -2218,7 +2264,7 @@ protected: class Create_func_lpad : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { return thd->variables.sql_mode & MODE_ORACLE ? @@ -2230,15 +2276,18 @@ public: protected: Create_func_lpad() {} virtual ~Create_func_lpad() {} - Item *create_native_std(THD *thd, LEX_CSTRING *name, List *items); - Item *create_native_oracle(THD *thd, LEX_CSTRING *name, List *items); + Item *create_native_std(THD *thd, const LEX_CSTRING *name, + List *items); + Item *create_native_oracle(THD *thd, const LEX_CSTRING *name, + List *items); }; class Create_func_lpad_oracle : public Create_func_lpad { public: - Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list) + Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { return create_native_oracle(thd, name, item_list); } @@ -2301,7 +2350,8 @@ protected: class Create_func_make_set : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_make_set s_singleton; @@ -2314,7 +2364,8 @@ protected: class Create_func_master_pos_wait : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_master_pos_wait s_singleton; @@ -2327,7 +2378,8 @@ protected: class Create_func_master_gtid_wait : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_master_gtid_wait s_singleton; @@ -2623,7 +2675,8 @@ protected: class Create_func_rand : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_rand s_singleton; @@ -2675,7 +2728,8 @@ protected: class Create_func_round : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_round s_singleton; @@ -2688,7 +2742,7 @@ protected: class Create_func_rpad : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { return thd->variables.sql_mode & MODE_ORACLE ? @@ -2700,15 +2754,18 @@ public: protected: Create_func_rpad() {} virtual ~Create_func_rpad() {} - Item *create_native_std(THD *thd, LEX_CSTRING *name, List *items); - Item *create_native_oracle(THD *thd, LEX_CSTRING *name, List *items); + Item *create_native_std(THD *thd, const LEX_CSTRING *name, + List *items); + Item *create_native_oracle(THD *thd, const LEX_CSTRING *name, + List *items); }; class Create_func_rpad_oracle : public Create_func_rpad { public: - Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list) + Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { return create_native_oracle(thd, name, item_list); } @@ -2931,7 +2988,7 @@ protected: class Create_func_substr_oracle : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list); static Create_func_substr_oracle s_singleton; @@ -3115,7 +3172,8 @@ protected: class Create_func_unix_timestamp : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_unix_timestamp s_singleton; @@ -3277,7 +3335,8 @@ protected: class Create_func_year_week : public Create_native_func { public: - virtual Item *create_native(THD *thd, LEX_CSTRING *name, List *item_list); + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, + List *item_list); static Create_func_year_week s_singleton; @@ -3321,7 +3380,7 @@ Create_func_no_geom Create_func_no_geom::s_singleton; Item* Create_func_no_geom::create_func(THD * /* unused */, - LEX_CSTRING /* unused */, + const LEX_CSTRING /* unused */, List * /* unused */) { /* FIXME: error message can't be translated. */ @@ -3333,7 +3392,8 @@ Create_func_no_geom::create_func(THD * /* unused */, Item* -Create_qfunc::create_func(THD *thd, LEX_CSTRING *name, List *item_list) +Create_qfunc::create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) { LEX_CSTRING db; @@ -3366,7 +3426,8 @@ Create_qfunc::create_func(THD *thd, LEX_CSTRING *name, List *item_list) Create_udf_func Create_udf_func::s_singleton; Item* -Create_udf_func::create_func(THD *thd, LEX_CSTRING *name, List *item_list) +Create_udf_func::create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) { udf_func *udf= find_udf(name->str, name->length); DBUG_ASSERT(udf); @@ -3476,7 +3537,9 @@ Create_udf_func::create(THD *thd, udf_func *udf, List *item_list) Create_sp_func Create_sp_func::s_singleton; Item* -Create_sp_func::create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name, +Create_sp_func::create_with_db(THD *thd, + const LEX_CSTRING *db, + const LEX_CSTRING *name, bool use_explicit_name, List *item_list) { int arg_count= 0; @@ -3524,7 +3587,8 @@ Create_sp_func::create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name, Item* -Create_native_func::create_func(THD *thd, LEX_CSTRING *name, List *item_list) +Create_native_func::create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) { if (unlikely(has_named_parameters(item_list))) { @@ -3537,7 +3601,8 @@ Create_native_func::create_func(THD *thd, LEX_CSTRING *name, List *item_li Item* -Create_func_arg0::create_func(THD *thd, LEX_CSTRING *name, List *item_list) +Create_func_arg0::create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) { int arg_count= 0; @@ -3555,7 +3620,8 @@ Create_func_arg0::create_func(THD *thd, LEX_CSTRING *name, List *item_list Item* -Create_func_arg1::create_func(THD *thd, LEX_CSTRING *name, List *item_list) +Create_func_arg1::create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) { int arg_count= 0; @@ -3581,7 +3647,8 @@ Create_func_arg1::create_func(THD *thd, LEX_CSTRING *name, List *item_list Item* -Create_func_arg2::create_func(THD *thd, LEX_CSTRING *name, List *item_list) +Create_func_arg2::create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) { int arg_count= 0; @@ -3609,7 +3676,8 @@ Create_func_arg2::create_func(THD *thd, LEX_CSTRING *name, List *item_list Item* -Create_func_arg3::create_func(THD *thd, LEX_CSTRING *name, List *item_list) +Create_func_arg3::create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) { int arg_count= 0; @@ -3728,7 +3796,7 @@ Create_func_asin::create_1_arg(THD *thd, Item *arg1) Create_func_atan Create_func_atan::s_singleton; Item* -Create_func_atan::create_native(THD *thd, LEX_CSTRING *name, +Create_func_atan::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item* func= NULL; @@ -3919,7 +3987,7 @@ Create_func_dyncol_json::create_1_arg(THD *thd, Item *arg1) Create_func_concat Create_func_concat::s_singleton; Item* -Create_func_concat::create_native(THD *thd, LEX_CSTRING *name, +Create_func_concat::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -3942,7 +4010,7 @@ Create_func_concat_operator_oracle Create_func_concat_operator_oracle::s_singleton; Item* -Create_func_concat_operator_oracle::create_native(THD *thd, LEX_CSTRING *name, +Create_func_concat_operator_oracle::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -3970,7 +4038,7 @@ Create_func_decode_histogram::create_2_arg(THD *thd, Item *arg1, Item *arg2) Create_func_decode_oracle Create_func_decode_oracle::s_singleton; Item* -Create_func_decode_oracle::create_native(THD *thd, LEX_CSTRING *name, +Create_func_decode_oracle::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { uint arg_count= item_list ? item_list->elements : 0; @@ -3985,7 +4053,7 @@ Create_func_decode_oracle::create_native(THD *thd, LEX_CSTRING *name, Create_func_concat_ws Create_func_concat_ws::s_singleton; Item* -Create_func_concat_ws::create_native(THD *thd, LEX_CSTRING *name, +Create_func_concat_ws::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -4172,7 +4240,7 @@ Create_func_degrees::create_1_arg(THD *thd, Item *arg1) Create_func_des_decrypt Create_func_des_decrypt::s_singleton; Item* -Create_func_des_decrypt::create_native(THD *thd, LEX_CSTRING *name, +Create_func_des_decrypt::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4209,7 +4277,7 @@ Create_func_des_decrypt::create_native(THD *thd, LEX_CSTRING *name, Create_func_des_encrypt Create_func_des_encrypt::s_singleton; Item* -Create_func_des_encrypt::create_native(THD *thd, LEX_CSTRING *name, +Create_func_des_encrypt::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4288,7 +4356,7 @@ Create_func_distance::create_2_arg(THD *thd, Item *arg1, Item *arg2) Create_func_elt Create_func_elt::s_singleton; Item* -Create_func_elt::create_native(THD *thd, LEX_CSTRING *name, +Create_func_elt::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -4318,7 +4386,7 @@ Create_func_encode::create_2_arg(THD *thd, Item *arg1, Item *arg2) Create_func_encrypt Create_func_encrypt::s_singleton; Item* -Create_func_encrypt::create_native(THD *thd, LEX_CSTRING *name, +Create_func_encrypt::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4419,7 +4487,7 @@ Create_func_exp::create_1_arg(THD *thd, Item *arg1) Create_func_export_set Create_func_export_set::s_singleton; Item* -Create_func_export_set::create_native(THD *thd, LEX_CSTRING *name, +Create_func_export_set::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4484,7 +4552,7 @@ Create_func_exteriorring::create_1_arg(THD *thd, Item *arg1) Create_func_field Create_func_field::s_singleton; Item* -Create_func_field::create_native(THD *thd, LEX_CSTRING *name, +Create_func_field::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -4523,7 +4591,7 @@ Create_func_floor::create_1_arg(THD *thd, Item *arg1) Create_func_format Create_func_format::s_singleton; Item* -Create_func_format::create_native(THD *thd, LEX_CSTRING *name, +Create_func_format::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4588,7 +4656,7 @@ Create_func_from_days::create_1_arg(THD *thd, Item *arg1) Create_func_from_unixtime Create_func_from_unixtime::s_singleton; Item* -Create_func_from_unixtime::create_native(THD *thd, LEX_CSTRING *name, +Create_func_from_unixtime::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4627,7 +4695,7 @@ Create_func_from_unixtime::create_native(THD *thd, LEX_CSTRING *name, Create_func_geometry_from_text Create_func_geometry_from_text::s_singleton; Item* -Create_func_geometry_from_text::create_native(THD *thd, LEX_CSTRING *name, +Create_func_geometry_from_text::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4667,7 +4735,7 @@ Create_func_geometry_from_text::create_native(THD *thd, LEX_CSTRING *name, Create_func_geometry_from_wkb Create_func_geometry_from_wkb::s_singleton; Item* -Create_func_geometry_from_wkb::create_native(THD *thd, LEX_CSTRING *name, +Create_func_geometry_from_wkb::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -4707,8 +4775,8 @@ Create_func_geometry_from_wkb::create_native(THD *thd, LEX_CSTRING *name, Create_func_geometry_from_json Create_func_geometry_from_json::s_singleton; Item* -Create_func_geometry_from_json::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_geometry_from_json::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -4754,8 +4822,8 @@ Create_func_geometry_from_json::create_native(THD *thd, LEX_CSTRING *name, Create_func_as_geojson Create_func_as_geojson::s_singleton; Item* -Create_func_as_geojson::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_as_geojson::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -4856,7 +4924,7 @@ Create_func_glength::create_1_arg(THD *thd, Item *arg1) Create_func_distance_sphere Create_func_distance_sphere::s_singleton; Item* -Create_func_distance_sphere::create_native(THD *thd, LEX_CSTRING *name, +Create_func_distance_sphere::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -4877,7 +4945,7 @@ Create_func_distance_sphere::create_native(THD *thd, LEX_CSTRING *name, Create_func_greatest Create_func_greatest::s_singleton; Item* -Create_func_greatest::create_native(THD *thd, LEX_CSTRING *name, +Create_func_greatest::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -5170,8 +5238,8 @@ Create_func_json_exists::create_2_arg(THD *thd, Item *arg1, Item *arg2) Create_func_json_detailed Create_func_json_detailed::s_singleton; Item* -Create_func_json_detailed::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_json_detailed::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -5297,7 +5365,7 @@ Create_func_last_day::create_1_arg(THD *thd, Item *arg1) Create_func_json_array Create_func_json_array::s_singleton; Item* -Create_func_json_array::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_array::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func; @@ -5319,8 +5387,8 @@ Create_func_json_array::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_array_append Create_func_json_array_append::s_singleton; Item* -Create_func_json_array_append::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_json_array_append::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -5345,8 +5413,8 @@ Create_func_json_array_append::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_array_insert Create_func_json_array_insert::s_singleton; Item* -Create_func_json_array_insert::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_json_array_insert::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -5371,8 +5439,8 @@ Create_func_json_array_insert::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_insert Create_func_json_insert::s_singleton; Item* -Create_func_json_insert::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_json_insert::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -5398,7 +5466,7 @@ Create_func_json_insert::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_set Create_func_json_set::s_singleton; Item* -Create_func_json_set::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_set::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5425,7 +5493,7 @@ Create_func_json_set::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_replace Create_func_json_replace::s_singleton; Item* -Create_func_json_replace::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_replace::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5452,7 +5520,7 @@ Create_func_json_replace::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_remove Create_func_json_remove::s_singleton; Item* -Create_func_json_remove::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_remove::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5478,7 +5546,7 @@ Create_func_json_remove::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_object Create_func_json_object::s_singleton; Item* -Create_func_json_object::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_object::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func; @@ -5511,7 +5579,7 @@ Create_func_json_object::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_length Create_func_json_length::s_singleton; Item* -Create_func_json_length::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_length::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func; @@ -5536,7 +5604,7 @@ Create_func_json_length::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_merge Create_func_json_merge::s_singleton; Item* -Create_func_json_merge::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_merge::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func; @@ -5561,8 +5629,8 @@ Create_func_json_merge::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_merge_patch Create_func_json_merge_patch::s_singleton; Item* -Create_func_json_merge_patch::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_json_merge_patch::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func; int arg_count; @@ -5585,7 +5653,7 @@ Create_func_json_merge_patch::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_contains Create_func_json_contains::s_singleton; Item* -Create_func_json_contains::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_contains::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5611,7 +5679,7 @@ Create_func_json_contains::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_keys Create_func_json_keys::s_singleton; Item* -Create_func_json_keys::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_keys::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5637,8 +5705,8 @@ Create_func_json_keys::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_contains_path Create_func_json_contains_path::s_singleton; Item* -Create_func_json_contains_path::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_json_contains_path::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -5663,8 +5731,8 @@ Create_func_json_contains_path::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_extract Create_func_json_extract::s_singleton; Item* -Create_func_json_extract::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_json_extract::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= 0; @@ -5689,7 +5757,7 @@ Create_func_json_extract::create_native(THD *thd, LEX_CSTRING *name, Create_func_json_search Create_func_json_search::s_singleton; Item* -Create_func_json_search::create_native(THD *thd, LEX_CSTRING *name, +Create_func_json_search::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5715,7 +5783,7 @@ Create_func_json_search::create_native(THD *thd, LEX_CSTRING *name, Create_func_last_insert_id Create_func_last_insert_id::s_singleton; Item* -Create_func_last_insert_id::create_native(THD *thd, LEX_CSTRING *name, +Create_func_last_insert_id::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5761,7 +5829,7 @@ Create_func_lcase::create_1_arg(THD *thd, Item *arg1) Create_func_least Create_func_least::s_singleton; Item* -Create_func_least::create_native(THD *thd, LEX_CSTRING *name, +Create_func_least::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -5843,7 +5911,7 @@ Create_func_load_file::create_1_arg(THD *thd, Item *arg1) Create_func_locate Create_func_locate::s_singleton; Item* -Create_func_locate::create_native(THD *thd, LEX_CSTRING *name, +Create_func_locate::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5884,7 +5952,7 @@ Create_func_locate::create_native(THD *thd, LEX_CSTRING *name, Create_func_log Create_func_log::s_singleton; Item* -Create_func_log::create_native(THD *thd, LEX_CSTRING *name, +Create_func_log::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5941,7 +6009,7 @@ Create_func_lpad Create_func_lpad::s_singleton; Create_func_lpad_oracle Create_func_lpad_oracle::s_singleton; Item* -Create_func_lpad::create_native_std(THD *thd, LEX_CSTRING *name, +Create_func_lpad::create_native_std(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -5973,7 +6041,7 @@ Create_func_lpad::create_native_std(THD *thd, LEX_CSTRING *name, Item* -Create_func_lpad::create_native_oracle(THD *thd, LEX_CSTRING *name, +Create_func_lpad::create_native_oracle(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= item_list ? item_list->elements : 0; @@ -6039,7 +6107,7 @@ Create_func_maketime::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) Create_func_make_set Create_func_make_set::s_singleton; Item* -Create_func_make_set::create_native(THD *thd, LEX_CSTRING *name, +Create_func_make_set::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= 0; @@ -6060,7 +6128,7 @@ Create_func_make_set::create_native(THD *thd, LEX_CSTRING *name, Create_func_master_pos_wait Create_func_master_pos_wait::s_singleton; Item* -Create_func_master_pos_wait::create_native(THD *thd, LEX_CSTRING *name, +Create_func_master_pos_wait::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { @@ -6111,7 +6179,7 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_CSTRING *name, Create_func_master_gtid_wait Create_func_master_gtid_wait::s_singleton; Item* -Create_func_master_gtid_wait::create_native(THD *thd, LEX_CSTRING *name, +Create_func_master_gtid_wait::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -6357,7 +6425,7 @@ Create_func_radians::create_1_arg(THD *thd, Item *arg1) Create_func_rand Create_func_rand::s_singleton; Item* -Create_func_rand::create_native(THD *thd, LEX_CSTRING *name, +Create_func_rand::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -6437,7 +6505,7 @@ Create_func_reverse::create_1_arg(THD *thd, Item *arg1) Create_func_round Create_func_round::s_singleton; Item* -Create_func_round::create_native(THD *thd, LEX_CSTRING *name, +Create_func_round::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -6477,7 +6545,7 @@ Create_func_rpad Create_func_rpad::s_singleton; Create_func_rpad_oracle Create_func_rpad_oracle::s_singleton; Item* -Create_func_rpad::create_native_std(THD *thd, LEX_CSTRING *name, +Create_func_rpad::create_native_std(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -6509,7 +6577,7 @@ Create_func_rpad::create_native_std(THD *thd, LEX_CSTRING *name, Item* -Create_func_rpad::create_native_oracle(THD *thd, LEX_CSTRING *name, +Create_func_rpad::create_native_oracle(THD *thd, const LEX_CSTRING *name, List *item_list) { int arg_count= item_list ? item_list->elements : 0; @@ -6690,8 +6758,8 @@ Create_func_substr_index::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *a Create_func_substr_oracle Create_func_substr_oracle::s_singleton; Item* -Create_func_substr_oracle::create_native(THD *thd, LEX_CSTRING *name, - List *item_list) +Create_func_substr_oracle::create_native(THD *thd, const LEX_CSTRING *name, + List *item_list) { Item *func= NULL; int arg_count= item_list ? item_list->elements : 0; @@ -6844,7 +6912,7 @@ Create_func_unhex::create_1_arg(THD *thd, Item *arg1) Create_func_unix_timestamp Create_func_unix_timestamp::s_singleton; Item* -Create_func_unix_timestamp::create_native(THD *thd, LEX_CSTRING *name, +Create_func_unix_timestamp::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; @@ -6999,7 +7067,7 @@ Create_func_y::create_1_arg(THD *thd, Item *arg1) Create_func_year_week Create_func_year_week::s_singleton; Item* -Create_func_year_week::create_native(THD *thd, LEX_CSTRING *name, +Create_func_year_week::create_native(THD *thd, const LEX_CSTRING *name, List *item_list) { Item *func= NULL; diff --git a/sql/item_create.h b/sql/item_create.h index 7e92016ab96..894e9777b8d 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -58,7 +58,8 @@ public: @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call, or NULL */ - virtual Item *create_func(THD *thd, LEX_CSTRING *name, List *item_list) = 0; + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, + List *item_list) = 0; protected: /** Constructor */ @@ -79,7 +80,7 @@ protected: class Create_native_func : public Create_func { public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, List *item_list); /** @@ -89,7 +90,7 @@ public: @param item_list The function parameters, none of which are named @return An item representing the function call */ - virtual Item *create_native(THD *thd, LEX_CSTRING *name, + virtual Item *create_native(THD *thd, const LEX_CSTRING *name, List *item_list) = 0; protected: @@ -117,7 +118,7 @@ public: @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call */ - virtual Item *create_func(THD *thd, LEX_CSTRING *name, + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, List *item_list); /** @@ -129,7 +130,9 @@ public: @param item_list The list of arguments to the function, can be NULL @return An item representing the parsed function call */ - virtual Item *create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name, + virtual Item *create_with_db(THD *thd, + const LEX_CSTRING *db, + const LEX_CSTRING *name, bool use_explicit_name, List *item_list) = 0; @@ -167,7 +170,7 @@ extern Create_qfunc * find_qualified_function_builder(THD *thd); class Create_udf_func : public Create_func { public: - virtual Item *create_func(THD *thd, LEX_CSTRING *name, + virtual Item *create_func(THD *thd, const LEX_CSTRING *name, List *item_list); /** -- cgit v1.2.1 From daed558b2c15bd40bd957616da2a3872e5436ce2 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Mon, 4 Apr 2022 11:28:36 +0200 Subject: MDEV-28204: The tr utility does not work as expected on rsync SST This commit contains a fix to use modern syntax for selecting character classes in the tr utility options. Also one of the tests for SST via rsync (galera_sst_rysnc2) is made more reliable (to avoid rare failures during automatic testing). --- mysql-test/suite/galera/t/galera_sst_rsync2.cnf | 4 ++-- mysql-test/suite/galera/t/galera_sst_rsync2.test | 2 ++ scripts/wsrep_sst_mariabackup.sh | 2 +- scripts/wsrep_sst_rsync.sh | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/galera/t/galera_sst_rsync2.cnf b/mysql-test/suite/galera/t/galera_sst_rsync2.cnf index 0159596f99b..a089baacf36 100644 --- a/mysql-test/suite/galera/t/galera_sst_rsync2.cnf +++ b/mysql-test/suite/galera/t/galera_sst_rsync2.cnf @@ -5,10 +5,10 @@ wsrep_sst_method=rsync [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' -log_bin=@ENV.MYSQLTEST_VARDIR/server1_binlog +log_bin=@ENV.MYSQLTEST_VARDIR/mysqld.1/server1_binlog log_bin_index=@ENV.MYSQLTEST_VARDIR/tmp/server1_binlog_index.index [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' -log_bin=@ENV.MYSQLTEST_VARDIR/server2_binlog +log_bin=@ENV.MYSQLTEST_VARDIR/mysqld.2/server2_binlog log_bin_index=@ENV.MYSQLTEST_VARDIR/tmp/server2_binlog_index.index diff --git a/mysql-test/suite/galera/t/galera_sst_rsync2.test b/mysql-test/suite/galera/t/galera_sst_rsync2.test index f796356cac7..20fae4a751e 100644 --- a/mysql-test/suite/galera/t/galera_sst_rsync2.test +++ b/mysql-test/suite/galera/t/galera_sst_rsync2.test @@ -7,6 +7,8 @@ --source suite/galera/include/galera_st_shutdown_slave.inc --source suite/galera/include/galera_st_clean_slave.inc +--let $wsrep_recover_additional=--log-bin=$MYSQLTEST_VARDIR/mysqld.2/server2_binlog --log-bin-index=$MYSQLTEST_VARDIR/tmp/server2_binlog_index.index + --source suite/galera/include/galera_st_kill_slave.inc --source suite/galera/include/galera_st_kill_slave_ddl.inc --source include/auto_increment_offset_restore.inc diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index ce4001fdc56..067a777fb9c 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -472,7 +472,7 @@ read_cnf() encrypt=$(parse_cnf "$encgroups" 'encrypt' 0) tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | \ - tr [:lower:] [:upper:]) + tr '[[:lower:]]' '[[:upper:]]') case "$tmode" in 'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED') diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 67a7afc638f..5f7ae4298b5 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -224,7 +224,7 @@ SSTCERT="$tpem" SSTCA="$tcert" SSTCAP="$tcap" -SSLMODE=$(parse_cnf "$encgroups" 'ssl-mode' | tr [:lower:] [:upper:]) +SSLMODE=$(parse_cnf "$encgroups" 'ssl-mode' | tr '[[:lower:]]' '[[:upper:]]') if [ -z "$SSLMODE" ]; then # Implicit verification if CA is set and the SSL mode -- cgit v1.2.1 From 09c7f78c2ef8c43d519eb4bad61d1be177a2c9b2 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 23 Mar 2022 19:34:40 +0200 Subject: Fixed double free issue in events Server crashed during shutdown with: "corrupted double-linked list" when running mysql_upgrade multiple times against the server. Reason was that db_repostitory could be freed twice. --- sql/events.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/events.cc b/sql/events.cc index 5e15b92dc49..7968697a8ba 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -666,6 +666,7 @@ Events::drop_schema_events(THD *thd, const char *db) { db_repository->drop_schema_events(thd, &db_lex); delete db_repository; + db_repository= 0; } } DBUG_VOID_RETURN; -- cgit v1.2.1 From c4ebb2bd04974807b3b81001fd2d733e75dfc1fb Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 23 Mar 2022 21:17:32 +0200 Subject: Fixed that mysql_upgrade doesn't give errors about mariadb.sys The reason for this fix was that when I tried to run mysql_upgrade at home to update an old 10.5 installation, mysql_upgrade failed with warnings about mariadb.sys user not existing. If the server was started with --skip-grants, there would be no warnings from mysql_upgrade, but in some cases running mysql_upgrade again could produce new warnings. The reason for the warnings was that any access of the mysql.user view will produce a warning if the mariadb.sys user does not exists. Fixed with the following changes: - Disable warnings about mariadb.sys user not existing - Don't overwrite old mariadb.sys entries in tables_priv and global_priv - Ensure that tables_priv has an entry for mariadb.sys if the user exists. This fixes an issue that tables_priv would not be updated if there was a failure directly after global_priv was updated. --- client/mysql_upgrade.c | 1 + scripts/mysql_system_tables.sql | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 0608665d6fc..6d5c954bd08 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1029,6 +1029,7 @@ static const char *expected_errors[]= "ERROR 1347", /* 'mysql.user' is not of type 'BASE TABLE' */ "ERROR 1348", /* Column 'Show_db_priv' is not updatable */ "ERROR 1356", /* definer of view lack rights (UPDATE) */ + "ERROR 1449", /* definer ('mariadb.sys'@'localhost') of mysql.user does not exist */ 0 }; diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 020385992ea..26639f613de 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -35,17 +35,15 @@ set @had_db_table= @@warning_count != 0; CREATE TABLE IF NOT EXISTS global_priv (Host char(60) binary DEFAULT '', User char(80) binary DEFAULT '', Priv JSON NOT NULL DEFAULT '{}' CHECK(JSON_VALID(Priv)), PRIMARY KEY (Host,User)) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; -set @had_sys_user= 0 <> (select count(*) from mysql.global_priv where Host="localhost" and User="mariadb.sys"); - set @exists_user_view= EXISTS (SELECT * FROM information_schema.VIEWS WHERE TABLE_CATALOG = 'def' and TABLE_SCHEMA = 'mysql' and TABLE_NAME='user'); set @exists_user_view_by_root= EXISTS (SELECT * FROM information_schema.VIEWS WHERE TABLE_CATALOG = 'def' and TABLE_SCHEMA = 'mysql' and TABLE_NAME='user' and DEFINER = 'mariadb.sys@localhost'); -set @need_sys_user_creation= (NOT @had_sys_user) AND (( NOT @exists_user_view) OR @exists_user_view_by_root); +set @need_sys_user_creation= (( NOT @exists_user_view) OR @exists_user_view_by_root); CREATE TEMPORARY TABLE tmp_user_sys LIKE global_priv; INSERT INTO tmp_user_sys (Host,User,Priv) VALUES ('localhost','mariadb.sys','{"access":0,"plugin":"mysql_native_password","authentication_string":"","account_locked":true,"password_last_changed":0}'); -INSERT INTO global_priv SELECT * FROM tmp_user_sys WHERE 0 <> @need_sys_user_creation; +INSERT IGNORE INTO global_priv SELECT * FROM tmp_user_sys WHERE 0 <> @need_sys_user_creation; DROP TABLE tmp_user_sys; @@ -117,7 +115,7 @@ CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NUL CREATE TEMPORARY TABLE tmp_user_sys LIKE tables_priv; INSERT INTO tmp_user_sys (Host,Db,User,Table_name,Grantor,Timestamp,Table_priv) VALUES ('localhost','mysql','mariadb.sys','global_priv','root@localhost','0','Select,Delete'); -INSERT INTO tables_priv SELECT * FROM tmp_user_sys WHERE 0 <> @need_sys_user_creation; +INSERT IGNORE INTO tables_priv SELECT * FROM tmp_user_sys WHERE 0 <> @need_sys_user_creation; DROP TABLE tmp_user_sys; CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; -- cgit v1.2.1 From d7fd76456e7c7e52b28ee963ba074df73e619df6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 5 Apr 2022 13:09:21 +0200 Subject: MDEV-19525 fix the test for embedded followup for 58cd2a8dedd7 --- mysql-test/suite/versioning/t/debug.test | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/versioning/t/debug.test b/mysql-test/suite/versioning/t/debug.test index 59dde0d26fb..ed1b842dab3 100644 --- a/mysql-test/suite/versioning/t/debug.test +++ b/mysql-test/suite/versioning/t/debug.test @@ -1,5 +1,7 @@ --source include/have_debug.inc +--let $datadir=`select @@datadir` + create table t1 (a int); show create table t1; @@ -38,9 +40,10 @@ drop table t1, t2, t3, t4; --echo # create table t1 (x int) with system versioning; set debug_dbug='+d,error_vers_wrong_type'; ---replace_result $MYSQLTEST_VARDIR . master-data// '' '\\' '/' +--replace_result $datadir ./ --error ER_NOT_FORM_FILE show create table t1; +--replace_result $datadir ./ show warnings; drop table t1; set global debug_dbug=@old_dbug; -- cgit v1.2.1 From cf8d30efd221f58a80261d04642da34635a17595 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 Apr 2022 21:39:34 +0200 Subject: Revert "MDEV-28131 Unexpected warning while selecting from information_schema.processlist" This reverts commit 0812d0de8dcb1f76d4a03cea3f20bfa30345b83b. But keeps the test case. --- sql/sql_show.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 439cad1c858..e1090d450e8 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3351,16 +3351,6 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[11]->store((double) tmp->progress.counter / (double) max_counter*100.0); } - else - { - /* - This is a DECIMAL column without DEFAULT. - restore_record() fills its Field::ptr to zero bytes, - according to pack_length(). But an array of zero bytes - is not a valid decimal. Set it explicitly to 0. - */ - table->field[11]->store((longlong) 0, true); - } mysql_mutex_unlock(&tmp->LOCK_thd_data); } -- cgit v1.2.1 From 2d2c3da8ec846d8018c112d8901e2ae029f1c795 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 4 Apr 2022 21:34:05 +0200 Subject: MDEV-27673 Warning after "select progress from information_schema.processlist" after moving fields in optimize_schema_tables_memory_usage() store default values into their new, moved, locations. --- mysql-test/main/information_schema.result | 6 ++++++ mysql-test/main/information_schema.test | 5 ++++- sql/sql_show.cc | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index 8b7ab230ae6..cf452af216e 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -2370,5 +2370,11 @@ DROP TABLE t1; DROP TABLE t1; SET SQL_MODE=DEFAULT; # +# MDEV-27673 Warning after "select progress from information_schema.processlist" +# +select progress from information_schema.processlist limit 1; +progress +0.000 +# # End of 10.3 tests # diff --git a/mysql-test/main/information_schema.test b/mysql-test/main/information_schema.test index fb575c1ef24..2fac02d2fe0 100644 --- a/mysql-test/main/information_schema.test +++ b/mysql-test/main/information_schema.test @@ -2104,7 +2104,10 @@ DROP TABLE t1; DROP TABLE t1; SET SQL_MODE=DEFAULT; - +--echo # +--echo # MDEV-27673 Warning after "select progress from information_schema.processlist" +--echo # +select progress from information_schema.processlist limit 1; --echo # --echo # End of 10.3 tests diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e1090d450e8..2a3dbceb4cb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8803,6 +8803,7 @@ bool optimize_schema_tables_memory_usage(List &tables) if (bitmap_is_set(table->read_set, i)) { field->move_field(cur); + field->reset(); *to_recinfo++= *from_recinfo; cur+= from_recinfo->length; } @@ -8823,6 +8824,7 @@ bool optimize_schema_tables_memory_usage(List &tables) table->s->reclength= to_recinfo->length= 1; to_recinfo++; } + store_record(table, s->default_values); p->recinfo= to_recinfo; // TODO switch from Aria to Memory if all blobs were optimized away? -- cgit v1.2.1 From f6b09a7ce58f564d8e5c08c799d2fc45cfc10870 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Tue, 5 Apr 2022 20:20:09 +0700 Subject: MDEV-21173: Assertion `m_thd == __null' failed in sp_head::~sp_head Some SQL statements that involves subqueries or stored routines could fail since execution of subqueries or stored routines is not supported for theses statements. Unfortunately, parsing error could result in abnormal termination by firing the following assert DBUG_ASSERT(m_thd == NULL); in a destructor of the class sp_head. The reason of the assert firing is that the method sp_head::restore_thd_mem_root() is not called on semantic action code to clean up resources allocated during parsing. This happens since the macros YYABORT is called instead of MYSQL_YYABORT by semantic action code for some grammar rules. So, to fix the bug YYABORT was just replaced with MYSQL_YYABORT. --- mysql-test/main/ps.result | 13 +++++++++++++ mysql-test/main/ps.test | 19 +++++++++++++++++++ mysql-test/main/sp.result | 6 ++++++ mysql-test/main/sp.test | 9 ++++++++- sql/sql_yacc.yy | 6 +++--- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 6df83228875..5d72cde5dd2 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -5650,5 +5650,18 @@ connection default; SET GLOBAL disconnect_on_expired_password=@disconnect_on_expired_password_save; DROP USER user1@localhost; # +# MDEV-21173: Assertion `m_thd == __null' failed in sp_head::~sp_head +# +CREATE TABLE t1 (a INT); +EXECUTE IMMEDIATE "CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1));"; +ERROR 42000: PROCEDURE does not support subqueries or stored functions +DROP TABLE t1; +BEGIN NOT ATOMIC +PREPARE stmt FROM 'SELECT ?'; +EXECUTE stmt USING ((SELECT 1)); +END; +$ +ERROR 42000: EXECUTE..USING does not support subqueries or stored functions +# # End of 10.4 tests # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index 9b781f32631..c99731e768d 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -5082,6 +5082,25 @@ connection default; SET GLOBAL disconnect_on_expired_password=@disconnect_on_expired_password_save; DROP USER user1@localhost; +--echo # +--echo # MDEV-21173: Assertion `m_thd == __null' failed in sp_head::~sp_head +--echo # +CREATE TABLE t1 (a INT); + +--error ER_SUBQUERIES_NOT_SUPPORTED +EXECUTE IMMEDIATE "CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1));"; +DROP TABLE t1; + +delimiter $; +--error ER_SUBQUERIES_NOT_SUPPORTED +BEGIN NOT ATOMIC + PREPARE stmt FROM 'SELECT ?'; + EXECUTE stmt USING ((SELECT 1)); +END; +$ + +delimiter ;$ + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 7dfaa6176a3..3795e4db894 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8916,5 +8916,11 @@ END; $$ ERROR 42000: Incorrect usage/placement of 'HIGH_PRIORITY' # +# MDEV-21173: Assertion `m_thd == __null' failed in sp_head::~sp_head +# +CREATE TABLE t1 (a INT); +CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1)); +ERROR 42000: PROCEDURE does not support subqueries or stored functions +DROP TABLE t1; # End of 10.4 tests # diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index bd614072e1a..4fa5085128a 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10481,7 +10481,14 @@ END; $$ DELIMITER ;$$ - --echo # +--echo # MDEV-21173: Assertion `m_thd == __null' failed in sp_head::~sp_head +--echo # +CREATE TABLE t1 (a INT); +--error ER_SUBQUERIES_NOT_SUPPORTED +CREATE PROCEDURE p1() SELECT 1 FROM t1 PROCEDURE ANALYSE( 10, (SELECT a FROM t1)); + +DROP TABLE t1; + --echo # End of 10.4 tests --echo # diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3bda2381230..7d8b02a0f12 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9610,7 +9610,7 @@ subselect: query_expression { if (!($$= Lex->parsed_subselect($1))) - YYABORT; + MYSQL_YYABORT; } ; @@ -9655,14 +9655,14 @@ subquery: else $1->fake_select_lex->braces= false; if (!($$= Lex->parsed_subselect($1))) - YYABORT; + MYSQL_YYABORT; } | '(' with_clause query_expression_no_with_clause ')' { $3->set_with_clause($2); $2->attach_to($3->first_select()); if (!($$= Lex->parsed_subselect($3))) - YYABORT; + MYSQL_YYABORT; } ; -- cgit v1.2.1 From e9735a81859f172b73f75eccc043540a58d91cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 6 Apr 2022 08:06:49 +0300 Subject: MDEV-25975 innodb_disallow_writes causes shutdown to hang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will remove the parameter innodb_disallow_writes because it is badly designed and implemented. The parameter was never allowed at startup. It was only internally used by Galera snapshot transfer. If a user executed SET GLOBAL innodb_disallow_writes=ON; the server could hang even on subsequent read operations. During Galera snapshot transfer, we will block writes to implement an rsync friendly snapshot, as follows: sst_flush_tables() will acquire a global lock by executing FLUSH TABLES WITH READ LOCK, which will block any writes at the high level. sst_disable_innodb_writes(), invoked via ha_disable_internal_writes(true), will suspend or disable InnoDB background tasks or threads that could initiate writes. As part of this, log_make_checkpoint() will be invoked to ensure that anything in the InnoDB buf_pool.flush_list will be written to the data files. This has the nice side effect that the Galera joiner will avoid crash recovery. The changes to sql/wsrep.cc and to the tests are based on a prototype that was developed by Jan Lindström. Reviewed by: Jan Lindström --- extra/mariabackup/xtrabackup.cc | 12 --- mysql-test/include/have_innodb_disallow_writes.inc | 6 -- .../suite/galera/r/galera_bf_abort_shutdown.result | 11 +++ .../suite/galera/r/galera_drop_database.result | 3 + mysql-test/suite/galera/r/galera_events2.result | 1 + .../r/galera_restart_on_unknown_option.result | 1 + .../r/galera_var_innodb_disallow_writes.result | 28 ------- .../suite/galera/t/galera_bf_abort_shutdown.test | 34 ++++++++ .../suite/galera/t/galera_drop_database.test | 1 + mysql-test/suite/galera/t/galera_events2.test | 2 + .../galera/t/galera_restart_on_unknown_option.test | 1 + .../t/galera_var_innodb_disallow_writes.test | 71 ---------------- .../sys_vars/r/innodb_disallow_writes_basic.result | 45 ---------- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 2 - .../sys_vars/t/innodb_disallow_writes_basic.test | 42 ---------- mysql-test/suite/sys_vars/t/sysvars_innodb.test | 2 - scripts/wsrep_sst_rsync.sh | 14 +++- sql/handler.cc | 16 ++++ sql/handler.h | 5 ++ sql/wsrep_sst.cc | 92 +++++++-------------- storage/innobase/dict/dict0stats_bg.cc | 12 ++- storage/innobase/fts/fts0opt.cc | 30 ++++++- storage/innobase/handler/ha_innodb.cc | 96 ++++++++++++---------- storage/innobase/include/srv0srv.h | 7 +- storage/innobase/innodb.cmake | 8 +- storage/innobase/log/log0log.cc | 20 +++-- storage/innobase/os/os0file.cc | 29 +------ storage/innobase/row/row0merge.cc | 2 +- storage/innobase/srv/srv0srv.cc | 28 +------ storage/innobase/srv/srv0start.cc | 6 +- 30 files changed, 229 insertions(+), 398 deletions(-) delete mode 100644 mysql-test/include/have_innodb_disallow_writes.inc create mode 100644 mysql-test/suite/galera/r/galera_bf_abort_shutdown.result delete mode 100644 mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result create mode 100644 mysql-test/suite/galera/t/galera_bf_abort_shutdown.test delete mode 100644 mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test delete mode 100644 mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result delete mode 100644 mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 70542a35514..41461d6ece1 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4372,11 +4372,6 @@ fail: crc_init(); recv_sys_init(); -#ifdef WITH_INNODB_DISALLOW_WRITES - srv_allow_writes_event = os_event_create(0); - os_event_set(srv_allow_writes_event); -#endif - xb_filters_init(); xb_fil_io_init(); @@ -5837,10 +5832,6 @@ static bool xtrabackup_prepare_func(char** argv) log_sys.create(); recv_recovery_on = true; -#ifdef WITH_INNODB_DISALLOW_WRITES - srv_allow_writes_event = os_event_create(0); - os_event_set(srv_allow_writes_event); -#endif dberr_t err = xb_data_files_init(); if (err != DB_SUCCESS) { msg("mariabackup: error: xb_data_files_init() failed " @@ -5862,9 +5853,6 @@ static bool xtrabackup_prepare_func(char** argv) xb_filter_hash_free(inc_dir_tables_hash); fil_system.close(); -#ifdef WITH_INNODB_DISALLOW_WRITES - os_event_destroy(srv_allow_writes_event); -#endif innodb_free_param(); log_sys.close(); sync_check_close(); diff --git a/mysql-test/include/have_innodb_disallow_writes.inc b/mysql-test/include/have_innodb_disallow_writes.inc deleted file mode 100644 index 83b516b7a34..00000000000 --- a/mysql-test/include/have_innodb_disallow_writes.inc +++ /dev/null @@ -1,6 +0,0 @@ ---source include/have_innodb.inc - -if (`SELECT COUNT(*) = 0 from INFORMATION_SCHEMA.GLOBAL_VARIABLES - WHERE VARIABLE_NAME = 'INNODB_DISALLOW_WRITES'`) { - --skip Test requires 'innodb_disallow_writes' -} diff --git a/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result new file mode 100644 index 00000000000..bf77fd7eae7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result @@ -0,0 +1,11 @@ +connection node_1; +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INT PRIMARY KEY); +connection node_2; +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:.*"); +SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue'; +INSERT INTO t1 VALUES (1); +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_drop_database.result b/mysql-test/suite/galera/r/galera_drop_database.result index 914cdffceed..794e934206f 100644 --- a/mysql-test/suite/galera/r/galera_drop_database.result +++ b/mysql-test/suite/galera/r/galera_drop_database.result @@ -46,3 +46,6 @@ SHOW TABLES; Tables_in_fts DROP DATABASE fts; connection node_2; +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:"); +Warnings: +Note 1049 Unknown database 'fts' diff --git a/mysql-test/suite/galera/r/galera_events2.result b/mysql-test/suite/galera/r/galera_events2.result index 36441e15f7d..8fb98e03fab 100644 --- a/mysql-test/suite/galera/r/galera_events2.result +++ b/mysql-test/suite/galera/r/galera_events2.result @@ -109,6 +109,7 @@ f1 f2 SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT def test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND SLAVESIDE_DISABLED NOT PRESERVE +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:.*"); connection node_1; SELECT * FROM t1; f1 f2 diff --git a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result index ba6f30fcf30..e748859beb7 100644 --- a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result +++ b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result @@ -39,6 +39,7 @@ f1 f2 connection node_2; Starting server ... Starting server ... +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:"); SELECT * FROM t1; f1 f2 1 a diff --git a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result deleted file mode 100644 index 8750651612d..00000000000 --- a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result +++ /dev/null @@ -1,28 +0,0 @@ -connection node_1a; -SET SESSION wsrep_sync_wait = 0; -connection node_1; -CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB; -CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); -SET GLOBAL innodb_disallow_writes=ON; -INSERT INTO t1 (f2) SELECT 'abcde ' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; -connection node_2; -INSERT INTO t1 (f2) SELECT 'fghij ' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 -connection node_1a; -SET GLOBAL innodb_disallow_writes=OFF; -connection node_1; -SELECT COUNT(*) AS EXPECT_20000 FROM t1; -EXPECT_20000 -20000 -connection node_2; -SELECT COUNT(*) AS EXPECT_20000 FROM t1; -EXPECT_20000 -20000 -connection node_1; -connection node_2; -DROP TABLE t1; -DROP TABLE ten; -disconnect node_1a; diff --git a/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test new file mode 100644 index 00000000000..42f85ecf7c2 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test @@ -0,0 +1,34 @@ +# +# This test verifies that the server can be shut down even if +# some of the wsrep transactions are in QUERY_COMMITTING state. +# In this case the shutdown sequence may do a BF abort for the +# connection. +# + +--source include/have_innodb.inc +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--connection node_1 +CREATE TABLE t1 (f1 INT PRIMARY KEY); + +--connection node_2 +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:.*"); +SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue'; +--send INSERT INTO t1 VALUES (1) + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--source include/restart_mysqld.inc + +# Restore original auto_increment_offset values. +--let $node_2=node_2a +--source include/auto_increment_offset_restore.inc + +--connection node_1 + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_drop_database.test b/mysql-test/suite/galera/t/galera_drop_database.test index 8dc73c1ce38..c1a66e1f66c 100644 --- a/mysql-test/suite/galera/t/galera_drop_database.test +++ b/mysql-test/suite/galera/t/galera_drop_database.test @@ -56,6 +56,7 @@ SHOW TABLES; DROP DATABASE fts; --connection node_2 +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:"); --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'fts_t1'; --source include/wait_condition.inc --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'fts_t2'; diff --git a/mysql-test/suite/galera/t/galera_events2.test b/mysql-test/suite/galera/t/galera_events2.test index 3dfbe406fc4..b29ad3ba2f2 100644 --- a/mysql-test/suite/galera/t/galera_events2.test +++ b/mysql-test/suite/galera/t/galera_events2.test @@ -137,6 +137,8 @@ SELECT * FROM t1; --echo # node_2 Event should be SERVERSIDE_DISABLED SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:.*"); + --connection node_1 SELECT * FROM t1; --echo # node_1 Event should be ENABLED diff --git a/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test b/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test index ed7f106c123..6a0f24dbaae 100644 --- a/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test +++ b/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test @@ -125,6 +125,7 @@ SELECT * FROM t1; # Sanity check (node 2 is running now and can perform SQL operators): +call mtr.add_suppression("WSREP: Failed to scan the last segment to the end. Last events may be missing. Last recovered event:"); SELECT * FROM t1; --connection node_1 diff --git a/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test b/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test deleted file mode 100644 index 0d2a6effd92..00000000000 --- a/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test +++ /dev/null @@ -1,71 +0,0 @@ -# -# This test checks that innodb_disallow_writes works as expected -# -# Note that we need to enable binlog for this test: If the commit -# to InnoDB is done in one phase, the transaction is committed in -# memory before it is persisted to disk. This means that the -# innodb_disallow_writes=ON may not prevent transaction to -# become visible to other readers. On the other hand, if the -# commit is two phase (as it is with binlog), the transaction -# will be blocked in prepare phase. -# - ---source include/galera_cluster.inc ---source include/have_innodb.inc - ---let $datadir= `SELECT @@datadir` - - -# Open a separate connection to be used to run SHOW PROCESSLIST ---let $galera_connection_name = node_1a ---let $galera_server_number = 1 ---source include/galera_connect.inc ---connection node_1a -SET SESSION wsrep_sync_wait = 0; - ---connection node_1 -CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB; -CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); - -SET GLOBAL innodb_disallow_writes=ON; ---exec find $datadir -type f-exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_before - -# -# This insert has no effect before innodb_disallow_writes is OFF -# ---send INSERT INTO t1 (f2) SELECT 'abcde ' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; - ---connection node_2 -INSERT INTO t1 (f2) SELECT 'fghij ' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; - ---connection node_1a ---sleep 5 - ---exec find $datadir -type f-exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_after - -SET GLOBAL innodb_disallow_writes=OFF; - ---connection node_1 ---reap ---let $wait_condition = SELECT COUNT(*) = 20000 FROM t1; ---source include/wait_condition.inc - -SELECT COUNT(*) AS EXPECT_20000 FROM t1; - ---connection node_2 ---let $wait_condition = SELECT COUNT(*) = 20000 FROM t1; ---source include/wait_condition.inc -SELECT COUNT(*) AS EXPECT_20000 FROM t1; - ---connection node_1 ---diff_files $MYSQLTEST_VARDIR/tmp/innodb_before $MYSQLTEST_VARDIR/tmp/innodb_after - ---connection node_2 - -DROP TABLE t1; -DROP TABLE ten; - ---disconnect node_1a - diff --git a/mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result b/mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result deleted file mode 100644 index bfb6b67b5d8..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_disallow_writes_basic.result +++ /dev/null @@ -1,45 +0,0 @@ -# -# innodb_disallow_writes -# -# save the initial value -SET @innodb_disallow_writes_global_saved = @@global.innodb_disallow_writes; -# default -SELECT @@global.innodb_disallow_writes; -@@global.innodb_disallow_writes -0 - -# scope -SELECT @@session.innodb_disallow_writes; -ERROR HY000: Variable 'innodb_disallow_writes' is a GLOBAL variable -SET @@global.innodb_disallow_writes=OFF; -SELECT @@global.innodb_disallow_writes; -@@global.innodb_disallow_writes -0 -SET @@global.innodb_disallow_writes=ON; -SELECT @@global.innodb_disallow_writes; -@@global.innodb_disallow_writes -1 - -# valid values -SET @@global.innodb_disallow_writes='OFF'; -SELECT @@global.innodb_disallow_writes; -@@global.innodb_disallow_writes -0 -SET @@global.innodb_disallow_writes=ON; -SELECT @@global.innodb_disallow_writes; -@@global.innodb_disallow_writes -1 -SET @@global.innodb_disallow_writes=default; -SELECT @@global.innodb_disallow_writes; -@@global.innodb_disallow_writes -0 - -# invalid values -SET @@global.innodb_disallow_writes=NULL; -ERROR 42000: Variable 'innodb_disallow_writes' can't be set to the value of 'NULL' -SET @@global.innodb_disallow_writes='junk'; -ERROR 42000: Variable 'innodb_disallow_writes' can't be set to the value of 'junk' - -# restore the initial value -SET @@global.innodb_disallow_writes = @innodb_disallow_writes_global_saved; -# End of test diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index ff6c6d310cf..f47c7de8132 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2,9 +2,7 @@ select VARIABLE_NAME, SESSION_VALUE, DEFAULT_VALUE, VARIABLE_SCOPE, VARIABLE_TYP where variable_name like 'innodb%' and variable_name not in ( 'innodb_version', # always the same as the server version -'innodb_disallow_writes', # only available WITH_WSREP 'innodb_numa_interleave', # only available WITH_NUMA -'innodb_sched_priority_cleaner', # linux only 'innodb_evict_tables_on_commit_debug', # one may want to override this 'innodb_use_native_aio', # default value depends on OS 'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing diff --git a/mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test b/mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test deleted file mode 100644 index b8e5c127377..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_disallow_writes_basic.test +++ /dev/null @@ -1,42 +0,0 @@ ---source include/have_innodb_disallow_writes.inc - ---echo # ---echo # innodb_disallow_writes ---echo # - ---echo # save the initial value -SET @innodb_disallow_writes_global_saved = @@global.innodb_disallow_writes; - ---echo # default -SELECT @@global.innodb_disallow_writes; - ---echo ---echo # scope ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -SELECT @@session.innodb_disallow_writes; -SET @@global.innodb_disallow_writes=OFF; -SELECT @@global.innodb_disallow_writes; -SET @@global.innodb_disallow_writes=ON; -SELECT @@global.innodb_disallow_writes; - ---echo ---echo # valid values -SET @@global.innodb_disallow_writes='OFF'; -SELECT @@global.innodb_disallow_writes; -SET @@global.innodb_disallow_writes=ON; -SELECT @@global.innodb_disallow_writes; -SET @@global.innodb_disallow_writes=default; -SELECT @@global.innodb_disallow_writes; - ---echo ---echo # invalid values ---error ER_WRONG_VALUE_FOR_VAR -SET @@global.innodb_disallow_writes=NULL; ---error ER_WRONG_VALUE_FOR_VAR -SET @@global.innodb_disallow_writes='junk'; - ---echo ---echo # restore the initial value -SET @@global.innodb_disallow_writes = @innodb_disallow_writes_global_saved; - ---echo # End of test diff --git a/mysql-test/suite/sys_vars/t/sysvars_innodb.test b/mysql-test/suite/sys_vars/t/sysvars_innodb.test index ef52ee3264a..15fd99e9984 100644 --- a/mysql-test/suite/sys_vars/t/sysvars_innodb.test +++ b/mysql-test/suite/sys_vars/t/sysvars_innodb.test @@ -9,9 +9,7 @@ select VARIABLE_NAME, SESSION_VALUE, DEFAULT_VALUE, VARIABLE_SCOPE, VARIABLE_TYP where variable_name like 'innodb%' and variable_name not in ( 'innodb_version', # always the same as the server version - 'innodb_disallow_writes', # only available WITH_WSREP 'innodb_numa_interleave', # only available WITH_NUMA - 'innodb_sched_priority_cleaner', # linux only 'innodb_evict_tables_on_commit_debug', # one may want to override this 'innodb_use_native_aio', # default value depends on OS 'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 5f7ae4298b5..29e2b390e27 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -3,7 +3,7 @@ set -ue # Copyright (C) 2017-2022 MariaDB -# Copyright (C) 2010-2014 Codership Oy +# Copyright (C) 2010-2022 Codership Oy # # 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 @@ -416,6 +416,8 @@ EOF sync + wsrep_log_info "Tables flushed" + if [ -n "$WSREP_SST_OPT_BINLOG" ]; then # Change the directory to binlog base (if possible): cd "$DATA" @@ -557,6 +559,8 @@ FILTER="-f '- /lost+found' exit $RC fi + wsrep_log_info "Transfer of normal directories done" + # Transfer InnoDB data files rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials \ @@ -570,6 +574,8 @@ FILTER="-f '- /lost+found' exit 255 # unknown error fi + wsrep_log_info "Transfer of InnoDB data files done" + # second, we transfer InnoDB and Aria log files rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials \ @@ -583,6 +589,8 @@ FILTER="-f '- /lost+found' exit 255 # unknown error fi + wsrep_log_info "Transfer of InnoDB and Aria log files done" + # then, we parallelize the transfer of database directories, # use '.' so that path concatenation works: @@ -610,6 +618,9 @@ FILTER="-f '- /lost+found' exit 255 # unknown error fi + wsrep_log_info "Transfer of data done" + + else # BYPASS wsrep_log_info "Bypassing state dump." @@ -620,6 +631,7 @@ FILTER="-f '- /lost+found' fi + wsrep_log_info "Sending continue to donor" echo 'continue' # now server can resume updating data echo "$STATE" > "$MAGIC_FILE" diff --git a/sql/handler.cc b/sql/handler.cc index cad9019c969..e4c377451c6 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -849,6 +849,22 @@ void ha_kill_query(THD* thd, enum thd_kill_levels level) } +static my_bool plugin_disable_internal_writes(THD *, plugin_ref plugin, + void *disable) +{ + if (void(*diw)(bool)= plugin_hton(plugin)->disable_internal_writes) + diw(*static_cast(disable)); + return FALSE; +} + + +void ha_disable_internal_writes(bool disable) +{ + plugin_foreach(NULL, plugin_disable_internal_writes, + MYSQL_STORAGE_ENGINE_PLUGIN, &disable); +} + + /* ======================================================================== ======================= TRANSACTIONS ===================================*/ diff --git a/sql/handler.h b/sql/handler.h index a39de4b7180..1c971b2f831 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1537,6 +1537,9 @@ struct handlerton @return transaction commit ID @retval 0 if no system-versioned data was affected by the transaction */ ulonglong (*prepare_commit_versioned)(THD *thd, ulonglong *trx_id); + + /** Disable or enable the internal writes of a storage engine */ + void (*disable_internal_writes)(bool disable); }; @@ -4713,6 +4716,8 @@ int ha_create_table(THD *thd, const char *path, int ha_delete_table(THD *thd, handlerton *db_type, const char *path, const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning); +void ha_disable_internal_writes(bool disable); + /* statistics and info */ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 0549d3e1c1d..db31b019a59 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1,4 +1,5 @@ /* Copyright 2008-2022 Codership Oy + Copyright (c) 2008, 2022, MariaDB 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 @@ -1403,47 +1404,18 @@ static int run_sql_command(THD *thd, const char *query) } mysql_parse(thd, thd->query(), thd->query_length(), &ps, FALSE, FALSE); + if (thd->is_error()) { int const err= thd->get_stmt_da()->sql_errno(); - WSREP_WARN ("Error executing '%s': %d (%s)%s", - query, err, thd->get_stmt_da()->message(), - err == ER_UNKNOWN_SYSTEM_VARIABLE ? - ". Was mysqld built with --with-innodb-disallow-writes ?" : ""); + WSREP_WARN ("Error executing '%s': %d (%s)", + query, err, thd->get_stmt_da()->message()); thd->clear_error(); return -1; } return 0; } -static void sst_disallow_writes (THD* thd, bool yes) -{ - char query_str[64]= { 0, }; - ssize_t const query_max= sizeof(query_str) - 1; - CHARSET_INFO *current_charset; - - current_charset= thd->variables.character_set_client; - - if (!is_supported_parser_charset(current_charset)) - { - /* Do not use non-supported parser character sets */ - WSREP_WARN("Current client character set is non-supported parser character set: %s", current_charset->csname); - thd->variables.character_set_client= &my_charset_latin1; - WSREP_WARN("For SST temporally setting character set to : %s", - my_charset_latin1.csname); - } - - snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d", - yes ? 1 : 0); - - if (run_sql_command(thd, query_str)) - { - WSREP_ERROR("Failed to disallow InnoDB writes"); - } - thd->variables.character_set_client= current_charset; -} - - static int sst_flush_tables(THD* thd) { WSREP_INFO("Flushing tables for SST..."); @@ -1503,23 +1475,21 @@ static int sst_flush_tables(THD* thd) } else { - WSREP_INFO("Tables flushed."); + ha_disable_internal_writes(true); - /* disable further disk IO */ - sst_disallow_writes(thd, true); - WSREP_INFO("Disabled further disk IO."); + WSREP_INFO("Tables flushed."); - /* - Tables have been flushed. Create a file with cluster state ID and - wsrep_gtid_domain_id. - */ + // Create a file with cluster state ID and wsrep_gtid_domain_id. char content[100]; snprintf(content, sizeof(content), "%s:%lld %d\n", wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno, wsrep_gtid_domain_id); err= sst_create_file(flush_success, content); - if(err) + if (err) + { WSREP_INFO("Creating file for flush_success failed %d",err); + ha_disable_internal_writes(false); + } } return err; @@ -1570,31 +1540,30 @@ wait_signal: if (!strcasecmp (out, magic_flush)) { err= sst_flush_tables (thd.ptr); + if (!err) { - /* + locked= true; + /* Lets also keep statements that modify binary logs (like RESET LOGS, RESET MASTER) from proceeding until the files have been transferred to the joiner node. */ if (mysql_bin_log.is_open()) - { mysql_mutex_lock(mysql_bin_log.get_log_lock()); - } - - locked= true; - WSREP_INFO("Donor state reached"); + WSREP_INFO("Donor state reached"); DBUG_EXECUTE_IF("sync.wsrep_donor_state", - { - const char act[]= - "now " - "SIGNAL sync.wsrep_donor_state_reached " - "WAIT_FOR signal.wsrep_donor_state"; - assert(!debug_sync_set_action(thd.ptr, - STRING_WITH_LEN(act))); - };); + { + const char act[]= + "now " + "SIGNAL sync.wsrep_donor_state_reached " + "WAIT_FOR signal.wsrep_donor_state"; + assert(!debug_sync_set_action(thd.ptr, + STRING_WITH_LEN(act))); + };); + goto wait_signal; } } @@ -1602,14 +1571,11 @@ wait_signal: { if (locked) { + locked= false; + ha_disable_internal_writes(false); if (mysql_bin_log.is_open()) - { - mysql_mutex_assert_owner(mysql_bin_log.get_log_lock()); mysql_mutex_unlock(mysql_bin_log.get_log_lock()); - } - sst_disallow_writes (thd.ptr, false); - thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); - locked= false; + thd.ptr->global_read_lock.unlock_global_read_lock(thd.ptr); } err= 0; goto wait_signal; @@ -1639,13 +1605,13 @@ wait_signal: if (locked) // don't forget to unlock server before return { + ha_disable_internal_writes(false); if (mysql_bin_log.is_open()) { mysql_mutex_assert_owner(mysql_bin_log.get_log_lock()); mysql_mutex_unlock(mysql_bin_log.get_log_lock()); } - sst_disallow_writes (thd.ptr, false); - thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); + thd.ptr->global_read_lock.unlock_global_read_lock(thd.ptr); } // signal to donor that SST is over diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 386c7864579..4abcf9cb09f 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2021, MariaDB Corporation. +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 @@ -37,6 +37,11 @@ Created Apr 25, 2012 Vasil Dimov # include "wsrep.h" # include "log.h" # include "wsrep_mysqld.h" +extern uint32 wsrep_sst_disable_writes; +# define wsrep_sst_disable_writes \ + my_atomic_load32_explicit(&wsrep_sst_disable_writes, MY_MEMORY_ORDER_RELAXED) +#else +# define wsrep_sst_disable_writes false #endif #include @@ -490,6 +495,11 @@ DECLARE_THREAD(dict_stats_thread)(void*) os_event_wait_time( dict_stats_event, MIN_RECALC_INTERVAL * 1000000); + if (wsrep_sst_disable_writes) { + os_thread_sleep(1000000); + continue; + } + #ifdef UNIV_DEBUG while (innodb_dict_stats_disabled_debug) { os_event_set(dict_stats_disabled_event); diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 376f09b8ff5..d0ea888202e 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2018, 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 @@ -37,6 +37,15 @@ Completed 2011/7/10 Sunny and Jimmy Yang #include "zlib.h" #include "fts0opt.h" #include "fts0vlc.h" +#include "wsrep.h" + +#ifdef WITH_WSREP +extern uint32 wsrep_sst_disable_writes; +# define wsrep_sst_disable_writes \ + my_atomic_load32_explicit(&wsrep_sst_disable_writes, MY_MEMORY_ORDER_RELAXED) +#else +# define wsrep_sst_disable_writes false +#endif /** The FTS optimize thread's work queue. */ ib_wqueue_t* fts_optimize_wq; @@ -2824,6 +2833,16 @@ DECLARE_THREAD(fts_optimize_thread)( && ib_wqueue_is_empty(wq) && n_tables > 0 && n_optimize > 0) { + + /* The queue is empty but we have tables + to optimize. */ + while (UNIV_UNLIKELY(wsrep_sst_disable_writes) + && srv_shutdown_state + <= SRV_SHUTDOWN_INITIATED) { + os_thread_sleep(1000000); + continue; + } + fts_slot_t* slot = static_cast( ib_vector_get(fts_slots, current)); @@ -2882,6 +2901,13 @@ DECLARE_THREAD(fts_optimize_thread)( break; case FTS_MSG_SYNC_TABLE: + if (UNIV_UNLIKELY(wsrep_sst_disable_writes)) { + ib_wqueue_add(wq, msg, msg->heap, + false); + os_thread_sleep(1000000); + goto next; + } + DBUG_EXECUTE_IF( "fts_instrument_msg_sync_sleep", os_thread_sleep(300000);); @@ -2895,6 +2921,7 @@ DECLARE_THREAD(fts_optimize_thread)( } mem_heap_free(msg->heap); +next: n_optimize = done ? 0 : fts_optimize_how_many(); } } @@ -2943,7 +2970,6 @@ fts_optimize_init(void) /* Create FTS optimize work queue */ fts_optimize_wq = ib_wqueue_create(); - ut_a(fts_optimize_wq != NULL); /* Create FTS vector to store fts_slot_t */ heap = mem_heap_create(sizeof(dict_table_t*) * 64); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 02ac53e22dd..3866eb79853 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -104,9 +104,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include "srv0srv.h" #include "srv0start.h" #include "rem0rec.h" -#ifdef UNIV_DEBUG #include "trx0purge.h" -#endif /* UNIV_DEBUG */ #include "trx0roll.h" #include "trx0rseg.h" #include "trx0trx.h" @@ -1894,6 +1892,57 @@ thd_to_trx_id( { return(thd_to_trx(thd)->id); } + +uint32 wsrep_sst_disable_writes; + +static void sst_disable_innodb_writes() +{ + const uint old_count= srv_n_fil_crypt_threads; + fil_crypt_set_thread_cnt(0); + srv_n_fil_crypt_threads= old_count; + + my_atomic_store32_explicit(&wsrep_sst_disable_writes, true, + MY_MEMORY_ORDER_RELAXED); + purge_sys.stop(); + /* We are holding a global MDL thanks to FLUSH TABLES WITH READ LOCK. + + That will prevent any writes from arriving into InnoDB, but it will + not prevent writes of modified pages from the buffer pool, or log + checkpoints. + + Let us perform a log checkpoint to ensure that the entire buffer + pool is clean, so that no writes to persistent files will be + possible during the snapshot, and to guarantee that no crash + recovery will be necessary when starting up on the snapshot. */ + log_make_checkpoint(); + /* If any FILE_MODIFY records were written by the checkpoint, an + extra write of a FILE_CHECKPOINT record could still be invoked by + buf_flush_page_cleaner(). Let us prevent that by invoking another + checkpoint (which will write the FILE_CHECKPOINT record). */ + log_make_checkpoint(); + ut_d(recv_no_log_write= true); + /* If this were not a no-op, an assertion would fail due to + recv_no_log_write. */ + ut_d(log_make_checkpoint()); +} + +static void sst_enable_innodb_writes() +{ + ut_ad(recv_no_log_write); + ut_d(recv_no_log_write= false); + purge_sys.resume(); + my_atomic_store32_explicit(&wsrep_sst_disable_writes, false, + MY_MEMORY_ORDER_RELAXED); + fil_crypt_set_thread_cnt(srv_n_fil_crypt_threads); +} + +static void innodb_disable_internal_writes(bool disable) +{ + if (disable) + sst_disable_innodb_writes(); + else + sst_enable_innodb_writes(); +} #endif /* WITH_WSREP */ /********************************************************************//** @@ -2387,9 +2436,6 @@ os_file_t innobase_mysql_tmpfile( const char* path) { -#ifdef WITH_INNODB_DISALLOW_WRITES - os_event_wait(srv_allow_writes_event); -#endif /* WITH_INNODB_DISALLOW_WRITES */ File fd; DBUG_EXECUTE_IF( @@ -3543,9 +3589,6 @@ static int innodb_init_abort() } srv_tmp_space.shutdown(); -#ifdef WITH_INNODB_DISALLOW_WRITES - os_event_destroy(srv_allow_writes_event); -#endif /* WITH_INNODB_DISALLOW_WRITES */ DBUG_RETURN(1); } @@ -4252,6 +4295,7 @@ static int innodb_init(void* p) innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint; innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint; innobase_hton->fake_trx_id=wsrep_fake_trx_id; + innobase_hton->disable_internal_writes=innodb_disable_internal_writes; #endif /* WITH_WSREP */ innobase_hton->tablefile_extensions = ha_innobase_exts; @@ -20056,39 +20100,6 @@ static MYSQL_SYSVAR_ULONG(buf_dump_status_frequency, srv_buf_dump_status_frequen "dumped. Default is 0 (only start and end status is printed).", NULL, NULL, 0, 0, 100, 0); -#ifdef WITH_INNODB_DISALLOW_WRITES -/******************************************************* - * innobase_disallow_writes variable definition * - *******************************************************/ - -/* Must always init to FALSE. */ -static my_bool innobase_disallow_writes = FALSE; - -/************************************************************************** -An "update" method for innobase_disallow_writes variable. */ -static -void -innobase_disallow_writes_update(THD*, st_mysql_sys_var*, - void* var_ptr, const void* save) -{ - const my_bool val = *static_cast(save); - *static_cast(var_ptr) = val; - ut_a(srv_allow_writes_event); - mysql_mutex_unlock(&LOCK_global_system_variables); - if (val) { - os_event_reset(srv_allow_writes_event); - } else { - os_event_set(srv_allow_writes_event); - } - mysql_mutex_lock(&LOCK_global_system_variables); -} - -static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes, - PLUGIN_VAR_NOCMDOPT, - "Tell InnoDB to stop any writes to disk", - NULL, innobase_disallow_writes_update, FALSE); -#endif /* WITH_INNODB_DISALLOW_WRITES */ - static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG, "Whether to use read ahead for random access within an extent.", @@ -20519,9 +20530,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(change_buffering_debug), MYSQL_SYSVAR(disable_background_merge), #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ -#ifdef WITH_INNODB_DISALLOW_WRITES - MYSQL_SYSVAR(disallow_writes), -#endif /* WITH_INNODB_DISALLOW_WRITES */ MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(read_only), diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 10bfa2d0e82..a7bed269fa4 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -353,11 +353,6 @@ extern ulong srv_log_write_ahead_size; extern my_bool srv_adaptive_flushing; extern my_bool srv_flush_sync; -#ifdef WITH_INNODB_DISALLOW_WRITES -/* When this event is reset we do not allow any file writes to take place. */ -extern os_event_t srv_allow_writes_event; -#endif /* WITH_INNODB_DISALLOW_WRITES */ - /* If this flag is TRUE, then we will load the indexes' (and tables') metadata even if they are marked as "corrupted". Mostly it is for DBA to process corrupted index and table */ diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake index 8262d95030b..833793b65c1 100644 --- a/storage/innobase/innodb.cmake +++ b/storage/innobase/innodb.cmake @@ -1,5 +1,5 @@ # Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2017, 2019, MariaDB Corporation. +# 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 @@ -214,12 +214,6 @@ ELSE() ADD_DEFINITIONS(-DMUTEX_SYS) ENDIF() -OPTION(WITH_INNODB_DISALLOW_WRITES "InnoDB freeze writes patch from Google" ${WITH_WSREP}) -IF (WITH_INNODB_DISALLOW_WRITES) - ADD_DEFINITIONS(-DWITH_INNODB_DISALLOW_WRITES) -ENDIF() -ADD_FEATURE_INFO(INNODB_DISALLOW_WRITES WITH_INNODB_DISALLOW_WRITES "Expose innodb_disallow_writes switch to stop innodb from writing to disk") - # Include directories under innobase INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innobase/include diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index e2a40b06ba4..afd4fa278ea 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (c) 2014, 2021, MariaDB Corporation. +Copyright (c) 2014, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -886,7 +886,6 @@ loop: #endif log_write_mutex_enter(); - ut_ad(!recv_no_log_write); lsn_t limit_lsn = flush_to_disk ? log_sys.flushed_to_disk_lsn @@ -897,6 +896,8 @@ loop: return; } + ut_ad(!recv_no_log_write); + /* If it is a write call we should just go ahead and do it as we checked that write_lsn is not where we'd like it to be. If we have to flush as well then we check if there is a @@ -1452,7 +1453,6 @@ bool log_checkpoint(bool sync) log_mutex_enter(); - ut_ad(!recv_no_log_write); oldest_lsn = log_buf_pool_get_oldest_modification(); /* Because log also contains headers and dummy log records, @@ -1464,9 +1464,16 @@ bool log_checkpoint(bool sync) flushed up to oldest_lsn. */ ut_ad(oldest_lsn >= log_sys.last_checkpoint_lsn); - if (oldest_lsn - > log_sys.last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT) { + const lsn_t age = oldest_lsn - log_sys.last_checkpoint_lsn; + if (age > SIZE_OF_MLOG_CHECKPOINT + + LOG_BLOCK_HDR_SIZE + LOG_BLOCK_CHECKSUM) { /* Some log has been written since the previous checkpoint. */ + } else if (age > SIZE_OF_MLOG_CHECKPOINT + && !((log_sys.log.calc_lsn_offset(oldest_lsn) + ^ log_sys.log.calc_lsn_offset( + log_sys.last_checkpoint_lsn)) + & ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1))) { + /* Some log has been written to the same log block. */ } else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { /* MariaDB 10.3 startup expects the redo log file to be logically empty (not even containing a MLOG_CHECKPOINT record) @@ -1478,6 +1485,9 @@ bool log_checkpoint(bool sync) log_mutex_exit(); return(true); } + + ut_ad(!recv_no_log_write); + /* Repeat the MLOG_FILE_NAME records after the checkpoint, in case some log records between the checkpoint and log_sys.lsn need them. Finally, write a MLOG_CHECKPOINT marker. Redo log diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 329fd29b119..8c76e86ef0f 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -114,12 +114,6 @@ static const ulint OS_AIO_MERGE_N_CONSECUTIVE = 64; /** Flag indicating if the page_cleaner is in active state. */ extern bool buf_page_cleaner_is_active; -#ifdef WITH_INNODB_DISALLOW_WRITES -#define WAIT_ALLOW_WRITES() os_event_wait(srv_allow_writes_event) -#else -#define WAIT_ALLOW_WRITES() do { } while (0) -#endif /* WITH_INNODB_DISALLOW_WRITES */ - /********************************************************************** InnoDB AIO Implementation: @@ -1247,7 +1241,6 @@ FILE* os_file_create_tmpfile() { FILE* file = NULL; - WAIT_ALLOW_WRITES(); os_file_t fd = innobase_mysql_tmpfile(NULL); if (fd != OS_FILE_CLOSED) { @@ -2611,7 +2604,6 @@ os_file_flush_func( { int ret; - WAIT_ALLOW_WRITES(); ret = os_file_fsync_posix(file); if (ret == 0) { @@ -2663,10 +2655,6 @@ os_file_create_simple_func( int create_flag; const char* mode_str = NULL; - if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) { - WAIT_ALLOW_WRITES(); - } - ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); ut_a(!(create_mode & OS_FILE_ON_ERROR_NO_EXIT)); @@ -2784,7 +2772,6 @@ os_file_create_directory( { int rcode; - WAIT_ALLOW_WRITES(); rcode = mkdir(pathname, 0770); if (!(rcode == 0 || (errno == EEXIST && !fail_if_exists))) { @@ -3119,10 +3106,6 @@ os_file_create_simple_no_error_handling_func( os_file_t file; int create_flag; - if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) { - WAIT_ALLOW_WRITES(); - } - ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); ut_a(!(create_mode & OS_FILE_ON_ERROR_NO_EXIT)); @@ -3197,7 +3180,6 @@ os_file_delete_if_exists_func( } int ret; - WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -3222,7 +3204,6 @@ os_file_delete_func( const char* name) { int ret; - WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -3261,7 +3242,6 @@ os_file_rename_func( #endif /* UNIV_DEBUG */ int ret; - WAIT_ALLOW_WRITES(); ret = rename(oldpath, newpath); @@ -3435,7 +3415,6 @@ bool os_file_set_eof( FILE* file) /*!< in: file to be truncated */ { - WAIT_ALLOW_WRITES(); return(!ftruncate(fileno(file), ftell(file))); } @@ -4157,10 +4136,6 @@ os_file_create_func( ? FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE : FILE_SHARE_READ | FILE_SHARE_DELETE; - if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) { - WAIT_ALLOW_WRITES(); - } - on_error_no_exit = create_mode & OS_FILE_ON_ERROR_NO_EXIT ? true : false; @@ -5008,8 +4983,6 @@ os_file_write_func( ut_ad(type.validate()); ut_ad(n > 0); - WAIT_ALLOW_WRITES(); - ssize_t n_bytes = os_file_pwrite(type, file, (byte*)buf, n, offset, &err); if ((ulint) n_bytes != n && !os_has_said_disk_full) { diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index d6ace914c23..71df96c5be1 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. -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 diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 93efe7ed3f4..2bc5500ef91 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -218,10 +218,6 @@ srv_printf_innodb_monitor() will request mutex acquisition with mutex_enter(), which will wait until it gets the mutex. */ #define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT) -#ifdef WITH_INNODB_DISALLOW_WRITES -UNIV_INTERN os_event_t srv_allow_writes_event; -#endif /* WITH_INNODB_DISALLOW_WRITES */ - /** copy of innodb_buffer_pool_size */ ulint srv_buf_pool_size; /** Requested buffer pool chunk size. Each buffer pool instance consists @@ -1059,15 +1055,6 @@ srv_init() dict_ind_init(); -#ifdef WITH_INNODB_DISALLOW_WRITES - /* Writes have to be enabled on init or else we hang. Thus, we - always set the event here regardless of innobase_disallow_writes. - That flag will always be 0 at this point because it isn't settable - via my.cnf or command line arg. */ - srv_allow_writes_event = os_event_create(0); - os_event_set(srv_allow_writes_event); -#endif /* WITH_INNODB_DISALLOW_WRITES */ - /* Initialize some INFORMATION SCHEMA internal structures */ trx_i_s_cache_init(trx_i_s_cache); @@ -1822,20 +1809,7 @@ loop: if (sync_array_print_long_waits(&waiter, &sema) && sema == old_sema && os_thread_eq(waiter, old_waiter)) { -#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) - if (os_event_is_set(srv_allow_writes_event)) { -#endif /* WITH_WSREP */ fatal_cnt++; -#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) - } else { - fprintf(stderr, - "WSREP: avoiding InnoDB self crash due to long " - "semaphore wait of > %lu seconds\n" - "Server is processing SST donor operation, " - "fatal_cnt now: " ULINTPF, - srv_fatal_semaphore_wait_threshold, fatal_cnt); - } -#endif /* WITH_WSREP */ if (fatal_cnt > 10) { ib::fatal() << "Semaphore wait has lasted > " << srv_fatal_semaphore_wait_threshold diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 4144ae86578..48f71db73e4 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -3,7 +3,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -2680,10 +2680,6 @@ void innodb_shutdown() } srv_tmp_space.shutdown(); -#ifdef WITH_INNODB_DISALLOW_WRITES - os_event_destroy(srv_allow_writes_event); -#endif /* WITH_INNODB_DISALLOW_WRITES */ - if (srv_was_started && srv_print_verbose_log) { ib::info() << "Shutdown completed; log sequence number " << srv_shutdown_lsn -- cgit v1.2.1 From aed87f1e0aa20e9e3f525ff303ee766ca6b106b7 Mon Sep 17 00:00:00 2001 From: Faustin Lammler Date: Thu, 31 Mar 2022 10:14:12 +0200 Subject: Change MDBF mirror URL As as discussed with @dbart we decided to move https://deb.mariadb.org/repo to https://deb.mariadb.org so that a request on https://deb.mariadb.org will end up directly in https://mirror.mariadb.org/repo. The same behavior was configured for rpms (https://rpm.mariadb.org --> https://mirror.mariadb.org/yum) this also makes the old yum.mariadb.org service transparently compatible with this new service (after DNS change to point to rpm.mariadb.org). See also: https://jira.mariadb.org/browse/MDBF-297 --- debian/salsa-ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml index 499c0e9e92b..24f59aae221 100644 --- a/debian/salsa-ci.yml +++ b/debian/salsa-ci.yml @@ -519,7 +519,7 @@ mariadb.org-10.5 to mariadb-10.5 upgrade: - *test-prepare-container - apt install -y curl - curl -sS https://mariadb.org/mariadb_release_signing_key.asc -o /etc/apt/trusted.gpg.d/mariadb.asc - - echo "deb https://deb.mariadb.org/repo/10.5/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list + - echo "deb https://deb.mariadb.org/10.5/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list - apt-get update # The 10.5.9 release is missing mariadb-plugin-columnstore, define all other packages but it to avoid hitting the error: # The following packages have unmet dependencies: @@ -539,7 +539,7 @@ mariadb.org-10.5 to mariadb-10.5 upgrade: - *test-verify-final variables: GIT_STRATEGY: none - RELEASE: bullseye # Last Debian release that MariaDB.org publised 10.5 binaries for + RELEASE: bullseye # Last Debian release that MariaDB.org published 10.5 binaries for except: variables: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ @@ -558,7 +558,7 @@ mariadb.org-10.4 to mariadb-10.5 upgrade: - *test-prepare-container - apt install -y curl - curl -sS https://mariadb.org/mariadb_release_signing_key.asc -o /etc/apt/trusted.gpg.d/mariadb.asc - - echo "deb https://deb.mariadb.org/repo/10.4/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list + - echo "deb https://deb.mariadb.org/10.4/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list - apt-get update - apt-get install -y mariadb-server-10.4 # MariaDB.org version of 10.4 and early 10.5 do not install an init file, so @@ -572,7 +572,7 @@ mariadb.org-10.4 to mariadb-10.5 upgrade: - *test-verify-final variables: GIT_STRATEGY: none - RELEASE: buster # Last Debian release that MariaDB.org publised 10.4 binaries for + RELEASE: buster # Last Debian release that MariaDB.org published 10.4 binaries for except: variables: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ @@ -591,7 +591,7 @@ mariadb.org-10.3 to mariadb-10.5 upgrade: - *test-prepare-container - apt install -y curl - curl -sS https://mariadb.org/mariadb_release_signing_key.asc -o /etc/apt/trusted.gpg.d/mariadb.asc - - echo "deb https://deb.mariadb.org/repo/10.3/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list + - echo "deb https://deb.mariadb.org/10.3/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list - apt-get update - apt-get install -y mariadb-server-10.3 - *test-verify-initial @@ -605,7 +605,7 @@ mariadb.org-10.3 to mariadb-10.5 upgrade: - *test-verify-final variables: GIT_STRATEGY: none - RELEASE: buster # Last Debian release that MariaDB.org publised 10.3 binaries for + RELEASE: buster # Last Debian release that MariaDB.org published 10.3 binaries for except: variables: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ @@ -624,7 +624,7 @@ mariadb.org-10.2 to mariadb-10.5 upgrade: - *test-prepare-container - apt install -y curl apt-transport-https - curl -sS https://mariadb.org/mariadb_release_signing_key.asc -o /etc/apt/trusted.gpg.d/mariadb.asc - - echo "deb https://deb.mariadb.org/repo/10.2/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list + - echo "deb https://deb.mariadb.org/10.2/debian ${RELEASE} main" > /etc/apt/sources.list.d/mariadb.list - apt-get update - apt-get install -y mariadb-server-10.2 # Verify initial state before upgrade @@ -657,7 +657,7 @@ mariadb.org-10.2 to mariadb-10.5 upgrade: - *test-verify-final variables: GIT_STRATEGY: none - RELEASE: stretch # Last Debian release that MariaDB.org publised 10.2 binaries for + RELEASE: stretch # Last Debian release that MariaDB.org published 10.2 binaries for except: variables: - $CI_COMMIT_TAG != null && $SALSA_CI_ENABLE_PIPELINE_ON_TAGS !~ /^(1|yes|true)$/ -- cgit v1.2.1 From d6758efbe126cdc6a0718a4b560d9e8f494c0399 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Thu, 21 Oct 2021 14:49:51 +0300 Subject: MDEV-23328 Server hang due to Galera lock conflict resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick the sql_kill and sql_user_kill from ef2dbb8dbc3e Changed ER_CANNOT_USER to ER_KILL_DENIED_ERROR to match other kill denied user messages. Cherry-pick by Daniel Black. Reviewed-by: Jan Lindström --- sql/sql_parse.cc | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3f1bb257750..27f269ab61b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -9203,6 +9203,7 @@ THD *find_thread_by_id(longlong id, bool query_id) return arg.thd; } + /** kill one thread. @@ -9246,7 +9247,8 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ faster and do a harder kill than KILL_SYSTEM_THREAD; */ - mysql_mutex_lock(&tmp->LOCK_thd_data); // for various wsrep* checks below + mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from concurrent usage + #ifdef WITH_WSREP if (((thd->security_ctx->master_access & PRIV_KILL_OTHER_USER_PROCESS) || thd->security_ctx->user_matches(tmp->security_ctx)) && @@ -9261,23 +9263,23 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ if (tmp->wsrep_aborter && tmp->wsrep_aborter != thd->thread_id) { /* victim is in hit list already, bail out */ - WSREP_DEBUG("victim has wsrep aborter: %lu, skipping awake()", - tmp->wsrep_aborter); + WSREP_DEBUG("victim %lld has wsrep aborter: %lu, skipping awake()", + id, tmp->wsrep_aborter); error= 0; } else #endif /* WITH_WSREP */ { - WSREP_DEBUG("kill_one_thread %llu, victim: %llu wsrep_aborter %llu by signal %d", - thd->thread_id, id, tmp->wsrep_aborter, kill_signal); + WSREP_DEBUG("kill_one_thread victim: %lld wsrep_aborter %lu by signal %d", + id, tmp->wsrep_aborter, kill_signal); tmp->awake_no_mutex(kill_signal); - WSREP_DEBUG("victim: %llu taken care of", id); error= 0; } } else error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR : ER_KILL_DENIED_ERROR); + mysql_mutex_unlock(&tmp->LOCK_thd_data); } mysql_mutex_unlock(&tmp->LOCK_thd_kill); @@ -9392,6 +9394,18 @@ static void sql_kill(THD *thd, longlong id, killed_state state, killed_type type) { uint error; +#ifdef WITH_WSREP + if (WSREP(thd)) + { + WSREP_DEBUG("sql_kill called"); + if (thd->wsrep_applier) + { + WSREP_DEBUG("KILL in applying, bailing out here"); + return; + } + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + } +#endif /* WITH_WSREP */ if (likely(!(error= kill_one_thread(thd, id, state, type)))) { if (!thd->killed) @@ -9401,6 +9415,11 @@ void sql_kill(THD *thd, longlong id, killed_state state, killed_type type) } else my_error(error, MYF(0), id); +#ifdef WITH_WSREP + return; + wsrep_error_label: + my_error(ER_KILL_DENIED_ERROR, MYF(0), (long long) thd->thread_id); +#endif /* WITH_WSREP */ } @@ -9409,6 +9428,18 @@ sql_kill_user(THD *thd, LEX_USER *user, killed_state state) { uint error; ha_rows rows; +#ifdef WITH_WSREP + if (WSREP(thd)) + { + WSREP_DEBUG("sql_kill_user called"); + if (thd->wsrep_applier) + { + WSREP_DEBUG("KILL in applying, bailing out here"); + return; + } + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + } +#endif /* WITH_WSREP */ switch (error= kill_threads_for_user(thd, user, state, &rows)) { case 0: @@ -9421,6 +9452,11 @@ sql_kill_user(THD *thd, LEX_USER *user, killed_state state) default: my_error(error, MYF(0)); } +#ifdef WITH_WSREP + return; + wsrep_error_label: + my_error(ER_KILL_DENIED_ERROR, MYF(0), (long long) thd->thread_id); +#endif /* WITH_WSREP */ } -- cgit v1.2.1 From f089f8d95e569291bdf4329124c34674f02e40fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 6 Apr 2022 08:59:41 +0300 Subject: MDEV-23328 fixup: sign mismatch in format strings kill_one_thread(): Fix integer sign mismatch in some format strings. Some of this was introduced in commit 5c230b21bfa582ac304db526c3638c514cf98b13 --- sql/sql_parse.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 35310d2655a..e3efa2d051c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2008, 2021, MariaDB + Copyright (c) 2008, 2022, MariaDB 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 @@ -9176,7 +9176,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ THD *tmp; uint error= (type == KILL_TYPE_QUERY ? ER_NO_SUCH_QUERY : ER_NO_SUCH_THREAD); DBUG_ENTER("kill_one_thread"); - DBUG_PRINT("enter", ("id: %lld signal: %u", id, (uint) kill_signal)); + DBUG_PRINT("enter", ("id: %lld signal: %d", id, kill_signal)); tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY); if (!tmp) DBUG_RETURN(error); @@ -9220,14 +9220,15 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ if (tmp->wsrep_aborter && tmp->wsrep_aborter != thd->thread_id) { /* victim is in hit list already, bail out */ - WSREP_DEBUG("victim %llu has wsrep aborter: %lu, skipping awake()", + WSREP_DEBUG("victim %lld has wsrep aborter: %lu, skipping awake()", id, tmp->wsrep_aborter); error= 0; } else #endif /* WITH_WSREP */ { - WSREP_DEBUG("kill_one_thread victim: %llu wsrep_aborter %lu by signal %d", + WSREP_DEBUG("kill_one_thread victim: %lld wsrep_aborter %lu" + " by signal %d", id, tmp->wsrep_aborter, kill_signal); tmp->awake_no_mutex(kill_signal); error= 0; @@ -9240,7 +9241,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ mysql_mutex_unlock(&tmp->LOCK_thd_data); } mysql_mutex_unlock(&tmp->LOCK_thd_kill); - DBUG_PRINT("exit", ("%d", error)); + DBUG_PRINT("exit", ("%u", error)); DBUG_RETURN(error); } -- cgit v1.2.1 From cbdf62ae907ad42ceb7a65e070b821bb45e07be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 6 Apr 2022 10:13:21 +0300 Subject: MDEV-25975 merge fixup --- storage/innobase/dict/dict0stats_bg.cc | 6 ++---- storage/innobase/fts/fts0opt.cc | 6 ++---- storage/innobase/log/log0log.cc | 5 ++--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index d2a72695d4e..4968612e964 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -37,11 +37,9 @@ Created Apr 25, 2012 Vasil Dimov # include "wsrep.h" # include "log.h" # include "wsrep_mysqld.h" -extern uint32 wsrep_sst_disable_writes; -# define wsrep_sst_disable_writes \ - my_atomic_load32_explicit(&wsrep_sst_disable_writes, MY_MEMORY_ORDER_RELAXED) +extern Atomic_relaxed wsrep_sst_disable_writes; #else -# define wsrep_sst_disable_writes false +constexpr bool wsrep_sst_disable_writes= false; #endif #include diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index ab75968ec91..bb8d9c13d68 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -40,11 +40,9 @@ Completed 2011/7/10 Sunny and Jimmy Yang #include "wsrep.h" #ifdef WITH_WSREP -extern uint32 wsrep_sst_disable_writes; -# define wsrep_sst_disable_writes \ - my_atomic_load32_explicit(&wsrep_sst_disable_writes, MY_MEMORY_ORDER_RELAXED) +extern Atomic_relaxed wsrep_sst_disable_writes; #else -# define wsrep_sst_disable_writes false +constexpr bool wsrep_sst_disable_writes= false; #endif /** The FTS optimize thread's work queue. */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index c58df6314e9..bf75b3b7c86 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -1460,14 +1460,13 @@ bool log_checkpoint(bool sync) ut_ad(oldest_lsn >= log_sys.last_checkpoint_lsn); const lsn_t age = oldest_lsn - log_sys.last_checkpoint_lsn; - if (age > SIZE_OF_MLOG_CHECKPOINT - + LOG_BLOCK_HDR_SIZE + LOG_BLOCK_CHECKSUM) { + if (age > SIZE_OF_MLOG_CHECKPOINT + log_sys.framing_size()) { /* Some log has been written since the previous checkpoint. */ } else if (age > SIZE_OF_MLOG_CHECKPOINT && !((log_sys.log.calc_lsn_offset(oldest_lsn) ^ log_sys.log.calc_lsn_offset( log_sys.last_checkpoint_lsn)) - & ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1))) { + & ~lsn_t{OS_FILE_LOG_BLOCK_SIZE - 1})) { /* Some log has been written to the same log block. */ } else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { /* MariaDB 10.3 startup expects the redo log file to be -- cgit v1.2.1 From fd6a464ae5a4a4db4950fb9c7606a40d6fc32256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 6 Apr 2022 11:51:36 +0300 Subject: MDEV-13005 after-merge fixup --- mysql-test/suite/sql_sequence/create.result | 2 +- mysql-test/suite/sql_sequence/create.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index 7f13470ab97..15cf5cb77de 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -703,7 +703,7 @@ ERROR HY000: Sequence 'test.seq1' has out of range value for options # Task 4: CREATE TEMPORARY TABLE s1 (s1 INT); DROP TEMPORARY SEQUENCE s1; -ERROR 42S02: 'test.s1' is not a SEQUENCE +ERROR 42S02: Unknown SEQUENCE: 'test.s1' DROP TEMPORARY TABLE s1; # Task 5: CREATE TEMPORARY TABLE s1 (s1 INT); diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index e9852797ba3..49b39fbb40c 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -536,7 +536,7 @@ CREATE SEQUENCE seq1 START WITH 1 cache -1; --echo # Task 4: CREATE TEMPORARY TABLE s1 (s1 INT); ---error ER_NOT_SEQUENCE2 +--error ER_UNKNOWN_SEQUENCES DROP TEMPORARY SEQUENCE s1; DROP TEMPORARY TABLE s1; -- cgit v1.2.1 From 4e1ca388381eea27a9275571744ad17ce317b273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 6 Apr 2022 12:51:27 +0300 Subject: MDEV-26781 InnoDB hangs when using SUX_LOCK_GENERIC The Shared/Update/Exclusive locks that were introduced in commit 03ca6495df31313c96e38834b9a235245e2ae2a8 (MDEV-24142) did not work correctly when a futex-like system call interface was not available. On all tested implementations (IBM AIX as well as FreeBSD and GNU/Linux with the futex interface artificially disabled), the old implementation would cause hangs in some SPATIAL INDEX tests (innodb_gis suite). On FreeBSD, a hang was also observed in an encryption test. We will simply emulate the futex system calls with a single mutex and two condition variables, one for each wait queue. The condition variables basically shadow the lock words and are used as wait queues, just like the futex system calls would be. The storage overhead of ssux_lock_impl will be increased by 32 bits when using SUX_LOCK_GENERIC. Compared to the futex-based implementation, the SUX_LOCK_GENERIC implementation has an overhead of sizeof(pthread_mutex_t)+2*sizeof(pthread_cond_t). rw_lock: Remove all SUX_LOCK_GENERIC extensions. pthread_mutex_wrapper: A simple wrapper of pthread_mutex that implements srw_spin_mutex and srw_mutex for SUX_LOCK_GENERIC. srw_mutex_impl: Define this also for SUX_LOCK_GENERIC, but in that case add the fields mutex, cond. ssux_lock_impl: Define for SUX_LOCK_GENERIC with a minimal difference: adding readers_cond. --- storage/innobase/include/rw_lock.h | 104 ------------- storage/innobase/include/srw_lock.h | 152 +++++++++++-------- storage/innobase/sync/srw_lock.cc | 291 ++++++------------------------------ 3 files changed, 138 insertions(+), 409 deletions(-) diff --git a/storage/innobase/include/rw_lock.h b/storage/innobase/include/rw_lock.h index 70607b979c1..4881f2f1d35 100644 --- a/storage/innobase/include/rw_lock.h +++ b/storage/innobase/include/rw_lock.h @@ -20,25 +20,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include #include "my_dbug.h" -#if defined __linux__ -/* futex(2): FUTEX_WAIT_PRIVATE, FUTEX_WAKE_PRIVATE */ -#elif defined __OpenBSD__ || defined __FreeBSD__ || defined __DragonFly__ -/* system calls similar to Linux futex(2) */ -#elif defined _WIN32 -/* SRWLOCK as well as WaitOnAddress(), WakeByAddressSingle() */ -#else -# define SUX_LOCK_GENERIC /* fall back to generic synchronization primitives */ -#endif - -#if !defined SUX_LOCK_GENERIC && 0 /* defined SAFE_MUTEX */ -# define SUX_LOCK_GENERIC /* Use dummy implementation for debugging purposes */ -#endif - -#ifdef SUX_LOCK_GENERIC -/** Simple read-update-write lock based on std::atomic */ -#else /** Simple read-write lock based on std::atomic */ -#endif class rw_lock { /** The lock word */ @@ -53,10 +35,6 @@ protected: static constexpr uint32_t WRITER_WAITING= 1U << 30; /** Flag to indicate that write_lock() or write_lock_wait() is pending */ static constexpr uint32_t WRITER_PENDING= WRITER | WRITER_WAITING; -#ifdef SUX_LOCK_GENERIC - /** Flag to indicate that an update lock exists */ - static constexpr uint32_t UPDATER= 1U << 29; -#endif /* SUX_LOCK_GENERIC */ /** Start waiting for an exclusive lock. */ void write_lock_wait_start() @@ -84,12 +62,8 @@ protected: std::memory_order_relaxed); } /** Try to acquire a shared lock. - @tparam prioritize_updater whether to ignore WRITER_WAITING for UPDATER @param l the value of the lock word @return whether the lock was acquired */ -#ifdef SUX_LOCK_GENERIC - template -#endif /* SUX_LOCK_GENERIC */ bool read_trylock(uint32_t &l) { l= UNLOCKED; @@ -97,66 +71,11 @@ protected: std::memory_order_relaxed)) { DBUG_ASSERT(!(WRITER & l) || !(~WRITER_PENDING & l)); -#ifdef SUX_LOCK_GENERIC - DBUG_ASSERT((~(WRITER_PENDING | UPDATER) & l) < UPDATER); - if (prioritize_updater - ? (WRITER & l) || ((WRITER_WAITING | UPDATER) & l) == WRITER_WAITING - : (WRITER_PENDING & l)) -#else /* SUX_LOCK_GENERIC */ if (l & WRITER_PENDING) -#endif /* SUX_LOCK_GENERIC */ return false; } return true; } -#ifdef SUX_LOCK_GENERIC - /** Try to acquire an update lock. - @param l the value of the lock word - @return whether the lock was acquired */ - bool update_trylock(uint32_t &l) - { - l= UNLOCKED; - while (!lock.compare_exchange_strong(l, l | UPDATER, - std::memory_order_acquire, - std::memory_order_relaxed)) - { - DBUG_ASSERT(!(WRITER & l) || !(~WRITER_PENDING & l)); - DBUG_ASSERT((~(WRITER_PENDING | UPDATER) & l) < UPDATER); - if ((WRITER_PENDING | UPDATER) & l) - return false; - } - return true; - } - /** Try to upgrade an update lock to an exclusive lock. - @return whether the update lock was upgraded to exclusive */ - bool upgrade_trylock() - { - auto l= UPDATER; - while (!lock.compare_exchange_strong(l, WRITER, - std::memory_order_acquire, - std::memory_order_relaxed)) - { - /* Either conflicting (read) locks have been granted, or - the WRITER_WAITING flag was set by some thread that is waiting - to become WRITER. */ - DBUG_ASSERT(((WRITER | UPDATER) & l) == UPDATER); - if (~(WRITER_WAITING | UPDATER) & l) - return false; - } - DBUG_ASSERT((l & ~WRITER_WAITING) == UPDATER); - /* Any thread that had set WRITER_WAITING will eventually be woken - up by ssux_lock_impl::x_unlock() or ssux_lock_impl::u_unlock() - (not ssux_lock_impl::wr_u_downgrade() to keep the code simple). */ - return true; - } - /** Downgrade an exclusive lock to an update lock. */ - void downgrade() - { - IF_DBUG_ASSERT(auto l=,) - lock.fetch_xor(WRITER | UPDATER, std::memory_order_relaxed); - DBUG_ASSERT((l & ~WRITER_WAITING) == WRITER); - } -#endif /* SUX_LOCK_GENERIC */ /** Wait for an exclusive lock. @return whether the exclusive lock was acquired */ @@ -183,24 +102,9 @@ public: { auto l= lock.fetch_sub(1, std::memory_order_release); DBUG_ASSERT(!(l & WRITER)); /* no write lock must have existed */ -#ifdef SUX_LOCK_GENERIC - DBUG_ASSERT(~(WRITER_PENDING | UPDATER) & l); /* at least one read lock */ - return (~(WRITER_PENDING | UPDATER) & l) == 1; -#else /* SUX_LOCK_GENERIC */ DBUG_ASSERT(~(WRITER_PENDING) & l); /* at least one read lock */ return (~WRITER_PENDING & l) == 1; -#endif /* SUX_LOCK_GENERIC */ - } -#ifdef SUX_LOCK_GENERIC - /** Release an update lock */ - void update_unlock() - { - IF_DBUG_ASSERT(auto l=,) - lock.fetch_and(~UPDATER, std::memory_order_release); - /* the update lock must have existed */ - DBUG_ASSERT((l & (WRITER | UPDATER)) == UPDATER); } -#endif /* SUX_LOCK_GENERIC */ /** Release an exclusive lock */ void write_unlock() { @@ -211,11 +115,7 @@ public: static_assert(WRITER == 1U << 31, "compatibility"); IF_DBUG_ASSERT(auto l=,) lock.fetch_sub(WRITER, std::memory_order_release); /* the write lock must have existed */ -#ifdef SUX_LOCK_GENERIC - DBUG_ASSERT((l & (WRITER | UPDATER)) == WRITER); -#else /* SUX_LOCK_GENERIC */ DBUG_ASSERT(l & WRITER); -#endif /* SUX_LOCK_GENERIC */ } /** Try to acquire a shared lock. @return whether the lock was acquired */ @@ -231,10 +131,6 @@ public: /** @return whether an exclusive lock is being held by any thread */ bool is_write_locked() const { return !!(value() & WRITER); } -#ifdef SUX_LOCK_GENERIC - /** @return whether an update lock is being held by any thread */ - bool is_update_locked() const { return !!(value() & UPDATER); } -#endif /* SUX_LOCK_GENERIC */ /** @return whether any lock is being held or waited for by any thread */ bool is_locked_or_waiting() const { return value() != 0; } /** @return whether any lock is being held by any thread */ diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h index be72af9cc39..1dca0cc1054 100644 --- a/storage/innobase/include/srw_lock.h +++ b/storage/innobase/include/srw_lock.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2020, 2021, MariaDB Corporation. +Copyright (c) 2020, 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 @@ -20,27 +20,58 @@ this program; if not, write to the Free Software Foundation, Inc., #include "univ.i" #include "rw_lock.h" +#if defined __linux__ +/* futex(2): FUTEX_WAIT_PRIVATE, FUTEX_WAKE_PRIVATE */ +#elif defined __OpenBSD__ || defined __FreeBSD__ || defined __DragonFly__ +/* system calls similar to Linux futex(2) */ +#elif defined _WIN32 +/* SRWLOCK as well as WaitOnAddress(), WakeByAddressSingle() */ +#else +# define SUX_LOCK_GENERIC /* fall back to generic synchronization primitives */ +#endif + +#if !defined SUX_LOCK_GENERIC && 0 /* defined SAFE_MUTEX */ +# define SUX_LOCK_GENERIC /* Use dummy implementation for debugging purposes */ +#endif + #ifdef SUX_LOCK_GENERIC /** An exclusive-only variant of srw_lock */ template -class srw_mutex_impl final +class pthread_mutex_wrapper final { pthread_mutex_t lock; - void wr_wait(); public: - void init() { pthread_mutex_init(&lock, nullptr); } + void init() + { + if (spinloop) + pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST); + else + pthread_mutex_init(&lock, nullptr); + } void destroy() { pthread_mutex_destroy(&lock); } +# ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP + void wr_lock() { pthread_mutex_lock(&lock); } +# else +private: + void wr_wait(); +public: inline void wr_lock(); +# endif void wr_unlock() { pthread_mutex_unlock(&lock); } bool wr_lock_try() { return !pthread_mutex_trylock(&lock); } }; -template<> void srw_mutex_impl::wr_wait(); +# ifndef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +template<> void pthread_mutex_wrapper::wr_wait(); template<> -inline void srw_mutex_impl::wr_lock() { pthread_mutex_lock(&lock); } +inline void pthread_mutex_wrapper::wr_lock() +{ pthread_mutex_lock(&lock); } template<> -inline void srw_mutex_impl::wr_lock() { if (!wr_lock_try()) wr_wait(); } -#else +inline void pthread_mutex_wrapper::wr_lock() +{ if (!wr_lock_try()) wr_wait(); } +# endif +#endif + /** Futex-based mutex */ template class srw_mutex_impl final @@ -51,6 +82,15 @@ class srw_mutex_impl final /** Identifies that the lock is being held */ static constexpr uint32_t HOLDER= 1U << 31; +#ifdef SUX_LOCK_GENERIC +public: + /** The mutex for the condition variables. */ + pthread_mutex_t mutex; +private: + /** Condition variable for the lock word. Used with mutex. */ + pthread_cond_t cond; +#endif + /** Wait until the mutex has been acquired */ void wait_and_lock(); /** Wait for lock!=lk */ @@ -65,8 +105,22 @@ public: bool is_locked() const { return (lock.load(std::memory_order_acquire) & HOLDER) != 0; } - void init() { DBUG_ASSERT(!is_locked_or_waiting()); } - void destroy() { DBUG_ASSERT(!is_locked_or_waiting()); } + void init() + { + DBUG_ASSERT(!is_locked_or_waiting()); +#ifdef SUX_LOCK_GENERIC + pthread_mutex_init(&mutex, nullptr); + pthread_cond_init(&cond, nullptr); +#endif + } + void destroy() + { + DBUG_ASSERT(!is_locked_or_waiting()); +#ifdef SUX_LOCK_GENERIC + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); +#endif + } /** @return whether the mutex was acquired */ bool wr_lock_try() @@ -88,19 +142,20 @@ public: } } }; -#endif +#ifdef SUX_LOCK_GENERIC +typedef pthread_mutex_wrapper srw_spin_mutex; +typedef pthread_mutex_wrapper srw_mutex; +#else typedef srw_mutex_impl srw_spin_mutex; typedef srw_mutex_impl srw_mutex; +#endif template class srw_lock_impl; /** Slim shared-update-exclusive lock with no recursion */ template class ssux_lock_impl final -#ifdef SUX_LOCK_GENERIC - : private rw_lock -#endif { #ifdef UNIV_PFS_RWLOCK friend class ssux_lock; @@ -110,50 +165,12 @@ class ssux_lock_impl final friend srw_lock_impl; # endif #endif -#ifdef SUX_LOCK_GENERIC - pthread_mutex_t mutex; - pthread_cond_t cond_shared; - pthread_cond_t cond_exclusive; - - /** Wait for a read lock. - @param l lock word from a failed read_trylock() */ - void read_lock(uint32_t l); - /** Wait for an update lock. - @param l lock word from a failed update_trylock() */ - void update_lock(uint32_t l); - /** Wait for a write lock after a failed write_trylock() or upgrade_trylock() - @param holding_u whether we already hold u_lock() */ - void write_lock(bool holding_u); - /** Wait for signal - @param l lock word from a failed acquisition */ - inline void writer_wait(uint32_t l); - /** Wait for signal - @param l lock word from a failed acquisition */ - inline void readers_wait(uint32_t l); - /** Wake waiters */ - inline void wake(); -public: - void init(); - void destroy(); - /** @return whether any writer is waiting */ - bool is_waiting() const { return (value() & WRITER_WAITING) != 0; } - bool is_write_locked() const { return rw_lock::is_write_locked(); } - bool is_locked_or_waiting() const { return rw_lock::is_locked_or_waiting(); } - - bool rd_lock_try() { uint32_t l; return read_trylock(l); } - bool wr_lock_try() { return write_trylock(); } - void rd_lock() { uint32_t l; if (!read_trylock(l)) read_lock(l); } - void u_lock() { uint32_t l; if (!update_trylock(l)) update_lock(l); } - bool u_lock_try() { uint32_t l; return update_trylock(l); } - void u_wr_upgrade() { if (!upgrade_trylock()) write_lock(true); } - void wr_u_downgrade() { downgrade(); } - void wr_lock() { if (!write_trylock()) write_lock(false); } - void rd_unlock(); - void u_unlock(); - void wr_unlock(); -#else /** mutex for synchronization; held by U or X lock holders */ srw_mutex_impl writer; +#ifdef SUX_LOCK_GENERIC + /** Condition variable for "readers"; used with writer.mutex. */ + pthread_cond_t readers_cond; +#endif /** S or U holders, and WRITER flag for X holder or waiter */ std::atomic readers; /** indicates an X request; readers=WRITER indicates granted X lock */ @@ -169,15 +186,29 @@ public: /** Acquire a read lock */ void rd_wait(); public: - void init() { DBUG_ASSERT(is_vacant()); } - void destroy() { DBUG_ASSERT(is_vacant()); } + void init() + { + writer.init(); + DBUG_ASSERT(is_vacant()); +#ifdef SUX_LOCK_GENERIC + pthread_cond_init(&readers_cond, nullptr); +#endif + } + void destroy() + { + DBUG_ASSERT(is_vacant()); + writer.destroy(); +#ifdef SUX_LOCK_GENERIC + pthread_cond_destroy(&readers_cond); +#endif + } /** @return whether any writer is waiting */ bool is_waiting() const { return (readers.load(std::memory_order_relaxed) & WRITER) != 0; } -# ifndef DBUG_OFF +#ifndef DBUG_OFF /** @return whether the lock is being held or waited for */ bool is_vacant() const { return !is_locked_or_waiting(); } -# endif /* !DBUG_OFF */ +#endif /* !DBUG_OFF */ bool rd_lock_try() { @@ -288,7 +319,6 @@ public: void unlock_shared() { rd_unlock(); } void lock() { wr_lock(); } void unlock() { wr_unlock(); } -#endif }; #if defined _WIN32 || defined SUX_LOCK_GENERIC diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc index 339b431522c..05445f1a68c 100644 --- a/storage/innobase/sync/srw_lock.cc +++ b/storage/innobase/sync/srw_lock.cc @@ -139,7 +139,8 @@ static inline void srw_pause(unsigned delay) } #ifdef SUX_LOCK_GENERIC -template<> void srw_mutex_impl::wr_wait() +# ifndef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +template<> void pthread_mutex_wrapper::wr_wait() { const unsigned delay= srw_pause_delay(); @@ -152,203 +153,46 @@ template<> void srw_mutex_impl::wr_wait() pthread_mutex_lock(&lock); } +# endif -template -void ssux_lock_impl::init() -{ - DBUG_ASSERT(!is_locked_or_waiting()); - pthread_mutex_init(&mutex, nullptr); - pthread_cond_init(&cond_shared, nullptr); - pthread_cond_init(&cond_exclusive, nullptr); -} - -template -void ssux_lock_impl::destroy() -{ - DBUG_ASSERT(!is_locked_or_waiting()); - pthread_mutex_destroy(&mutex); - pthread_cond_destroy(&cond_shared); - pthread_cond_destroy(&cond_exclusive); -} +template void ssux_lock_impl::init(); +template void ssux_lock_impl::init(); +template void ssux_lock_impl::destroy(); +template void ssux_lock_impl::destroy(); template -inline void ssux_lock_impl::writer_wait(uint32_t l) +inline void srw_mutex_impl::wait(uint32_t lk) { pthread_mutex_lock(&mutex); - while (value() == l) - pthread_cond_wait(&cond_exclusive, &mutex); + while (lock.load(std::memory_order_relaxed) == lk) + pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); } template -inline void ssux_lock_impl::readers_wait(uint32_t l) +inline void ssux_lock_impl::wait(uint32_t lk) { - pthread_mutex_lock(&mutex); - while (value() == l) - pthread_cond_wait(&cond_shared, &mutex); - pthread_mutex_unlock(&mutex); + pthread_mutex_lock(&writer.mutex); + while (readers.load(std::memory_order_relaxed) == lk) + pthread_cond_wait(&readers_cond, &writer.mutex); + pthread_mutex_unlock(&writer.mutex); } template -inline void ssux_lock_impl::wake() +void srw_mutex_impl::wake() { pthread_mutex_lock(&mutex); - uint32_t l= value(); - if (l & WRITER) - DBUG_ASSERT(!(l & ~WRITER_PENDING)); - else - { - pthread_cond_broadcast(&cond_exclusive); - if (!(l & WRITER_PENDING)) - pthread_cond_broadcast(&cond_shared); - } + pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); } - -/** Wait for a read lock. -@param lock word value from a failed read_trylock() */ template -void ssux_lock_impl::read_lock(uint32_t l) +void ssux_lock_impl::wake() { - do - { - if (l == WRITER_WAITING) - { - wake_writer: - pthread_mutex_lock(&mutex); - for (;;) - { - if (l == WRITER_WAITING) - pthread_cond_signal(&cond_exclusive); - l= value(); - if (!(l & WRITER_PENDING)) - break; - pthread_cond_wait(&cond_shared, &mutex); - } - pthread_mutex_unlock(&mutex); - continue; - } - else if (spinloop) - { - const unsigned delay= srw_pause_delay(); - - for (auto spin= srv_n_spin_wait_rounds; spin; spin--) - { - srw_pause(delay); - if (read_trylock(l)) - return; - else if (l == WRITER_WAITING) - goto wake_writer; - } - } - - readers_wait(l); - } - while (!read_trylock(l)); -} - -/** Wait for an update lock. -@param lock word value from a failed update_trylock() */ -template -void ssux_lock_impl::update_lock(uint32_t l) -{ - do - { - if ((l | UPDATER) == (UPDATER | WRITER_WAITING)) - { - wake_writer: - pthread_mutex_lock(&mutex); - for (;;) - { - if ((l | UPDATER) == (UPDATER | WRITER_WAITING)) - pthread_cond_signal(&cond_exclusive); - l= value(); - if (!(l & WRITER_PENDING)) - break; - pthread_cond_wait(&cond_shared, &mutex); - } - pthread_mutex_unlock(&mutex); - continue; - } - else if (spinloop) - { - const unsigned delay= srw_pause_delay(); - - for (auto spin= srv_n_spin_wait_rounds; spin; spin--) - { - srw_pause(delay); - if (update_trylock(l)) - return; - else if ((l | UPDATER) == (UPDATER | WRITER_WAITING)) - goto wake_writer; - } - } - - readers_wait(l); - } - while (!update_trylock(l)); -} - -/** Wait for a write lock after a failed write_trylock() or upgrade_trylock() -@param holding_u whether we already hold u_lock() */ -template -void ssux_lock_impl::write_lock(bool holding_u) -{ - for (;;) - { - write_lock_wait_start(); - - const uint32_t e= holding_u ? WRITER_WAITING | UPDATER : WRITER_WAITING; - uint32_t l= e; - if (write_lock_wait_try(l)) - return; - - if (!(l & WRITER_WAITING)) - { - switch (l) { - case UNLOCKED: - DBUG_ASSERT(!holding_u); - if (write_trylock()) - return; - break; - case UPDATER: - if (holding_u && upgrade_trylock()) - return; - } - - for (l= write_lock_wait_start_read() | WRITER_WAITING; - (l | WRITER_WAITING) == e; ) - if (write_lock_wait_try(l)) - return; - } - else - DBUG_ASSERT(~WRITER_WAITING & l); - - writer_wait(l); - } + pthread_mutex_lock(&writer.mutex); + pthread_cond_signal(&readers_cond); + pthread_mutex_unlock(&writer.mutex); } - -template -void ssux_lock_impl::rd_unlock() { if (read_unlock()) wake(); } -template -void ssux_lock_impl::u_unlock() { update_unlock(); wake(); } -template -void ssux_lock_impl::wr_unlock() { write_unlock(); wake(); } - -template void ssux_lock_impl::init(); -template void ssux_lock_impl::destroy(); -template void ssux_lock_impl::rd_unlock(); -template void ssux_lock_impl::u_unlock(); -template void ssux_lock_impl::wr_unlock(); -template void ssux_lock_impl::init(); -template void ssux_lock_impl::destroy(); -template void ssux_lock_impl::read_lock(uint32_t); -template void ssux_lock_impl::rd_unlock(); -template void ssux_lock_impl::u_unlock(); -template void ssux_lock_impl::wr_unlock(); -template void ssux_lock_impl::write_lock(bool); -template void ssux_lock_impl::update_lock(uint32_t); -#else /* SUX_LOCK_GENERIC */ +#else static_assert(4 == sizeof(rw_lock), "ABI"); # ifdef _WIN32 # include @@ -401,8 +245,8 @@ inline void ssux_lock_impl::wait(uint32_t lk) { SRW_FUTEX(&readers, WAIT, lk); } template void ssux_lock_impl::wake() { SRW_FUTEX(&readers, WAKE, 1); } - # endif +#endif template void srw_mutex_impl::wake(); template void ssux_lock_impl::wake(); @@ -425,6 +269,8 @@ assembler code or a Microsoft intrinsic function. #if defined __clang_major__ && __clang_major__ < 10 /* Only clang-10 introduced support for asm goto */ +#elif defined __APPLE__ +/* At least some versions of Apple Xcode do not support asm goto */ #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__) # define IF_FETCH_OR_GOTO(mem, bit, label) \ __asm__ goto("lock btsl $" #bit ", %0\n\t" \ @@ -441,32 +287,35 @@ assembler code or a Microsoft intrinsic function. goto label; #endif -template<> -void srw_mutex_impl::wait_and_lock() +template +void srw_mutex_impl::wait_and_lock() { uint32_t lk= 1 + lock.fetch_add(1, std::memory_order_relaxed); - const unsigned delay= srw_pause_delay(); - - for (auto spin= srv_n_spin_wait_rounds;;) + if (spinloop) { - DBUG_ASSERT(~HOLDER & lk); - if (lk & HOLDER) - lk= lock.load(std::memory_order_relaxed); - else + const unsigned delay= srw_pause_delay(); + + for (auto spin= srv_n_spin_wait_rounds;;) { + DBUG_ASSERT(~HOLDER & lk); + if (lk & HOLDER) + lk= lock.load(std::memory_order_relaxed); + else + { #ifdef IF_NOT_FETCH_OR_GOTO - static_assert(HOLDER == (1U << 31), "compatibility"); - IF_NOT_FETCH_OR_GOTO(*this, 31, acquired); - lk|= HOLDER; + static_assert(HOLDER == (1U << 31), "compatibility"); + IF_NOT_FETCH_OR_GOTO(*this, 31, acquired); + lk|= HOLDER; #else - if (!((lk= lock.fetch_or(HOLDER, std::memory_order_relaxed)) & HOLDER)) - goto acquired; + if (!((lk= lock.fetch_or(HOLDER, std::memory_order_relaxed)) & HOLDER)) + goto acquired; #endif - srw_pause(delay); + srw_pause(delay); + } + if (!--spin) + break; } - if (!--spin) - break; } for (;;) @@ -497,35 +346,8 @@ acquired: } } -template<> -void srw_mutex_impl::wait_and_lock() -{ - for (uint32_t lk= 1 + lock.fetch_add(1, std::memory_order_relaxed);;) - { - DBUG_ASSERT(~HOLDER & lk); - if (lk & HOLDER) - { - wait(lk); -#ifdef IF_FETCH_OR_GOTO -reload: -#endif - lk= lock.load(std::memory_order_relaxed); - } - else - { -#ifdef IF_FETCH_OR_GOTO - static_assert(HOLDER == (1U << 31), "compatibility"); - IF_FETCH_OR_GOTO(*this, 31, reload); -#else - if ((lk= lock.fetch_or(HOLDER, std::memory_order_relaxed)) & HOLDER) - continue; - DBUG_ASSERT(lk); -#endif - std::atomic_thread_fence(std::memory_order_acquire); - return; - } - } -} +template void srw_mutex_impl::wait_and_lock(); +template void srw_mutex_impl::wait_and_lock(); template void ssux_lock_impl::wr_wait(uint32_t lk) @@ -577,7 +399,6 @@ void ssux_lock_impl::rd_wait() template void ssux_lock_impl::rd_wait(); template void ssux_lock_impl::rd_wait(); -#endif /* SUX_LOCK_GENERIC */ #if defined _WIN32 || defined SUX_LOCK_GENERIC template<> void srw_lock_::rd_wait() @@ -698,18 +519,6 @@ void ssux_lock::psi_wr_lock(const char *file, unsigned line) void ssux_lock::psi_u_wr_upgrade(const char *file, unsigned line) { PSI_rwlock_locker_state state; -# ifdef SUX_LOCK_GENERIC - const bool nowait= lock.upgrade_trylock(); - if (PSI_rwlock_locker *locker= PSI_RWLOCK_CALL(start_rwlock_wrwait) - (&state, pfs_psi, - nowait ? PSI_RWLOCK_TRYEXCLUSIVELOCK : PSI_RWLOCK_EXCLUSIVELOCK, - file, line)) - { - if (!nowait) - lock.write_lock(true); - PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, 0); - } -# else /* SUX_LOCK_GENERIC */ DBUG_ASSERT(lock.writer.is_locked()); uint32_t lk= 1; const bool nowait= @@ -725,18 +534,12 @@ void ssux_lock::psi_u_wr_upgrade(const char *file, unsigned line) lock.u_wr_upgrade(); PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, 0); } -# endif /* SUX_LOCK_GENERIC */ else if (!nowait) lock.u_wr_upgrade(); } #else /* UNIV_PFS_RWLOCK */ template void ssux_lock_impl::rd_lock(); -# ifdef SUX_LOCK_GENERIC -template void ssux_lock_impl::write_lock(bool); -template void ssux_lock_impl::update_lock(uint32_t); -# else template void ssux_lock_impl::rd_unlock(); template void ssux_lock_impl::u_unlock(); template void ssux_lock_impl::wr_unlock(); -# endif #endif /* UNIV_PFS_RWLOCK */ -- cgit v1.2.1