From 94e3f02db741e4a35f3aba22c258e20fe9617d75 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 24 Aug 2022 11:07:09 -0700 Subject: [PATCH 1/5] MDEV-29350 Crash when IN predicand is used in eliminated GROUP BY clause This bug affected some queries with an IN/ALL/ANY predicand or an EXISTS predicate whose subquery contained a GROUP BY clause that could be eliminated. If this clause used a IN/ALL/ANY predicand whose left operand was a single-value subquery then execution of the query caused a crash of the server after invokation of remove_redundant_subquery_clauses(). The crash was caused by an attempt to exclude the unit for the single-value subquery from the query tree for the second time by the function Item_subselect::eliminate_subselect_processor(). This bug had been masked by the bug MDEV-28617 until a fix for the latter that properly excluded units was pushed into 10.3. Approved by Oleksandr Byelkin --- mysql-test/main/subselect4.result | 116 ++++++++++++++++++++++++++++++ mysql-test/main/subselect4.test | 74 +++++++++++++++++++ sql/item_subselect.cc | 3 +- 3 files changed, 192 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index c374040e9e8..c794aade773 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -3038,4 +3038,120 @@ a 3 2 drop table t1,t2,t3; +# +# MDEV-29139: Redundant IN/ALL/ANY predicand in GROUP BY clause of +# IN/ALL/ANY/EXISTS subquery +# +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create table t4 (d int); +insert into t1 values (3), (1); +insert into t2 values (3), (2); +insert into t3 values (4), (2); +insert into t4 values (1), (7); +explain extended select b from t2 +where exists (select c from t3 +group by (select a from t1 where a = 1) in (select d from t4)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` where 1 +select b from t2 +where exists (select c from t3 +group by (select a from t1 where a = 1) in (select d from t4)); +b +3 +2 +prepare stmt from "select b from t2 +where exists (select c from t3 +group by (select a from t1 where a = 1) in (select d from t4))"; +execute stmt; +b +3 +2 +execute stmt; +b +3 +2 +deallocate prepare stmt; +explain extended select b from t2 +where exists (select c from t3 +group by (select a from t1 where a = 1) >= +any (select d from t4)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` where 1 +select b from t2 +where exists (select c from t3 +group by (select a from t1 where a = 1) >= +any (select d from t4)); +b +3 +2 +explain extended select b from t2 +where exists (select c from t3 +group by (select a from t1 where a = 1) < +all (select d from t4)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` where 1 +select b from t2 +where exists (select c from t3 +group by (select a from t1 where a = 1) < +all (select d from t4)); +b +3 +2 +explain extended select b from t2 +where b in (select c from t3 +group by (select a from t1 where a = 1) in (select d from t4)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 +1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select `test`.`t2`.`b` AS `b` from `test`.`t2` semi join (`test`.`t3`) where 1 +select b from t2 +where b in (select c from t3 +group by (select a from t1 where a = 1) in (select d from t4)); +b +2 +explain extended select b from t2 +where b >= any (select c from t3 +group by (select a from t1 where a = 1) in +(select d from t4)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where +2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` where ((`test`.`t2`.`b`,(/* select#2 */ select min(`test`.`t3`.`c`) from `test`.`t3`) <= (`test`.`t2`.`b`))) +select b from t2 +where b >= any (select c from t3 +group by (select a from t1 where a = 1) in +(select d from t4)); +b +3 +2 +explain extended select b from t2 +where b <= all (select c from t3 +group by (select a from t1 where a = 1) in +(select d from t4)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where +2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` where ((`test`.`t2`.`b`,(/* select#2 */ select `test`.`t3`.`c` from `test`.`t3`) < (`test`.`t2`.`b`))) +select b from t2 +where b <= all (select c from t3 +group by (select a from t1 where a = 1) in +(select d from t4)); +b +2 +drop table t1,t2,t3,t4; # End of 10.3 tests diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test index 2faede5c27e..6aedabcd3f5 100644 --- a/mysql-test/main/subselect4.test +++ b/mysql-test/main/subselect4.test @@ -2477,4 +2477,78 @@ eval $q3; drop table t1,t2,t3; +--echo # +--echo # MDEV-29139: Redundant IN/ALL/ANY predicand in GROUP BY clause of +--echo # IN/ALL/ANY/EXISTS subquery +--echo # + +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create table t4 (d int); + +insert into t1 values (3), (1); +insert into t2 values (3), (2); +insert into t3 values (4), (2); +insert into t4 values (1), (7); + +let $q1= +select b from t2 + where exists (select c from t3 + group by (select a from t1 where a = 1) in (select d from t4)); + +eval explain extended $q1; +eval $q1; + +eval prepare stmt from "$q1"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +let $q2= +select b from t2 + where exists (select c from t3 + group by (select a from t1 where a = 1) >= + any (select d from t4)); + +eval explain extended $q2; +eval $q2; + +let $q3= +select b from t2 + where exists (select c from t3 + group by (select a from t1 where a = 1) < + all (select d from t4)); + +eval explain extended $q3; +eval $q3; + +let $q4= +select b from t2 + where b in (select c from t3 + group by (select a from t1 where a = 1) in (select d from t4)); + +eval explain extended $q4; +eval $q4; + +let $q5= +select b from t2 + where b >= any (select c from t3 + group by (select a from t1 where a = 1) in + (select d from t4)); + +eval explain extended $q5; +eval $q5; + +let $q6= +select b from t2 + where b <= all (select c from t3 + group by (select a from t1 where a = 1) in + (select d from t4)); + +eval explain extended $q6; +eval $q6; + +drop table t1,t2,t3,t4; + --echo # End of 10.3 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 2e33a71b8f9..ee36ee2fae9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -379,7 +379,8 @@ bool Item_subselect::mark_as_eliminated_processor(void *arg) bool Item_subselect::eliminate_subselect_processor(void *arg) { unit->item= NULL; - unit->exclude(); + if (!unit->is_excluded()) + unit->exclude(); eliminated= TRUE; return FALSE; } From 0d1de5e1d19f1e96058ab5948e184f22e7bdd908 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 28 Aug 2022 21:23:28 +0300 Subject: [PATCH 2/5] MDEV-29403 innodb.innodb_sys_semaphore_waits fails with wrong errno 5014 take into account C/C specific CR_ERR_NET_WRITE error --- mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test index a0b9fc626f3..29ff3f69ed7 100644 --- a/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test +++ b/mysql-test/suite/innodb/t/innodb_sys_semaphore_waits.test @@ -78,10 +78,10 @@ let $counter= 80; let $mysql_errno= 0; while (!$mysql_errno) { - --error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,2002,2006,2013 + --error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,2002,2006,2013,5014 show status; - --error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,2002,2006,2013 + --error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,2002,2006,2013,5014 select * from information_schema.innodb_sys_semaphore_waits; dec $counter; From b260903832456dcad882e01a10cdcd48dfd2b0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 30 Aug 2022 10:59:31 +0300 Subject: [PATCH 3/5] MDEV-29258 Failing assertion for name length on RENAME TABLE trx_undo_page_report_rename(): Use the correct maximum length of a table name. Both the database name and the table name can be up to NAME_CHAR_LEN (64 characters) times 5 bytes per character in the my_charset_filename encoding. They are not encoded in UTF-8! fil_op_write_log(): Reserve the correct amount of log buffer for a rename operation. The file name will be appended by mlog_catenate_string(). rename_file_ext(): Reserve a large enough buffer for the file names. --- .../innodb/r/foreign_key_not_windows.result | 9 ++++++++- .../suite/innodb/t/foreign_key_not_windows.test | 17 ++++++++++++++++- sql/table.cc | 5 +++-- storage/innobase/fil/fil0fil.cc | 2 +- storage/innobase/trx/trx0rec.cc | 6 +++--- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key_not_windows.result b/mysql-test/suite/innodb/r/foreign_key_not_windows.result index 764ba911214..0dcc3d46bb1 100644 --- a/mysql-test/suite/innodb/r/foreign_key_not_windows.result +++ b/mysql-test/suite/innodb/r/foreign_key_not_windows.result @@ -11,6 +11,13 @@ CREATE TABLE `d255`.`_##################################################` ERROR HY000: Long database name and identifier for object resulted in path length exceeding 512 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023/_@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023 CREATE TABLE `d255`.`##################################################` (a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB; +# +# MDEV-29258 Failing assertion for name length on RENAME TABLE +# +CREATE TABLE `d255`.`d245` (x INT) ENGINE=InnoDB; +DROP TABLE `d255`.`d250`; +RENAME TABLE `d250#`.`d245` TO `d250#`.`d250`; +RENAME TABLE `d255`.`d250` TO a; DROP DATABASE `d255`; -DROP TABLE t; +DROP TABLE a,t; # End of 10.3 tests diff --git a/mysql-test/suite/innodb/t/foreign_key_not_windows.test b/mysql-test/suite/innodb/t/foreign_key_not_windows.test index 7ad3723d5de..0e1e25d64b3 100644 --- a/mysql-test/suite/innodb/t/foreign_key_not_windows.test +++ b/mysql-test/suite/innodb/t/foreign_key_not_windows.test @@ -38,8 +38,23 @@ eval CREATE TABLE `$d255`.`_$d250` --replace_result $d255 d255 eval CREATE TABLE `$d255`.`$d250` (a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB; + +--echo # +--echo # MDEV-29258 Failing assertion for name length on RENAME TABLE +--echo # + +let $d245=-------------------------------------------------; +--replace_result $d245 d245 $d255 d255 +eval CREATE TABLE `$d255`.`$d245` (x INT) ENGINE=InnoDB; +--replace_result $d250 d250 $d255 d255 +eval DROP TABLE `$d255`.`$d250`; + +--replace_result $d245 d245 $d250 d250 d255 d255 +eval RENAME TABLE `$d255`.`$d245` TO `$d255`.`$d250`; +--replace_result $d250 d250 $d255 d255 +eval RENAME TABLE `$d255`.`$d250` TO a; --replace_result $d255 d255 eval DROP DATABASE `$d255`; -DROP TABLE t; +DROP TABLE a,t; --echo # End of 10.3 tests diff --git a/sql/table.cc b/sql/table.cc index 64fb3150a39..506195127b2 100644 --- a/sql/table.cc +++ b/sql/table.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 @@ -4197,7 +4197,8 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) int rename_file_ext(const char * from,const char * to,const char * ext) { - char from_b[FN_REFLEN],to_b[FN_REFLEN]; + /* Reserve space for ./databasename/tablename.frm + NUL byte */ + char from_b[2 + FN_REFLEN + 4 + 1], to_b[2 + FN_REFLEN + 4 + 1]; (void) strxmov(from_b,from,ext,NullS); (void) strxmov(to_b,to,ext,NullS); return mysql_file_rename(key_file_frm, from_b, to_b, MYF(0)); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a196303c39f..5d9f80eda70 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -2105,7 +2105,7 @@ fil_op_write_log( case MLOG_FILE_RENAME2: ut_ad(strchr(new_path, OS_PATH_SEPARATOR) != NULL); len = strlen(new_path) + 1; - log_ptr = mlog_open(mtr, 2 + len); + log_ptr = mlog_open(mtr, 2); ut_a(log_ptr); mach_write_to_2(log_ptr, len); log_ptr += 2; diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index e011b3f5d8e..d7ec2a38f19 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2019, 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 @@ -1867,9 +1867,9 @@ trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table, byte* start = block->frame + first_free; size_t len = strlen(table->name.m_name); const size_t fixed = 2 + 1 + 11 + 11 + 2; - ut_ad(len <= NAME_LEN * 2 + 1); + ut_ad(len <= NAME_CHAR_LEN * 5 * 2 + 1); /* The -10 is used in trx_undo_left() */ - compile_time_assert((NAME_LEN * 1) * 2 + fixed + compile_time_assert(NAME_CHAR_LEN * 5 * 2 + fixed + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE < UNIV_PAGE_SIZE_MIN - 10 - FIL_PAGE_DATA_END); From 422f3204efbbb27be9ad95355f69636114e7f907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 30 Aug 2022 12:02:56 +0300 Subject: [PATCH 4/5] MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLE dict_table_rename_in_cache(), dict_table_get_highest_foreign_id(): Reserve sufficient space for the fkid[] buffer, and ensure that the fkid[] will be NUL-terminated. The fkid[] must accommodate both the database name (which is already encoded in my_charset_filename) and the constraint name (which must be converted to my_charset_filename) so that we can check if it is in the format databasename/tablename_ibfk_1 (all encoded in my_charset_filename). --- .../innodb/r/foreign_key_not_windows.result | 10 +++++++++- .../innodb/t/foreign_key_not_windows.test | 19 ++++++++++++++++++- storage/innobase/dict/dict0dict.cc | 10 ++++++---- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key_not_windows.result b/mysql-test/suite/innodb/r/foreign_key_not_windows.result index 0dcc3d46bb1..aaff06f8d68 100644 --- a/mysql-test/suite/innodb/r/foreign_key_not_windows.result +++ b/mysql-test/suite/innodb/r/foreign_key_not_windows.result @@ -18,6 +18,14 @@ CREATE TABLE `d255`.`d245` (x INT) ENGINE=InnoDB; DROP TABLE `d255`.`d250`; RENAME TABLE `d250#`.`d245` TO `d250#`.`d250`; RENAME TABLE `d255`.`d250` TO a; -DROP DATABASE `d255`; DROP TABLE a,t; +# +# MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLE +# +CREATE TABLE `d255`.t(a INT PRIMARY KEY)ENGINE=InnoDB; +CREATE TABLE `d255`.u(a INT PRIMARY KEY, +CONSTRAINT `d320` FOREIGN KEY (a) REFERENCES `d255`.t (a)) ENGINE=InnoDB; +RENAME TABLE `d255`.u TO u; +DROP TABLE u; +DROP DATABASE `d255`; # End of 10.3 tests diff --git a/mysql-test/suite/innodb/t/foreign_key_not_windows.test b/mysql-test/suite/innodb/t/foreign_key_not_windows.test index 0e1e25d64b3..e5f42a0ddab 100644 --- a/mysql-test/suite/innodb/t/foreign_key_not_windows.test +++ b/mysql-test/suite/innodb/t/foreign_key_not_windows.test @@ -54,7 +54,24 @@ eval RENAME TABLE `$d255`.`$d245` TO `$d255`.`$d250`; --replace_result $d250 d250 $d255 d255 eval RENAME TABLE `$d255`.`$d250` TO a; --replace_result $d255 d255 -eval DROP DATABASE `$d255`; DROP TABLE a,t; +--echo # +--echo # MDEV-29409 Buffer overflow in my_wc_mb_filename() on RENAME TABLE +--echo # + +let $d225=#############################################; +let $d320=################################################################; + +--replace_result $d255 d255 +eval CREATE TABLE `$d255`.t(a INT PRIMARY KEY)ENGINE=InnoDB; +--replace_result $d255 d255 $d320 d320 +eval CREATE TABLE `$d255`.u(a INT PRIMARY KEY, +CONSTRAINT `$d320` FOREIGN KEY (a) REFERENCES `$d255`.t (a)) ENGINE=InnoDB; +--replace_result $d255 d255 +eval RENAME TABLE `$d255`.u TO u; +DROP TABLE u; +--replace_result $d255 d255 +eval DROP DATABASE `$d255`; + --echo # End of 10.3 tests diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index d714e5f815b..eb0f10d55f4 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1595,7 +1595,7 @@ dict_table_rename_in_cache( in UTF-8 charset. The variable fkid here is used to store foreign key constraint name in charset my_charset_filename for comparison further below. */ - char fkid[MAX_TABLE_NAME_LEN+20]; + char fkid[MAX_TABLE_NAME_LEN * 2 + 20]; ibool on_tmp = FALSE; /* The old table name in my_charset_filename is stored @@ -1629,7 +1629,8 @@ dict_table_rename_in_cache( } } - strncpy(fkid, foreign->id, MAX_TABLE_NAME_LEN); + strncpy(fkid, foreign->id, (sizeof fkid) - 1); + fkid[(sizeof fkid) - 1] = '\0'; if (strstr(fkid, TEMP_TABLE_PATH_PREFIX) == NULL) { innobase_convert_to_filename_charset( @@ -3671,10 +3672,11 @@ dict_table_get_highest_foreign_id( for (dict_foreign_set::iterator it = table->foreign_set.begin(); it != table->foreign_set.end(); ++it) { - char fkid[MAX_TABLE_NAME_LEN+20]; + char fkid[MAX_TABLE_NAME_LEN * 2 + 20]; foreign = *it; - strcpy(fkid, foreign->id); + strncpy(fkid, foreign->id, (sizeof fkid) - 1); + fkid[(sizeof fkid) - 1] = '\0'; /* Convert foreign key identifier on dictionary memory cache to filename charset. */ innobase_convert_to_filename_charset( From 57739ae94a4af580c62bbc87d364fa002c5dbe04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 30 Aug 2022 12:03:58 +0300 Subject: [PATCH 5/5] MDEV-13888: innodb_fts.innodb_fts_plugin failed Add ORDER BY to make the test deterministic. Add FLUSH TABLES to avoid crash recovery warnings about the table mysql.plugin. This tends to occur on Valgrind, where the server shutdown could presumably time out, resulting in a forced kill. --- .../innodb_fts/r/innodb_fts_plugin.result | 36 ++++++++++--------- .../suite/innodb_fts/t/innodb_fts_plugin.test | 24 ++++++++----- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result b/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result index cec88f14b26..e636b30852b 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_plugin.result @@ -1,4 +1,5 @@ INSTALL PLUGIN simple_parser SONAME 'mypluglib'; +FLUSH TABLES; # Test Part 1: Grammar Test CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, @@ -31,7 +32,7 @@ INSERT INTO articles (title, body) VALUES ('1001 MySQL Tricks','How to use full-text search engine'), ('Go MySQL Tricks','How to use full text search engine'); SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('mysql'); +MATCH(title, body) AGAINST('mysql') ORDER BY id; id title body 1 MySQL Tutorial DBMS stands for MySQL DataBase ... 2 How To Use MySQL Well After you went through a ... @@ -68,7 +69,7 @@ INSERT INTO articles (title, body) VALUES ('Go MySQL Tricks','How to use full text search engine'); ALTER TABLE articles ADD FULLTEXT INDEX (title, body) WITH PARSER simple_parser; SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('mysql'); +MATCH(title, body) AGAINST('mysql') ORDER BY id; id title body 1 MySQL Tutorial DBMS stands for MySQL DataBase ... 2 How To Use MySQL Well After you went through a ... @@ -88,21 +89,23 @@ MATCH(title, body) AGAINST('full text'); id title body 5 Go MySQL Tricks How to use full text search engine SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('full-text' WITH QUERY EXPANSION); +MATCH(title, body) AGAINST('full-text' WITH QUERY EXPANSION) +ORDER BY id; id title body +1 MySQL Tutorial DBMS stands for MySQL DataBase ... +2 How To Use MySQL Well After you went through a ... +3 Optimizing MySQL In this tutorial we will show ... 4 1001 MySQL Tricks How to use full-text search engine 5 Go MySQL Tricks How to use full text search engine -2 How To Use MySQL Well After you went through a ... -1 MySQL Tutorial DBMS stands for MySQL DataBase ... -3 Optimizing MySQL In this tutorial we will show ... SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('full text' WITH QUERY EXPANSION); +MATCH(title, body) AGAINST('full text' WITH QUERY EXPANSION) +ORDER BY id; id title body -5 Go MySQL Tricks How to use full text search engine -4 1001 MySQL Tricks How to use full-text search engine -2 How To Use MySQL Well After you went through a ... 1 MySQL Tutorial DBMS stands for MySQL DataBase ... +2 How To Use MySQL Well After you went through a ... 3 Optimizing MySQL In this tutorial we will show ... +4 1001 MySQL Tricks How to use full-text search engine +5 Go MySQL Tricks How to use full text search engine SELECT * FROM articles WHERE MATCH(title, body) AGAINST('"mysql database"' IN BOOLEAN MODE); id title body @@ -135,27 +138,27 @@ INSERT INTO articles (title, body) VALUES ('1001 MySQL Tricks','How to use full-text search engine'), ('Go MariaDB Tricks','How to use full text search engine'); SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('MySQL'); +MATCH(title, body) AGAINST('MySQL') ORDER BY id; id title body 6 MySQL Tutorial DBMS stands for MySQL DataBase ... 7 How To Use MySQL Well After you went through a ... 8 Optimizing MySQL In this tutorial we will show ... 9 1001 MySQL Tricks How to use full-text search engine SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('tutorial'); +MATCH(title, body) AGAINST('tutorial') ORDER BY id; id title body 6 MySQL Tutorial DBMS stands for MySQL DataBase ... 8 Optimizing MySQL In this tutorial we will show ... SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('Tricks'); +MATCH(title, body) AGAINST('Tricks') ORDER BY id; id title body 9 1001 MySQL Tricks How to use full-text search engine 10 Go MariaDB Tricks How to use full text search engine SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('full text search'); +MATCH(title, body) AGAINST('full text search') ORDER BY id; id title body -10 Go MariaDB Tricks How to use full text search engine 9 1001 MySQL Tricks How to use full-text search engine +10 Go MariaDB Tricks How to use full text search engine SELECT COUNT(*) FROM articles; COUNT(*) 5 @@ -183,7 +186,8 @@ UNINSTALL PLUGIN simple_parser; Warnings: Warning 1620 Plugin is busy and will be uninstalled on shutdown SELECT * FROM articles WHERE -MATCH(title, body) AGAINST('mysql'); +MATCH(title, body) AGAINST('mysql') +ORDER BY id; id title body 1 MySQL Tutorial DBMS stands for MySQL DataBase ... 2 How To Use MySQL Well After you went through a ... diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test b/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test index b22ac456668..7279925386b 100644 --- a/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test +++ b/mysql-test/suite/innodb_fts/t/innodb_fts_plugin.test @@ -6,6 +6,9 @@ # Install fts parser plugin INSTALL PLUGIN simple_parser SONAME 'mypluglib'; +# Flush the table mysql.plugin in case the server shutdown would time out. +FLUSH TABLES; + -- echo # Test Part 1: Grammar Test # Create a myisam table and alter it to innodb table CREATE TABLE articles ( @@ -52,7 +55,7 @@ INSERT INTO articles (title, body) VALUES # Simple term search SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('mysql'); + MATCH(title, body) AGAINST('mysql') ORDER BY id; # Test stopword and word len less than fts_min_token_size SELECT * FROM articles WHERE @@ -90,7 +93,7 @@ ALTER TABLE articles ADD FULLTEXT INDEX (title, body) WITH PARSER simple_parser; # Simple term search SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('mysql'); + MATCH(title, body) AGAINST('mysql') ORDER BY id; # Test stopword and word len less than fts_min_token_size SELECT * FROM articles WHERE @@ -105,10 +108,12 @@ SELECT * FROM articles WHERE # Test query expansion SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('full-text' WITH QUERY EXPANSION); + MATCH(title, body) AGAINST('full-text' WITH QUERY EXPANSION) + ORDER BY id; SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('full text' WITH QUERY EXPANSION); + MATCH(title, body) AGAINST('full text' WITH QUERY EXPANSION) + ORDER BY id; # No result here, we get '"mysql' 'database"' by simple parser SELECT * FROM articles WHERE @@ -150,13 +155,13 @@ INSERT INTO articles (title, body) VALUES --source include/restart_mysqld.inc SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('MySQL'); + MATCH(title, body) AGAINST('MySQL') ORDER BY id; SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('tutorial'); + MATCH(title, body) AGAINST('tutorial') ORDER BY id; SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('Tricks'); + MATCH(title, body) AGAINST('Tricks') ORDER BY id; SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('full text search'); + MATCH(title, body) AGAINST('full text search') ORDER BY id; SELECT COUNT(*) FROM articles; INSERT INTO articles (title, body) VALUES ('111', '1234 1234 1234'); @@ -193,7 +198,8 @@ UNINSTALL PLUGIN simple_parser; # Simple term search SELECT * FROM articles WHERE - MATCH(title, body) AGAINST('mysql'); + MATCH(title, body) AGAINST('mysql') + ORDER BY id; # Test stopword and word len less than fts_min_token_size SELECT * FROM articles WHERE