From e9a33a5392e56360db7d599db976df9f741bf9f5 Mon Sep 17 00:00:00 2001 From: Rasmus Johansson Date: Tue, 19 May 2020 09:10:24 +0000 Subject: [PATCH 01/10] MDEV-22631 some test causes MTR interruption without generating summary and XML --- mysql-test/lib/mtr_report.pm | 4 +++- mysql-test/mysql-test-run.pl | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 0b99eafa4cf..d228e9406e0 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -473,7 +473,7 @@ sub mtr_report_stats ($$$$) { $comment =~ s/[\"]//g; # if a test case has to be retried it should have the result MTR_RES_FAILED in jUnit XML - if ($test->{'result'} eq "MTR_RES_FAILED" || $test->{'retries'}) { + if ($test->{'result'} eq "MTR_RES_FAILED" || $test->{'retries'} > 0) { my $logcontents = $test->{'logfile-failed'} || $test->{'logfile'}; $xml_report .= qq(>\n\t\t\t\n\n\t\t\t\n\t\t\n); @@ -639,6 +639,8 @@ sub mtr_error (@) { } else { + use Carp qw(cluck); + cluck "Error happened" if $verbose > 0; exit(1); } } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 538b76677f4..cd376690461 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -769,8 +769,14 @@ sub run_test_server ($$$) { if ( $result->is_failed() ) { my $worker_logdir= $result->{savedir}; my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log"; - $result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20); - rename $log_file_name,$log_file_name.".failed"; + + if (-e $log_file_name) { + $result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20); + } else { + $result->{'logfile-failed'} = ""; + } + + rename $log_file_name, $log_file_name.".failed"; } delete($result->{result}); $result->{retries}= $retries+1; From 395ed66b3b4e3b6b785e554ab9794161cef029cd Mon Sep 17 00:00:00 2001 From: Rasmus Johansson Date: Tue, 19 May 2020 15:15:52 +0000 Subject: [PATCH 02/10] MDEV-22636 XML output for mtr doesn't work with valgrind option --- mysql-test/mysql-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index cd376690461..e4fa0b5231a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -567,6 +567,7 @@ sub main { # Create minimalistic "test" for the reporting my $tinfo = My::Test->new ( + suite => { name => 'valgrind', }, name => 'valgrind_report', ); # Set dummy worker id to align report with normal tests From 2c4a2f2007a467658996f0f8f03295e415190bf8 Mon Sep 17 00:00:00 2001 From: Rasmus Johansson Date: Tue, 19 May 2020 15:15:52 +0000 Subject: [PATCH 03/10] MDEV-22636 XML output for mtr doesn't work with valgrind option --- mysql-test/mysql-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index fad066c1c0f..dbdf4f7b8d6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -739,6 +739,7 @@ sub main { # Create minimalistic "test" for the reporting my $tinfo = My::Test->new ( + suite => { name => 'valgrind', }, name => 'valgrind_report', ); # Set dummy worker id to align report with normal tests From 7a5ba59e5f55410e563f7b81238597cf63707e63 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Tue, 19 May 2020 21:57:01 +0300 Subject: [PATCH 04/10] MDEV-22472 rpl.rpl_fail_register failed in buildbot with wrong result This is a new test from upstream that did not expect the correct value of the command slot of the Dump thread when the latter gets killed. The test is made to expect "Killed" string as the command in show-processlist as it is supposed to when a thread gets killed. --- mysql-test/suite/rpl/t/rpl_fail_register.test | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_fail_register.test b/mysql-test/suite/rpl/t/rpl_fail_register.test index bfecc9d7f14..3a37cc08f44 100644 --- a/mysql-test/suite/rpl/t/rpl_fail_register.test +++ b/mysql-test/suite/rpl/t/rpl_fail_register.test @@ -17,12 +17,11 @@ set global debug_dbug=@old_dbug; connection master; -### why is that needed? let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`; if ($id) { replace_result $id DUMP_THREAD; eval kill $id; - let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Binlog Dump'; + let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Killed'; source include/wait_condition.inc; } From ad0f85bcd22d28bcf95efd6eed09abbc37f6e2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 19 May 2020 10:10:30 +0300 Subject: [PATCH 05/10] MDEV-18838 : galera.galera_toi_truncate: Test failure: mysqltest: query 'reap' succeeded - should have failed with errno 1213 Test cleanup. --- .../suite/galera/r/galera_toi_truncate.result | 22 +++++++--------- .../suite/galera/t/galera_toi_truncate.test | 26 +++++++------------ 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_toi_truncate.result b/mysql-test/suite/galera/r/galera_toi_truncate.result index 73285d723c1..f299eacda00 100644 --- a/mysql-test/suite/galera/r/galera_toi_truncate.result +++ b/mysql-test/suite/galera/r/galera_toi_truncate.result @@ -1,24 +1,22 @@ connection node_1; -CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; connection node_2; SET SESSION wsrep_retry_autocommit = 0; -INSERT INTO t1(f1) SELECT 1 FROM ten as a1, ten AS a2; -set debug_sync='ha_commit_trans_after_prepare WAIT_FOR go'; -INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;; +INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8; connection node_1; TRUNCATE TABLE t1;; -connection node_1; connection node_2; ERROR 40001: Deadlock: wsrep aborted transaction -connection node_2; -SELECT COUNT(*) = 0 FROM t1; -COUNT(*) = 0 -1 connection node_1; -SELECT COUNT(*) = 0 FROM t1; -COUNT(*) = 0 -1 +connection node_2; +SELECT COUNT(*) AS EXPECT_0 FROM t1; +EXPECT_0 +0 +connection node_1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; +EXPECT_0 +0 DROP TABLE t1; DROP TABLE ten; diff --git a/mysql-test/suite/galera/t/galera_toi_truncate.test b/mysql-test/suite/galera/t/galera_toi_truncate.test index 0c1d0e45e41..30e0e802816 100644 --- a/mysql-test/suite/galera/t/galera_toi_truncate.test +++ b/mysql-test/suite/galera/t/galera_toi_truncate.test @@ -4,50 +4,42 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc --source include/have_debug_sync.inc ---source include/not_embedded.inc +--source include/have_debug.inc # # INSERT and TRUNCATE on different nodes # --connection node_1 -CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -# Insert 1m rows --connection node_2 --let $wait_condition = SELECT COUNT(*) = 10 FROM ten; --source include/wait_condition.inc # Prevent autocommit retring from masking the deadlock error we expect to get SET SESSION wsrep_retry_autocommit = 0; -INSERT INTO t1(f1) SELECT 1 FROM ten as a1, ten AS a2; - -set debug_sync='ha_commit_trans_after_prepare WAIT_FOR go'; ---send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6; +--send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8 --connection node_1 -# Wait for a above insert to start ---let $wait_condition = SELECT COUNT(*) >= 100 from t1; ---source include/wait_condition.inc - --send TRUNCATE TABLE t1; ---connection node_1 ---reap - --connection node_2 --error ER_LOCK_DEADLOCK --reap +--connection node_1 +--reap + --connection node_2 -SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; --connection node_1 -SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; + DROP TABLE t1; DROP TABLE ten; From dd95935e5bbf8811a91b21cd1bbc9b5941f24034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 20 May 2020 09:26:05 +0300 Subject: [PATCH 06/10] MDEV-22456 post-fix: Remove unused variable --- storage/innobase/fsp/fsp0fsp.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 974a514e637..06f66e88e56 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -3170,10 +3170,7 @@ fseg_free_extent( ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); ut_d(space->modify_check(*mtr)); - -#if defined BTR_CUR_HASH_ADAPT || defined UNIV_DEBUG - const ulint first_page_in_extent = page - (page % FSP_EXTENT_SIZE); -#endif /* BTR_CUR_HASH_ADAPT || UNIV_DEBUG */ + ut_d(ulint first_page_in_extent = page - (page % FSP_EXTENT_SIZE)); if (xdes_is_full(descr, mtr)) { flst_remove(seg_inode + FSEG_FULL, From d2900d917f1f3e98c87d21f35a5ea12cd0fa2c05 Mon Sep 17 00:00:00 2001 From: Yury Kurlykov Date: Wed, 20 May 2020 17:10:07 +1000 Subject: [PATCH 07/10] MDEV-22629 Remove fts_indexes field from struct fts_update_t (#1537) fts_indexes field in fts_update_t never used. So replace fts_update_t with doc_id_t in the code --- storage/innobase/fts/fts0fts.cc | 28 +++++++++--------- storage/innobase/fts/fts0opt.cc | 41 +++++++++++++-------------- storage/innobase/fts/fts0que.cc | 24 ++++++++-------- storage/innobase/include/fts0priv.h | 2 +- storage/innobase/include/fts0types.h | 21 ++------------ storage/innobase/include/fts0types.ic | 11 ++++--- 6 files changed, 55 insertions(+), 72 deletions(-) diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 52ea3e11609..2706c59495b 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -584,7 +584,7 @@ fts_cache_init( mutex_enter((ib_mutex_t*) &cache->deleted_lock); cache->deleted_doc_ids = ib_vector_create( - cache->sync_heap, sizeof(fts_update_t), 4); + cache->sync_heap, sizeof(doc_id_t), 4); mutex_exit((ib_mutex_t*) &cache->deleted_lock); /* Reset the cache data for all the FTS indexes. */ @@ -2637,11 +2637,11 @@ dberr_t fts_cmp_set_sync_doc_id( /*====================*/ const dict_table_t* table, /*!< in: table */ - doc_id_t doc_id_cmp, /*!< in: Doc ID to compare */ + doc_id_t cmp_doc_id, /*!< in: Doc ID to compare */ ibool read_only, /*!< in: TRUE if read the synced_doc_id only */ doc_id_t* doc_id) /*!< out: larger document id - after comparing "doc_id_cmp" + after comparing "cmp_doc_id" to the one stored in CONFIG table */ { @@ -2712,10 +2712,10 @@ retry: goto func_exit; } - if (doc_id_cmp == 0 && *doc_id) { + if (cmp_doc_id == 0 && *doc_id) { cache->synced_doc_id = *doc_id - 1; } else { - cache->synced_doc_id = ut_max(doc_id_cmp, *doc_id); + cache->synced_doc_id = ut_max(cmp_doc_id, *doc_id); } mutex_enter(&cache->doc_id_lock); @@ -2726,7 +2726,7 @@ retry: } mutex_exit(&cache->doc_id_lock); - if (doc_id_cmp > *doc_id) { + if (cmp_doc_id > *doc_id) { error = fts_update_sync_doc_id( table, cache->synced_doc_id, trx); } @@ -2848,7 +2848,7 @@ fts_doc_ids_create(void) fts_doc_ids->self_heap = ib_heap_allocator_create(heap); fts_doc_ids->doc_ids = static_cast(ib_vector_create( - fts_doc_ids->self_heap, sizeof(fts_update_t), 32)); + fts_doc_ids->self_heap, sizeof(doc_id_t), 32)); return(fts_doc_ids); } @@ -3943,7 +3943,7 @@ fts_sync_add_deleted_cache( ut_a(ib_vector_size(doc_ids) > 0); - ib_vector_sort(doc_ids, fts_update_doc_id_cmp); + ib_vector_sort(doc_ids, fts_doc_id_cmp); info = pars_info_create(); @@ -3961,13 +3961,13 @@ fts_sync_add_deleted_cache( "BEGIN INSERT INTO $table_name VALUES (:doc_id);"); for (i = 0; i < n_elems && error == DB_SUCCESS; ++i) { - fts_update_t* update; + doc_id_t* update; doc_id_t write_doc_id; - update = static_cast(ib_vector_get(doc_ids, i)); + update = static_cast(ib_vector_get(doc_ids, i)); /* Convert to "storage" byte order. */ - fts_write_doc_id((byte*) &write_doc_id, update->doc_id); + fts_write_doc_id((byte*) &write_doc_id, *update); fts_bind_doc_id(info, "doc_id", &write_doc_id); error = fts_eval_sql(sync->trx, graph); @@ -5292,12 +5292,12 @@ fts_cache_append_deleted_doc_ids( for (ulint i = 0; i < ib_vector_size(cache->deleted_doc_ids); ++i) { - fts_update_t* update; + doc_id_t* update; - update = static_cast( + update = static_cast( ib_vector_get(cache->deleted_doc_ids, i)); - ib_vector_push(vector, &update->doc_id); + ib_vector_push(vector, &update); } mutex_exit((ib_mutex_t*) &cache->deleted_lock); diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index deda14fee24..39a7b086e34 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, 2019, MariaDB Corporation. +Copyright (c) 2016, 2020, 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 @@ -920,7 +920,7 @@ fts_fetch_doc_ids( int i = 0; sel_node_t* sel_node = static_cast(row); fts_doc_ids_t* fts_doc_ids = static_cast(user_arg); - fts_update_t* update = static_cast( + doc_id_t* update = static_cast( ib_vector_push(fts_doc_ids->doc_ids, NULL)); for (exp = sel_node->select_list; @@ -936,8 +936,7 @@ fts_fetch_doc_ids( /* Note: The column numbers below must match the SELECT. */ switch (i) { case 0: /* DOC_ID */ - update->fts_indexes = NULL; - update->doc_id = fts_read_doc_id( + *update = fts_read_doc_id( static_cast(data)); break; @@ -1005,7 +1004,7 @@ fts_table_fetch_doc_ids( mutex_exit(&dict_sys->mutex); if (error == DB_SUCCESS) { - ib_vector_sort(doc_ids->doc_ids, fts_update_doc_id_cmp); + ib_vector_sort(doc_ids->doc_ids, fts_doc_id_cmp); } if (alloc_bk_trx) { @@ -1022,7 +1021,7 @@ Do a binary search for a doc id in the array int fts_bsearch( /*========*/ - fts_update_t* array, /*!< in: array to sort */ + doc_id_t* array, /*!< in: array to sort */ int lower, /*!< in: the array lower bound */ int upper, /*!< in: the array upper bound */ doc_id_t doc_id) /*!< in: the doc id to search for */ @@ -1036,9 +1035,9 @@ fts_bsearch( while (lower < upper) { int i = (lower + upper) >> 1; - if (doc_id > array[i].doc_id) { + if (doc_id > array[i]) { lower = i + 1; - } else if (doc_id < array[i].doc_id) { + } else if (doc_id < array[i]) { upper = i - 1; } else { return(i); /* Found. */ @@ -1047,7 +1046,7 @@ fts_bsearch( } if (lower == upper && lower < orig_size) { - if (doc_id == array[lower].doc_id) { + if (doc_id == array[lower]) { return(lower); } else if (lower == 0) { return(-1); @@ -1074,7 +1073,7 @@ fts_optimize_lookup( { int pos; int upper = static_cast(ib_vector_size(doc_ids)); - fts_update_t* array = (fts_update_t*) doc_ids->data; + doc_id_t* array = (doc_id_t*) doc_ids->data; pos = fts_bsearch(array, static_cast(lower), upper, first_doc_id); @@ -1087,10 +1086,10 @@ fts_optimize_lookup( /* If i is 1, it could be first_doc_id is less than either the first or second array item, do a double check */ - if (i == 1 && array[0].doc_id <= last_doc_id - && first_doc_id < array[0].doc_id) { + if (i == 1 && array[0] <= last_doc_id + && first_doc_id < array[0]) { pos = 0; - } else if (i < upper && array[i].doc_id <= last_doc_id) { + } else if (i < upper && array[i] <= last_doc_id) { /* Check if the "next" doc id is within the first & last doc id of the node. */ @@ -1229,12 +1228,12 @@ test_again: delta for decoding the entries following this document's entries. */ if (*del_pos >= 0 && *del_pos < (int) ib_vector_size(del_vec)) { - fts_update_t* update; + doc_id_t* update; - update = (fts_update_t*) ib_vector_get( + update = (doc_id_t*) ib_vector_get( del_vec, *del_pos); - del_doc_id = update->doc_id; + del_doc_id = *update; } if (enc->src_ilist_ptr == src_node->ilist && doc_id == 0) { @@ -2020,7 +2019,7 @@ fts_optimize_purge_deleted_doc_ids( ulint i; pars_info_t* info; que_t* graph; - fts_update_t* update; + doc_id_t* update; doc_id_t write_doc_id; dberr_t error = DB_SUCCESS; char deleted[MAX_FULL_NAME_LEN]; @@ -2030,11 +2029,11 @@ fts_optimize_purge_deleted_doc_ids( ut_a(ib_vector_size(optim->to_delete->doc_ids) > 0); - update = static_cast( + update = static_cast( ib_vector_get(optim->to_delete->doc_ids, 0)); /* Convert to "storage" byte order. */ - fts_write_doc_id((byte*) &write_doc_id, update->doc_id); + fts_write_doc_id((byte*) &write_doc_id, *update); /* This is required for the SQL parser to work. It must be able to find the following variables. So we do it twice. */ @@ -2056,11 +2055,11 @@ fts_optimize_purge_deleted_doc_ids( /* Delete the doc ids that were copied at the start. */ for (i = 0; i < ib_vector_size(optim->to_delete->doc_ids); ++i) { - update = static_cast(ib_vector_get( + update = static_cast(ib_vector_get( optim->to_delete->doc_ids, i)); /* Convert to "storage" byte order. */ - fts_write_doc_id((byte*) &write_doc_id, update->doc_id); + fts_write_doc_id((byte*) &write_doc_id, *update); fts_bind_doc_id(info, "doc_id1", &write_doc_id); diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 6baec777270..57ab4c4379f 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -730,10 +730,10 @@ fts_query_union_doc_id( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; /* Check if the doc id is deleted and it's not already in our set. */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0 + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0 && rbt_search(query->doc_ids, &parent, &doc_id) != 0) { fts_ranking_t ranking; @@ -761,10 +761,10 @@ fts_query_remove_doc_id( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; /* Check if the doc id is deleted and it's in our set. */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0 + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0 && rbt_search(query->doc_ids, &parent, &doc_id) == 0) { ut_free(rbt_remove_node(query->doc_ids, parent.last)); @@ -791,10 +791,10 @@ fts_query_change_ranking( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; /* Check if the doc id is deleted and it's in our set. */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0 + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0 && rbt_search(query->doc_ids, &parent, &doc_id) == 0) { fts_ranking_t* ranking; @@ -828,7 +828,7 @@ fts_query_intersect_doc_id( { ib_rbt_bound_t parent; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data; fts_ranking_t* ranking= NULL; /* There are three types of intersect: @@ -840,7 +840,7 @@ fts_query_intersect_doc_id( if it matches 'b' and it's in doc_ids.(multi_exist = true). */ /* Check if the doc id is deleted and it's in our set */ - if (fts_bsearch(array, 0, static_cast(size), doc_id) < 0) { + if (fts_bsearch(updates, 0, static_cast(size), doc_id) < 0) { fts_ranking_t new_ranking; if (rbt_search(query->doc_ids, &parent, &doc_id) != 0) { @@ -3649,8 +3649,8 @@ fts_query_prepare_result( if (query->flags == FTS_OPT_RANKING) { fts_word_freq_t* word_freq; ulint size = ib_vector_size(query->deleted->doc_ids); - fts_update_t* array = - (fts_update_t*) query->deleted->doc_ids->data; + doc_id_t* updates = + (doc_id_t*) query->deleted->doc_ids->data; node = rbt_first(query->word_freqs); ut_ad(node); @@ -3665,7 +3665,7 @@ fts_query_prepare_result( doc_freq = rbt_value(fts_doc_freq_t, node); /* Don't put deleted docs into result */ - if (fts_bsearch(array, 0, static_cast(size), + if (fts_bsearch(updates, 0, static_cast(size), doc_freq->doc_id) >= 0) { /* one less matching doc count */ --word_freq->doc_count; @@ -4016,7 +4016,7 @@ fts_query( DEBUG_SYNC_C("fts_deleted_doc_ids_append"); /* Sort the vector so that we can do a binary search over the ids. */ - ib_vector_sort(query.deleted->doc_ids, fts_update_doc_id_cmp); + ib_vector_sort(query.deleted->doc_ids, fts_doc_id_cmp); /* Convert the query string to lower case before parsing. We own the ut_malloc'ed result and so remember to free it before return. */ diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h index dd724aa12d4..4c8746c053f 100644 --- a/storage/innobase/include/fts0priv.h +++ b/storage/innobase/include/fts0priv.h @@ -239,7 +239,7 @@ Do a binary search for a doc id in the array int fts_bsearch( /*========*/ - fts_update_t* array, /*!< in: array to sort */ + doc_id_t* array, /*!< in: array to sort */ int lower, /*!< in: lower bound of array*/ int upper, /*!< in: upper bound of array*/ doc_id_t doc_id) /*!< in: doc id to lookup */ diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h index a08a60b9e95..44c3ab77695 100644 --- a/storage/innobase/include/fts0types.h +++ b/storage/innobase/include/fts0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -80,20 +80,6 @@ struct fts_index_cache_t { CHARSET_INFO* charset; /*!< charset */ }; -/** For supporting the tracking of updates on multiple FTS indexes we need -to track which FTS indexes need to be updated. For INSERT and DELETE we -update all fts indexes. */ -struct fts_update_t { - doc_id_t doc_id; /*!< The doc id affected */ - - ib_vector_t* fts_indexes; /*!< The FTS indexes that need to be - updated. A NULL value means all - indexes need to be updated. This - vector is not allocated on the heap - and so must be freed explicitly, - when we are done with it */ -}; - /** Stop word control infotmation. */ struct fts_stopword_t { ulint status; /*!< Status of the stopword tree */ @@ -319,10 +305,9 @@ fts_ranking_doc_id_cmp( const void* p2); /*!< in: id2 */ /******************************************************************//** -Compare two fts_update_t instances doc_ids. */ +Compare two doc_ids. */ UNIV_INLINE -int -fts_update_doc_id_cmp( +int fts_doc_id_cmp( /*==================*/ /*!< out: < 0 if n1 < n2, diff --git a/storage/innobase/include/fts0types.ic b/storage/innobase/include/fts0types.ic index e388d6257f6..cf5cf35c48e 100644 --- a/storage/innobase/include/fts0types.ic +++ b/storage/innobase/include/fts0types.ic @@ -79,19 +79,18 @@ fts_ranking_doc_id_cmp( } /******************************************************************//** -Compare two fts_update_t doc_ids. +Compare two doc_ids. @return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ UNIV_INLINE -int -fts_update_doc_id_cmp( +int fts_doc_id_cmp( /*==================*/ const void* p1, /*!< in: id1 */ const void* p2) /*!< in: id2 */ { - const fts_update_t* up1 = (const fts_update_t*) p1; - const fts_update_t* up2 = (const fts_update_t*) p2; + const doc_id_t* up1 = static_cast(p1); + const doc_id_t* up2 = static_cast(p2); - return((int)(up1->doc_id - up2->doc_id)); + return static_cast(*up1 - *up2); } /******************************************************************//** From 6b2c8cac1b52bee934ac88cc21c6023f48b69e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 20 May 2020 10:33:53 +0300 Subject: [PATCH 08/10] MDEV-22258 Limit innodb_encryption_threads to 255 For no good reason, innodb_encryption_threads was limited to 4,294,967,295. Expectedly, the server would crash if such an insane value was specified. Let us limit the maximum to 255. The encryption threads are not doing much useful work. They are basically only dirtying pages by performing dummy writes via the redo log. The encryption key rotation or the in-place addition or removal of encryption will take place in the page cleaner. In a quick test on a 20-core CPU (40 threads in total), the sweet spot on an otherwise idle server seemed to be innodb_encryption_threads=16 for the test encryption.encrypt_and_grep. The new limit 255 should be more than enough for even bigger servers. --- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/xtradb/handler/ha_innodb.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 38bafc03d6f..7019dda908b 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -826,7 +826,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Number of threads performing background key rotation and scrubbing NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 4294967295 +NUMERIC_MAX_VALUE 255 NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a06a9ed103f..2dd20927545 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19919,7 +19919,7 @@ static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads, "scrubbing", NULL, innodb_encryption_threads_update, - srv_n_fil_crypt_threads, 0, UINT_MAX32, 0); + 0, 0, 255, 0); static MYSQL_SYSVAR_UINT(encryption_rotate_key_age, srv_fil_crypt_rotate_key_age, diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 06f0388349e..0a77ce56eaf 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -21198,7 +21198,7 @@ static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads, "scrubbing", NULL, innodb_encryption_threads_update, - srv_n_fil_crypt_threads, 0, UINT_MAX32, 0); + 0, 0, 255, 0); static MYSQL_SYSVAR_UINT(encryption_rotate_key_age, srv_fil_crypt_rotate_key_age, From d4f97e2086848cedfdd35a6c1cf286f8dad26c5c Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 20 May 2020 11:53:09 +0400 Subject: [PATCH 09/10] MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query Problem: When handling a query like this: VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin; Type_handler_string_result::Item_hybrid_func_fix_attributes() tried to apply character set conversion Item_type_holder, which causes a crash on DBUG_ASSERT(0) inside Item_type_holder::val_str(). Fix: Overriding Item_type_holder's methods to avoid this, as follows: bool const_item() const { return false; } bool is_expensive() { return true; } --- mysql-test/main/ctype_utf16.result | 25 +++++++++++++++++++++++++ mysql-test/main/ctype_utf16.test | 21 +++++++++++++++++++++ mysql-test/main/ctype_utf8.result | 12 ++++++++++++ mysql-test/main/ctype_utf8.test | 7 +++++++ sql/item.h | 17 +++++++++++++++++ 5 files changed, 82 insertions(+) diff --git a/mysql-test/main/ctype_utf16.result b/mysql-test/main/ctype_utf16.result index 371ccc01a22..70f24491404 100644 --- a/mysql-test/main/ctype_utf16.result +++ b/mysql-test/main/ctype_utf16.result @@ -2814,3 +2814,28 @@ SET STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.3 tests +# +# +# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +# +SET NAMES utf8; +CREATE TABLE t1 (a TEXT CHARACTER SET utf16); +SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t; +1 +1 +DROP TABLE t1; +VALUES (1) UNION SELECT _utf16 0x0020; +1 +1 + +VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin; + + +VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin); + + +# +# End of 10.3 tests +# diff --git a/mysql-test/main/ctype_utf16.test b/mysql-test/main/ctype_utf16.test index 0e497b7b7bd..536a63ceeb4 100644 --- a/mysql-test/main/ctype_utf16.test +++ b/mysql-test/main/ctype_utf16.test @@ -934,3 +934,24 @@ let $coll_pad='utf16_bin'; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # Start of 10.3 tests +--echo # + +--echo # +--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +--echo # + +SET NAMES utf8; +CREATE TABLE t1 (a TEXT CHARACTER SET utf16); +SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t; +DROP TABLE t1; +VALUES (1) UNION SELECT _utf16 0x0020; +VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin; +VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin); + + +--echo # +--echo # End of 10.3 tests +--echo # diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result index f6fa2697241..10996329f24 100644 --- a/mysql-test/main/ctype_utf8.result +++ b/mysql-test/main/ctype_utf8.result @@ -11321,5 +11321,17 @@ SELECT x AS 5天内最近一次登录时间 FROM t1; 1 DROP TABLE t1; # +# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +# +SET NAMES utf8; +VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin; +_latin1 0xDF +ß +a +VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin); +_latin1 0xDF +ß +a +# # End of 10.3 tests # diff --git a/mysql-test/main/ctype_utf8.test b/mysql-test/main/ctype_utf8.test index 26fc491c568..1d244cf0096 100644 --- a/mysql-test/main/ctype_utf8.test +++ b/mysql-test/main/ctype_utf8.test @@ -2256,6 +2256,13 @@ INSERT INTO t1 VALUES (1); SELECT x AS 5天内最近一次登录时间 FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query +--echo # + +SET NAMES utf8; +VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin; +VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin); --echo # --echo # End of 10.3 tests diff --git a/sql/item.h b/sql/item.h index 39451d2631a..769e6b80ca9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -6602,6 +6602,23 @@ public: enum Type type() const { return TYPE_HOLDER; } TYPELIB *get_typelib() const { return enum_set_typelib; } + /* + When handling a query like this: + VALUES ('') UNION VALUES( _utf16 0x0020 COLLATE utf16_bin); + Item_type_holder can be passed to + Type_handler_xxx::Item_hybrid_func_fix_attributes() + We don't want the latter to perform character set conversion of a + Item_type_holder by calling its val_str(), which calls DBUG_ASSERT(0). + Let's override const_item() and is_expensive() to avoid this. + Note, Item_hybrid_func_fix_attributes() could probably + have a new argument to distinguish what we need: + - (a) aggregate data type attributes only + - (b) install converters after attribute aggregation + So st_select_lex_unit::join_union_type_attributes() could + ask it to do (a) only, without (b). + */ + bool const_item() const { return false; } + bool is_expensive() { return true; } double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); From 1893a1370d744408a16548196a6dc62136157399 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 20 May 2020 13:34:45 +0530 Subject: [PATCH 10/10] MDEV-22633 Assertion failed in prepare_inplace_alter_table_dict prepare_inplace_alter_table_dict(): In the error handling, relax a debug assertion for the case that we did not execute dict_stats_wait_bg_to_stop_using_table() yet. --- storage/innobase/handler/handler0alter.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 9afbcf4d1f4..d347d0e51a4 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4404,6 +4404,7 @@ prepare_inplace_alter_table_dict( create_table_info_t info(ctx->prebuilt->trx->mysql_thd, altered_table, ha_alter_info->create_info, NULL, NULL, srv_file_per_table); + ut_d(bool stats_wait = false); if (num_fts_index > 1) { my_error(ER_INNODB_FT_LIMIT, MYF(0)); @@ -4477,6 +4478,7 @@ prepare_inplace_alter_table_dict( XXX what may happen if bg stats opens the table after we have unlocked data dictionary below? */ dict_stats_wait_bg_to_stop_using_table(user_table, ctx->trx); + ut_d(stats_wait = true); online_retry_drop_indexes_low(ctx->new_table, ctx->trx); @@ -5116,7 +5118,8 @@ error_handled: /* n_ref_count must be 1, because purge cannot be executing on this very table as we are holding dict_operation_lock X-latch. */ - DBUG_ASSERT(user_table->get_ref_count() == 1 || ctx->online); + ut_ad(!stats_wait || ctx->online + || user_table->get_ref_count() == 1); online_retry_drop_indexes_with_trx(user_table, ctx->trx); } else {