diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-04-29 15:40:51 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-04-29 15:40:51 +0300 |
commit | 496d0372ef2ff2a570c20923af4df32a03781acd (patch) | |
tree | c15d45eeff0fbbfe6112816a72e10352551269ee | |
parent | d4da131cff004e4157b755e417c49daef45ca80e (diff) | |
parent | 5ba2aa1ddc074dc89db7f265ddb61ce96f714fc8 (diff) | |
download | mariadb-git-496d0372ef2ff2a570c20923af4df32a03781acd.tar.gz |
Merge 10.4 into 10.5
98 files changed, 2813 insertions, 1305 deletions
diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index 2779e07e9dd..9e3549964e1 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -128,6 +128,8 @@ SET(INSTALL_SUPPORTFILESDIR_STANDALONE "support-files") SET(INSTALL_MYSQLDATADIR_STANDALONE "data") SET(INSTALL_UNIX_ADDRDIR_STANDALONE "/tmp/mysql.sock") +SET(INSTALL_PAMDIR_STANDALONE "share") +SET(INSTALL_PAMDATADIR_STANDALONE "share") # # RPM layout # @@ -164,6 +166,7 @@ SET(INSTALL_SYSTEMD_UNITDIR_RPM "/usr/lib/systemd/system") SET(INSTALL_SYSTEMD_SYSUSERSDIR_RPM "/usr/lib/sysusers.d") SET(INSTALL_SYSTEMD_TMPFILESDIR_RPM "/usr/lib/tmpfiles.d") SET(INSTALL_PAMDIR_RPM "/${INSTALL_LIBDIR_RPM}/security") +SET(INSTALL_PAMDATADIR_RPM "/etc/security") # # DEB layout @@ -197,6 +200,7 @@ SET(INSTALL_SYSTEMD_UNITDIR_DEB "/lib/systemd/system") SET(INSTALL_SYSTEMD_SYSUSERSDIR_DEB "/usr/lib/sysusers.d") SET(INSTALL_SYSTEMD_TMPFILESDIR_DEB "/usr/lib/tmpfiles.d") SET(INSTALL_PAMDIR_DEB "/lib/${CMAKE_CXX_LIBRARY_ARCHITECTURE}/security") +SET(INSTALL_PAMDATADIR_DEB "/etc/security") # # SVR4 layout diff --git a/debian/mariadb-server-10.5.preinst b/debian/mariadb-server-10.5.preinst index fa49711f4e1..947b4420ee6 100644 --- a/debian/mariadb-server-10.5.preinst +++ b/debian/mariadb-server-10.5.preinst @@ -30,7 +30,7 @@ mysql_upgradedir=/var/lib/mysql-upgrade stop_server() { # Return immediately if there are no mysql processes running # as there is no point in trying to shutdown in that case. - if ! pgrep -x mysqld > /dev/null; then return; fi + if ! pgrep -x --ns $$ mysqld > /dev/null; then return; fi set +e systemctl stop mysql diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index a3bd111745c..6d804f78e15 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -875,54 +875,66 @@ Function acquires either a backup tables lock, if supported by the server, or a global read lock (FLUSH TABLES WITH READ LOCK) otherwise. @returns true if lock acquired */ -bool -lock_tables(MYSQL *connection) +bool lock_tables(MYSQL *connection) { - if (have_lock_wait_timeout) { - /* Set the maximum supported session value for - lock_wait_timeout to prevent unnecessary timeouts when the - global value is changed from the default */ - xb_mysql_query(connection, - "SET SESSION lock_wait_timeout=31536000", false); - } - - if (have_backup_locks) { - msg("Executing LOCK TABLES FOR BACKUP..."); - xb_mysql_query(connection, "LOCK TABLES FOR BACKUP", false); - return(true); - } + if (have_lock_wait_timeout || opt_lock_wait_timeout) + { + char buf[FN_REFLEN]; + /* Set the maximum supported session value for + lock_wait_timeout if opt_lock_wait_timeout is not set to prevent + unnecessary timeouts when the global value is changed from the default */ + snprintf(buf, sizeof(buf), "SET SESSION lock_wait_timeout=%u", + opt_lock_wait_timeout ? opt_lock_wait_timeout : 31536000); + xb_mysql_query(connection, buf, false); + } - if (opt_lock_wait_timeout) { - if (!wait_for_no_updates(connection, opt_lock_wait_timeout, - opt_lock_wait_threshold)) { - return(false); - } - } + if (have_backup_locks) + { + msg("Executing LOCK TABLES FOR BACKUP..."); + xb_mysql_query(connection, "LOCK TABLES FOR BACKUP", false); + return (true); + } - msg("Acquiring BACKUP LOCKS..."); + if (opt_lock_wait_timeout) + { + if (!wait_for_no_updates(connection, opt_lock_wait_timeout, + opt_lock_wait_threshold)) + { + return (false); + } + } - if (opt_kill_long_queries_timeout) { - start_query_killer(); - } + msg("Acquiring BACKUP LOCKS..."); - if (have_galera_enabled) { - xb_mysql_query(connection, - "SET SESSION wsrep_causal_reads=0", false); - } + if (opt_kill_long_queries_timeout) + { + start_query_killer(); + } - xb_mysql_query(connection, "BACKUP STAGE START", true); - //xb_mysql_query(connection, "BACKUP STAGE FLUSH", true); - //xb_mysql_query(connection, "BACKUP STAGE BLOCK_DDL", true); - xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", true); + if (have_galera_enabled) + { + xb_mysql_query(connection, "SET SESSION wsrep_causal_reads=0", false); + } - if (opt_kill_long_queries_timeout) { - stop_query_killer(); - } + xb_mysql_query(connection, "BACKUP STAGE START", true); + // xb_mysql_query(connection, "BACKUP STAGE FLUSH", true); + // xb_mysql_query(connection, "BACKUP STAGE BLOCK_DDL", true); + xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", true); + /* Set the maximum supported session value for + lock_wait_timeout to prevent unnecessary timeouts when the + global value is changed from the default */ + if (opt_lock_wait_timeout) + xb_mysql_query(connection, "SET SESSION lock_wait_timeout=31536000", + false); + + if (opt_kill_long_queries_timeout) + { + stop_query_killer(); + } - return(true); + return (true); } - /*********************************************************************//** If backup locks are used, execute LOCK BINLOG FOR BACKUP provided that we are not in the --no-lock mode and the lock has not been acquired already. diff --git a/include/my_pthread.h b/include/my_pthread.h index 8bdf02a1bac..0cb830fc9c6 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -730,13 +730,14 @@ struct st_my_thread_var #endif }; -extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); +struct st_my_thread_var *_my_thread_var(void); extern void **my_thread_var_dbug(void); extern safe_mutex_t **my_thread_var_mutex_in_use(void); extern uint my_thread_end_wait_time; extern my_bool safe_mutex_deadlock_detector; #define my_thread_var (_my_thread_var()) #define my_errno my_thread_var->thr_errno +int set_mysys_var(struct st_my_thread_var *mysys_var); /* diff --git a/mysql-test/include/galera_have_debug_sync.inc b/mysql-test/include/galera_have_debug_sync.inc index 7c0156052d8..21e7b3c88c3 100644 --- a/mysql-test/include/galera_have_debug_sync.inc +++ b/mysql-test/include/galera_have_debug_sync.inc @@ -3,7 +3,7 @@ --let $galera_have_debug_sync = `SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters'` --if (!$galera_have_debug_sync) { - --skip "Test requires Galera debug library with debug_sync functionality" + --skip Test requires Galera debug library with debug_sync functionality } --enable_query_log diff --git a/mysql-test/include/have_garbd.inc b/mysql-test/include/have_garbd.inc deleted file mode 100644 index 0dd693f2c63..00000000000 --- a/mysql-test/include/have_garbd.inc +++ /dev/null @@ -1,4 +0,0 @@ -# -# suite.pm will make sure that all tests including this file -# will be skipped as needed -# diff --git a/mysql-test/include/have_mariabackup.inc b/mysql-test/include/have_mariabackup.inc deleted file mode 100644 index 0dd693f2c63..00000000000 --- a/mysql-test/include/have_mariabackup.inc +++ /dev/null @@ -1,4 +0,0 @@ -# -# suite.pm will make sure that all tests including this file -# will be skipped as needed -# diff --git a/mysql-test/include/switch_to_mysql_global_priv.inc b/mysql-test/include/switch_to_mysql_global_priv.inc index 78df6642760..3a93746c4e8 100644 --- a/mysql-test/include/switch_to_mysql_global_priv.inc +++ b/mysql-test/include/switch_to_mysql_global_priv.inc @@ -1,3 +1,4 @@ +echo # switching back from mysql.user to mysql.global_priv; disable_query_log; drop table mysql.user; rename table mysql.user_bak to mysql.user; diff --git a/mysql-test/include/switch_to_mysql_user.inc b/mysql-test/include/switch_to_mysql_user.inc index 4d67f30a10b..7e5e460390c 100644 --- a/mysql-test/include/switch_to_mysql_user.inc +++ b/mysql-test/include/switch_to_mysql_user.inc @@ -1,3 +1,4 @@ +echo # switching from mysql.global_priv to mysql.user; disable_query_log; rename table mysql.user to mysql.user_bak; CREATE TABLE mysql.user ( diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index 87054019759..19f2893ea51 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -100,8 +100,6 @@ else $bindir = getcwd(); } -our $wsrep_check_version; - # Find the safe process binary or script sub find_bin { if (IS_WIN32PERL or IS_CYGWIN) @@ -121,10 +119,6 @@ sub find_bin { "my_safe_process"); push(@safe_process_cmd, $exe); } - # Wsrep version check utility: - $wsrep_check_version= - my_find_bin($bindir, ["lib/My/SafeProcess", "My/SafeProcess"], - "wsrep_check_version", NOT_REQUIRED); } diff --git a/mysql-test/lib/My/SafeProcess/CMakeLists.txt b/mysql-test/lib/My/SafeProcess/CMakeLists.txt index 4c3b62fa67e..44c0e6eb8cb 100644 --- a/mysql-test/lib/My/SafeProcess/CMakeLists.txt +++ b/mysql-test/lib/My/SafeProcess/CMakeLists.txt @@ -14,6 +14,8 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + IF (WIN32) ADD_EXECUTABLE(my_safe_process safe_process_win.cc) ADD_EXECUTABLE(my_safe_kill safe_kill_win.cc) diff --git a/mysql-test/lib/My/SafeProcess/wsrep_check_version.c b/mysql-test/lib/My/SafeProcess/wsrep_check_version.c index 91098be882a..7398bc8ad92 100644 --- a/mysql-test/lib/My/SafeProcess/wsrep_check_version.c +++ b/mysql-test/lib/My/SafeProcess/wsrep_check_version.c @@ -13,122 +13,39 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include <stdlib.h> -#include <stdio.h> +#include <my_global.h> #include <string.h> -#include <errno.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef _WIN32 -#include <windows.h> -#define dlsym(lib, name) GetProcAddress((HMODULE)lib, name) -#define dlopen(libname, unused) LoadLibraryEx(libname, NULL, 0) -#define dlclose(lib) FreeLibrary((HMODULE)lib) -#elif defined(HAVE_DLFCN_H) -#include <dlfcn.h> -#else -#define NO_DLL -#endif - -#ifndef NO_DLL - #include "../../../../wsrep-lib/wsrep-API/v26/wsrep_api.h" -/************************************************************************** - * Library loader - **************************************************************************/ - -static int wsrep_check_iface_version(const char *found, const char *iface_ver) -{ - if (strcmp(found, iface_ver)) { - return ERANGE; - } - return 0; -} - -typedef int (*wsrep_loader_fun)(wsrep_t*); - -static wsrep_loader_fun wsrep_dlf(void *dlh, const char *sym) -{ - union { - wsrep_loader_fun dlfun; - void *obj; - } alias; - alias.obj = dlsym(dlh, sym); - return alias.dlfun; -} - -static int wsrep_check_version_symbol(void *dlh) -{ - char** dlversion = NULL; - dlversion = (char**) dlsym(dlh, "wsrep_interface_version"); - if (dlversion == NULL) - return EINVAL; - return wsrep_check_iface_version(*dlversion, WSREP_INTERFACE_VERSION); -} - -static int wsrep_print_version(void *dlh) -{ - char** dlversion = NULL; - dlversion = (char**) dlsym(dlh, "wsrep_interface_version"); - if (dlversion == NULL) - return EINVAL; - printf("found: %s, need: %s\n", *dlversion, WSREP_INTERFACE_VERSION); - return 0; -} - int main(int argc, char **argv) { - int rc = EINVAL; - void *dlh; - wsrep_loader_fun dlfun; - const char *provider= getenv("WSREP_PROVIDER"); - - if (!provider) - { - fprintf(stderr, "WSREP_PROVIDER is not set\n"); - return 1; - } - if (!(dlh = dlopen(provider, RTLD_NOW | RTLD_LOCAL))) - { - fprintf(stderr, "Can't open WSREP_PROVIDER (%s) library, error: %s\n", - provider, dlerror()); - goto err; - } - - if (!(dlfun = wsrep_dlf(dlh, "wsrep_loader"))) - { - fprintf(stderr, "Can't find 'wsrep_loader' symbol in %s\n", - provider); - goto err; - } - - if (argc < 2 || strcmp(argv[1], "-p")) { - rc = wsrep_check_version_symbol(dlh); - } - else { - rc = wsrep_print_version(dlh); - } - -err: - if (dlh) dlclose(dlh); - - if (rc == 0) - return 0; - else if (rc == ERANGE) - return 2; - else - return 1; -} - -#else - -int main(void) -{ + int rc= 1; + void *dlh; + const char *provider= getenv("WSREP_PROVIDER"); + char** dlversion= NULL; + + if (!provider || !*provider) + { + printf("WSREP_PROVIDER is not set\n"); + return 1; + } + if (!(dlh= dlopen(provider, RTLD_NOW | RTLD_LOCAL))) + { + printf("Can't open WSREP_PROVIDER (%s) library, error: %s\n", + provider, dlerror()); return 1; + } + + dlversion= (char**) dlsym(dlh, "wsrep_interface_version"); + if (dlversion && *dlversion) + { + rc= strcmp(*dlversion, WSREP_INTERFACE_VERSION) ? 2 : 0; + if (rc) + printf("Wrong wsrep provider library version, found: %s, need: %s\n", *dlversion, WSREP_INTERFACE_VERSION); + } + else + printf("Galera library does not contain a version symbol"); + + dlclose(dlh); + return rc; } - -#endif diff --git a/mysql-test/main/connect.result b/mysql-test/main/connect.result index ee1844bc3ee..229c2d9dafe 100644 --- a/mysql-test/main/connect.result +++ b/mysql-test/main/connect.result @@ -99,6 +99,7 @@ ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); connect fail_con,localhost,test,zorro,; ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) +# switching from mysql.global_priv to mysql.user update mysql.user set plugin="", authentication_string="", password=old_password("gambling2") where user=_binary"test"; flush privileges; show grants for test@localhost; @@ -168,6 +169,7 @@ ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); connect fail_con,localhost,test,zorro,; ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) +# switching back from mysql.user to mysql.global_priv delete from mysql.user where user=_binary"test"; connect con7,localhost,root,,test; create table t1 (id integer not null auto_increment primary key); @@ -363,6 +365,7 @@ connect(localhost,mysqltest_nouser,,test,MASTER_PORT,MASTER_SOCKET); connect pcon5,localhost,mysqltest_nouser,,,$MASTER_MYPORT,; ERROR 28000: Access denied for user 'mysqltest_nouser'@'localhost' (using password: NO) connection default; +# switching from mysql.global_priv to mysql.user update mysql.user set plugin='mysql_native_password' where user = 'mysqltest_up1'; update mysql.user set plugin='mysql_old_password' where user = 'mysqltest_up2'; select user, password, plugin, authentication_string from mysql.user @@ -382,6 +385,7 @@ user() current_user() mysqltest_up2@localhost mysqltest_up2@% disconnect pcon7; connection default; +# switching back from mysql.user to mysql.global_priv DROP USER mysqltest_up1@'%'; DROP USER mysqltest_up2@'%'; # diff --git a/mysql-test/main/empty_user_table.result b/mysql-test/main/empty_user_table.result index 924e4cd8ea5..e5307c36e24 100644 --- a/mysql-test/main/empty_user_table.result +++ b/mysql-test/main/empty_user_table.result @@ -7,8 +7,10 @@ Got one of the listed errors insert mysql.global_priv select * from t1; drop table t1; flush privileges; +# switching from mysql.global_priv to mysql.user truncate table mysql.user; flush privileges; connect(localhost,u1,,test,MASTER_PORT,MASTER_SOCKET); connect fail,localhost,u1; Got one of the listed errors +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/grant.result b/mysql-test/main/grant.result index 2b9609b51af..e5d08781146 100644 --- a/mysql-test/main/grant.result +++ b/mysql-test/main/grant.result @@ -2764,6 +2764,7 @@ DROP USER dummy@localhost; # # MDEV-19948 'show grants' return privileges individually # +# switching from mysql.global_priv to mysql.user CREATE USER ten2; GRANT ALL ON *.* TO ten2; SHOW GRANTS FOR ten2; @@ -2774,6 +2775,7 @@ SHOW GRANTS FOR ten2; Grants for ten2@% GRANT ALL PRIVILEGES ON *.* TO `ten2`@`%` DROP USER ten2; +# switching back from mysql.user to mysql.global_priv # # End of 10.3 tests # diff --git a/mysql-test/main/grant4.result b/mysql-test/main/grant4.result index 9da0b0b40b7..f252a4c2ad5 100644 --- a/mysql-test/main/grant4.result +++ b/mysql-test/main/grant4.result @@ -129,6 +129,7 @@ connection default; disconnect con1; drop database mysqltest_db1; drop user mysqltest_u1@localhost; +# switching from mysql.global_priv to mysql.user call mtr.add_suppression("Table 'mysql.user' doesn't exist"); call mtr.add_suppression("'mysql.user' is not of type 'TABLE'"); rename table mysql.user to mysql.user1; @@ -141,6 +142,8 @@ flush privileges; ERROR 42S02: Table 'mysql.user' doesn't exist drop temporary table mysql.user; rename table mysql.user1 to mysql.user; +# switching back from mysql.user to mysql.global_priv +# switching from mysql.global_priv to mysql.user call mtr.add_suppression('mysql.user table is damaged'); rename table mysql.user to mysql.user1; create table mysql.user (Host char(100), User char(100)); @@ -148,6 +151,7 @@ flush privileges; ERROR HY000: Unknown error drop table mysql.user; rename table mysql.user1 to mysql.user; +# switching back from mysql.user to mysql.global_priv End of 5.5 tests # # Additional coverage for refactoring which is made as part diff --git a/mysql-test/main/grant_4332.result b/mysql-test/main/grant_4332.result index af6b23088f5..7fc29795b6f 100644 --- a/mysql-test/main/grant_4332.result +++ b/mysql-test/main/grant_4332.result @@ -1,3 +1,4 @@ +# switching from mysql.global_priv to mysql.user set global sql_mode=""; set local sql_mode=""; alter table mysql.user modify User char(16) binary not null default ''; @@ -33,3 +34,4 @@ def user() 253 141 14 N 1 39 8 user() root@localhost set global sql_mode=default; +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/grant_repair.result b/mysql-test/main/grant_repair.result new file mode 100644 index 00000000000..d97bcc38a08 --- /dev/null +++ b/mysql-test/main/grant_repair.result @@ -0,0 +1,9 @@ +call mtr.add_suppression("mysql.user"); +# switching from mysql.global_priv to mysql.user +flush tables; +flush privileges; +Warnings: +Error 145 Table './mysql/user' is marked as crashed and should be repaired +Warning 1034 12544 clients are using or haven't closed the table properly +Note 1034 Table is fixed +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/grant_repair.test b/mysql-test/main/grant_repair.test new file mode 100644 index 00000000000..f07e4df3ae6 --- /dev/null +++ b/mysql-test/main/grant_repair.test @@ -0,0 +1,21 @@ +# +# MDEV-20257 Server crashes in Grant_table_base::init_read_record upon crash-upgrade +# +source include/not_embedded.inc; + +call mtr.add_suppression("mysql.user"); +source include/switch_to_mysql_user.inc; + +let mysql_datadir=`select @@datadir`; +flush tables; +perl; + $f=$ENV{mysql_datadir} . '/mysql/user.MAI'; + sysopen F, $f, 2 or die "sysopen $f: $!"; + # set the open_count to 1, "table was not closed properly" + sysseek F, 24, O_RDWR or die "sysseek: $!"; + syswrite F, 1, 1 or die "syswrite: $!"; +EOF +replace_result \\ /; +flush privileges; + +source include/switch_to_mysql_global_priv.inc; diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index f71ce087ba1..33c3d1b8198 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -575,6 +575,7 @@ SET GLOBAL enforce_storage_engine=NULL; # Ensure that mysql_upgrade correctly sets truncate_versioning_priv # on upgrade from 10.2 # +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; CREATE USER 'user3'@'%'; GRANT USAGE ON *.* TO 'user3'@'%'; @@ -593,6 +594,7 @@ update mysql.db set Delete_history_priv='Y' where db like 'test%'; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; # End of 10.3 tests +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; create user 'user3'@'localhost' identified with mysql_native_password as password('a_password'); show create user user3@localhost; @@ -625,9 +627,19 @@ connection default; drop user user3@localhost; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; drop table mysql.innodb_index_stats, mysql.innodb_table_stats; # mysql_upgrade --force --silent 2>&1 drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user +drop view mysql.user_bak; +alter table mysql.user change authentication_string auth_string text collate utf8_bin not null; +# mysql_upgrade --force --silent 2>&1 +select count(*) from mysql.global_priv; +count(*) +4 +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; # End of 10.4 tests diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test index 3dfe38701aa..0dad53f8881 100644 --- a/mysql-test/main/mysql_upgrade.test +++ b/mysql-test/main/mysql_upgrade.test @@ -282,4 +282,17 @@ drop table mysql.innodb_index_stats, mysql.innodb_table_stats; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# +# MDEV-21244 mysql_upgrade creating empty global_priv table +# +--source include/switch_to_mysql_user.inc +drop view mysql.user_bak; +alter table mysql.user change authentication_string auth_string text collate utf8_bin not null; +--echo # mysql_upgrade --force --silent 2>&1 +--exec $MYSQL_UPGRADE --force --silent 2>&1 +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +select count(*) from mysql.global_priv; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; + --echo # End of 10.4 tests diff --git a/mysql-test/main/mysql_upgrade_noengine.result b/mysql-test/main/mysql_upgrade_noengine.result index 27afb198c0e..1b915978a6d 100644 --- a/mysql-test/main/mysql_upgrade_noengine.result +++ b/mysql-test/main/mysql_upgrade_noengine.result @@ -1,3 +1,4 @@ +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; install soname 'ha_blackhole'; install soname 'ha_archive'; @@ -144,6 +145,7 @@ Code 1286 Message Unknown storage engine 'ARCHIVE' drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; alter table mysql.user drop column default_role, drop column max_statement_time; Phase 1/7: Checking and upgrading mysql database @@ -236,6 +238,7 @@ Code 1286 Message Unknown storage engine 'ARCHIVE' drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; alter table mysql.user drop column default_role, drop column max_statement_time; Phase 1/7: Checking and upgrading mysql database diff --git a/mysql-test/main/mysql_upgrade_to_100502.result b/mysql-test/main/mysql_upgrade_to_100502.result index 0fd5568774d..85fae5afc22 100644 --- a/mysql-test/main/mysql_upgrade_to_100502.result +++ b/mysql-test/main/mysql_upgrade_to_100502.result @@ -1,6 +1,7 @@ # # MDEV-22057 REPLICATION MASTER ADMIN is missing in root account after upgrade # +# switching from mysql.global_priv to mysql.user DROP VIEW mysql.user_bak; FLUSH PRIVILEGES; CREATE USER user_all@localhost; diff --git a/mysql-test/main/password_expiration.result b/mysql-test/main/password_expiration.result index bb39d8788dc..d05f6b3b5d0 100644 --- a/mysql-test/main/password_expiration.result +++ b/mysql-test/main/password_expiration.result @@ -138,6 +138,7 @@ ERROR HY000: Incorrect DAY value: '0' # # Password expiration fields are loaded properly on 10.3 tables # +# switching from mysql.global_priv to mysql.user create user user1@localhost; show create user user1@localhost; CREATE USER for user1@localhost @@ -205,6 +206,7 @@ connection default; drop user user1@localhost; set global disconnect_on_expired_password=default; set global default_password_lifetime=default; +# switching back from mysql.user to mysql.global_priv # # PASSWORD EXPIRE DEFAULT should use the default_password_lifetime # system var to set the number of days till expiration diff --git a/mysql-test/main/plugin_auth.result b/mysql-test/main/plugin_auth.result index 244e048c517..73c384734bd 100644 --- a/mysql-test/main/plugin_auth.result +++ b/mysql-test/main/plugin_auth.result @@ -354,6 +354,7 @@ uplain@localhost uplain@localhost connection default; disconnect cleartext_con; DROP USER uplain@localhost; +# switching from mysql.global_priv to mysql.user drop view mysql.user_bak; # # Bug #59038 : mysql.user.authentication_string column diff --git a/mysql-test/main/set_password.result b/mysql-test/main/set_password.result index eef7c6eccea..91c8b567ad6 100644 --- a/mysql-test/main/set_password.result +++ b/mysql-test/main/set_password.result @@ -158,6 +158,7 @@ connection default; drop user natauth@localhost, newpass@localhost, newpassnat@localhost; drop user oldauth@localhost, oldpass@localhost, oldpassold@localhost; set global secure_auth=default; +# switching from mysql.global_priv to mysql.user create user foo@localhost identified with mysql_native_password; update mysql.user set authentication_string=password('foo'), plugin='mysql_native_password' where user='foo' and host='localhost'; set password for 'foo'@'localhost' = password('bar'); @@ -179,3 +180,4 @@ select user,host,password,plugin,authentication_string from mysql.user where use user host password plugin authentication_string foo localhost mysql_native_password drop user foo@localhost; +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/main/sp_notembedded.result b/mysql-test/main/sp_notembedded.result index 3cf066f5b4c..e03361598a6 100644 --- a/mysql-test/main/sp_notembedded.result +++ b/mysql-test/main/sp_notembedded.result @@ -212,6 +212,7 @@ disconnect rl_contender; drop procedure p1; drop table t1; set session low_priority_updates=default; +# switching from mysql.global_priv to mysql.user INSERT IGNORE INTO mysql.user (Host, User, Password, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Reload_priv, Shutdown_priv, Process_priv, File_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Show_db_priv, Super_priv, @@ -231,6 +232,7 @@ CREATE PROCEDURE p1(i INT) BEGIN END; disconnect con1; connection default; DROP PROCEDURE p1; +# switching back from mysql.user to mysql.global_priv # # Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al. # @@ -323,6 +325,7 @@ DROP EVENT teste_bug11763507; # ------------------------------------------------------------------ # -- End of 5.1 tests # ------------------------------------------------------------------ +# switching from mysql.global_priv to mysql.user grant create routine on test.* to foo1@localhost identified by 'foo'; update mysql.user set authentication_string = replace(authentication_string, '*', '-') where user='foo1'; connect foo,localhost,foo1,foo; @@ -347,4 +350,5 @@ connection default; disconnect foo; drop procedure spfoo; drop user foo1@localhost; +# switching back from mysql.user to mysql.global_priv set @@global.concurrent_insert= @old_concurrent_insert; diff --git a/mysql-test/main/system_mysql_db_507.result b/mysql-test/main/system_mysql_db_507.result index 00b53a5798d..2d68dc82529 100644 --- a/mysql-test/main/system_mysql_db_507.result +++ b/mysql-test/main/system_mysql_db_507.result @@ -3,6 +3,7 @@ # Fatal error: mysql.user table is damaged or in # unsupported 3.20 format # +# switching from mysql.global_priv to mysql.user # # Original mysql.user table # @@ -221,3 +222,4 @@ drop user user@localhost; # # Reset to final original state. # +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index dc3177328ee..6b910fbeef2 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -141,10 +141,6 @@ my $opt_start_dirty; my $opt_start_exit; my $start_only; my $file_wsrep_provider; -my $extra_path; -my $mariabackup_path; -my $mariabackup_exe; -my $garbd_exe; our @global_suppressions; @@ -383,170 +379,6 @@ $| = 1; # Automatically flush STDOUT main(); -sub have_wsrep() { - my $wsrep_on= $mysqld_variables{'wsrep-on'}; - return defined $wsrep_on -} - -sub have_wsrep_provider() { - return $file_wsrep_provider ne ""; -} - -sub have_mariabackup() { - return $mariabackup_path ne ""; -} - -sub have_garbd() { - return $garbd_exe ne ""; -} - -sub check_wsrep_version() { - if ($My::SafeProcess::wsrep_check_version ne "") { - system($My::SafeProcess::wsrep_check_version); - return ($? >> 8) == 0; - } - else { - return 0; - } -} - -sub wsrep_version_message() { - if ($My::SafeProcess::wsrep_check_version ne "") { - my $output= `$My::SafeProcess::wsrep_check_version -p`; - if (($? >> 8) == 0) { - $output =~ s/\s+\z//; - return "Wsrep provider version mismatch (".$output.")"; - } - else { - return "Galera library does not contain a version symbol"; - } - } - else { - return "Unable to find a wsrep version check utility"; - } -} - -sub which($) { return `sh -c "command -v $_[0]"` } - -sub check_garbd_support() { - if (defined $ENV{'MTR_GARBD_EXE'}) { - if (mtr_file_exists($ENV{'MTR_GARBD_EXE'}) ne "") { - $garbd_exe= $ENV{'MTR_GARBD_EXE'}; - } else { - mtr_error("MTR_GARBD_EXE env set to an invalid path"); - } - } - else { - my $wsrep_path= dirname($file_wsrep_provider); - $garbd_exe= - mtr_file_exists($wsrep_path."/garb/garbd", - $wsrep_path."/../../bin/garb/garbd"); - if ($garbd_exe ne "") { - $ENV{MTR_GARBD_EXE}= $garbd_exe; - } - } -} - -sub check_wsrep_support() { - $garbd_exe= ""; - if (have_wsrep()) { - mtr_report(" - binaries built with wsrep patch"); - - # ADD scripts to $PATH to that wsrep_sst_* can be found - my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$bindir/scripts", $path_client_bindir; - mtr_error("No SST scripts") unless $spath; - my $separator= (IS_WINDOWS) ? ';' : ':'; - $ENV{PATH}="$spath$separator$ENV{PATH}"; - - # ADD mysql client library path to path so that wsrep_notify_cmd can find mysql - # client for loading the tables. (Don't assume each machine has mysql install) - my ($cpath) = grep { -f "$_/mysql"; } "$bindir/scripts", $path_client_bindir; - mtr_error("No scritps") unless $cpath; - $ENV{PATH}="$cpath$separator$ENV{PATH}" unless $cpath eq $spath; - - # ADD my_print_defaults script path to path so that SST scripts can find it - my $my_print_defaults_exe= - mtr_exe_maybe_exists( - "$bindir/extra/my_print_defaults", - "$path_client_bindir/my_print_defaults"); - my $epath= ""; - if ($my_print_defaults_exe ne "") { - $epath= dirname($my_print_defaults_exe); - } - mtr_error("No my_print_defaults") unless $epath; - $ENV{PATH}="$epath$separator$ENV{PATH}" unless ($epath eq $spath) or - ($epath eq $cpath); - - $extra_path= $epath; - - if (!IS_WINDOWS) { - if (which("socat")) { - $ENV{MTR_GALERA_TFMT}="socat"; - } elsif (which("nc")) { - $ENV{MTR_GALERA_TFMT}="nc"; - } - } - - # Check whether WSREP_PROVIDER environment variable is set. - if (defined $ENV{'WSREP_PROVIDER'}) { - $file_wsrep_provider= ""; - if ($ENV{'WSREP_PROVIDER'} ne "none") { - if (mtr_file_exists($ENV{'WSREP_PROVIDER'}) ne "") { - $file_wsrep_provider= $ENV{'WSREP_PROVIDER'}; - } else { - mtr_error("WSREP_PROVIDER env set to an invalid path"); - } - check_garbd_support(); - } - # WSREP_PROVIDER is valid; set to a valid path or "none"). - mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}"); - } else { - # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider - # library. - $file_wsrep_provider= - mtr_file_exists("/usr/lib64/galera-4/libgalera_smm.so", - "/usr/lib64/galera/libgalera_smm.so", - "/usr/lib/galera-4/libgalera_smm.so", - "/usr/lib/galera/libgalera_smm.so"); - if ($file_wsrep_provider ne "") { - # wsrep provider library found ! - mtr_verbose("wsrep provider library found : $file_wsrep_provider"); - $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; - check_garbd_support(); - } else { - mtr_verbose("Could not find wsrep provider library, setting it to 'none'"); - $ENV{'WSREP_PROVIDER'}= "none"; - } - } - } else { - $file_wsrep_provider= ""; - $extra_path= ""; - } -} - -sub check_mariabackup_support() { - $mariabackup_path= ""; - $mariabackup_exe= - mtr_exe_maybe_exists( - "$bindir/extra/mariabackup$opt_vs_config/mariabackup", - "$path_client_bindir/mariabackup"); - if ($mariabackup_exe ne "") { - my $bpath= dirname($mariabackup_exe); - my $separator= (IS_WINDOWS) ? ';' : ':'; - $ENV{PATH}="$bpath$separator$ENV{PATH}" unless $bpath eq $extra_path; - - $mariabackup_path= $bpath; - - $ENV{XTRABACKUP}= $mariabackup_exe; - - $ENV{XBSTREAM}= mtr_exe_maybe_exists( - "$bindir/extra/mariabackup/$opt_vs_config/mbstream", - "$path_client_bindir/mbstream"); - - $ENV{INNOBACKUPEX}= "$mariabackup_exe --innobackupex"; - } -} - sub main { $ENV{MTR_PERL}=$^X; @@ -591,8 +423,7 @@ sub main { } check_ssl_support(); check_debug_support(); - check_wsrep_support(); - check_mariabackup_support(); + environment_setup(); if (!$opt_suites) { $opt_suites= join ',', collect_default_suites(@DEFAULT_SUITES); @@ -2602,10 +2433,23 @@ sub environment_setup { my $exe_innochecksum= mtr_exe_maybe_exists("$bindir/extra$opt_vs_config/innochecksum", "$path_client_bindir/innochecksum"); - if ($exe_innochecksum) - { - $ENV{'INNOCHECKSUM'}= native_path($exe_innochecksum); - } + $ENV{'INNOCHECKSUM'}= native_path($exe_innochecksum) if $exe_innochecksum; + + # ---------------------------------------------------- + # mariabackup + # ---------------------------------------------------- + my $exe_mariabackup= mtr_exe_maybe_exists( + "$bindir/extra/mariabackup$opt_vs_config/mariabackup", + "$path_client_bindir/mariabackup"); + + $ENV{XTRABACKUP}= native_path($exe_mariabackup) if $exe_mariabackup; + + my $exe_xbstream= mtr_exe_maybe_exists( + "$bindir/extra/mariabackup/$opt_vs_config/mbstream", + "$path_client_bindir/mbstream"); + $ENV{XBSTREAM}= native_path($exe_xbstream) if $exe_xbstream; + + $ENV{INNOBACKUPEX}= "$exe_mariabackup --innobackupex"; # Create an environment variable to make it possible # to detect that valgrind is being used from test cases @@ -3404,7 +3248,8 @@ sub mysql_install_db { # ---------------------------------------------------------------------- # export MYSQLD_BOOTSTRAP_CMD variable containing <path>/mysqld <args> # ---------------------------------------------------------------------- - $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args); + $ENV{'MYSQLD_BOOTSTRAP_CMD'}= "$exe_mysqld_bootstrap " . join(" ", @$args) + unless defined $ENV{'MYSQLD_BOOTSTRAP_CMD'}; # Extra options can come not only from the command line, but also # from option files or combinations. We want them on a command line diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index 6666947b03d..cb30a3186e5 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -47,21 +47,6 @@ sub skip_combinations { $skip{'main/plugin_loaderr.test'} = 'needs compiled-in innodb' unless $::mysqld_variables{'innodb'} eq "ON"; - $skip{'include/have_mariabackup.inc'} = 'Need mariabackup' - unless ::have_mariabackup(); - - $skip{'include/have_mariabackup.inc'} = 'Need socket statistics utility' - unless IS_WINDOWS || ::which("ss"); - - $skip{'include/have_mariabackup.inc'} = 'Need socat or nc' - unless IS_WINDOWS || $ENV{MTR_GALERA_TFMT}; - - $skip{'include/have_garbd.inc'} = 'Need garbd' - unless ::have_garbd(); - - $skip{'include/have_file_key_management.inc'} = 'Needs file_key_management plugin' - unless $ENV{FILE_KEY_MANAGEMENT_SO}; - # disable tests that use ipv6, if unsupported sub ipv6_ok() { use Socket; diff --git a/mysql-test/suite/galera/include/have_mariabackup.inc b/mysql-test/suite/galera/include/have_mariabackup.inc new file mode 100644 index 00000000000..6c4ad240172 --- /dev/null +++ b/mysql-test/suite/galera/include/have_mariabackup.inc @@ -0,0 +1,7 @@ +if (!$XTRABACKUP) { + skip Needs mariabackup; +} + +if (!$MTR_GALERA_TFMT) { + skip Needs socat or nc; +} diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 4bce28aceb2..447c2b79d2b 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -1,16 +1,11 @@ package My::Suite::Galera; -use File::Basename; -use My::Find; -@ISA = qw(My::Suite); - -return "Not run for embedded server" if $::opt_embedded_server; - -return "WSREP is not compiled in" if not ::have_wsrep(); +use lib 'suite'; +use wsrep::common; -return "No wsrep provider library" unless ::have_wsrep_provider(); +@ISA = qw(My::Suite); -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( @@ -69,4 +64,10 @@ push @::global_suppressions, qr(WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to .*), ); +sub skip_combinations { + my %skip = (); + $skip{'include/have_mariabackup.inc'} = 'Need ss' unless `ss -V`; + %skip; +} + bless { }; diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf b/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf index 75dff78149d..2392071ccfe 100644 --- a/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup.cnf @@ -10,3 +10,6 @@ wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' +[sst] +transferfmt=@ENV.MTR_GALERA_TFMT +streamfmt=xbstream diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf index 1542376b2b8..e98f37654cc 100644 --- a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf @@ -12,3 +12,6 @@ wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' +[sst] +transferfmt=@ENV.MTR_GALERA_TFMT +streamfmt=xbstream diff --git a/mysql-test/include/galera_resume.inc b/mysql-test/suite/galera_3nodes/include/galera_resume.inc index af8f2b956fd..af8f2b956fd 100644 --- a/mysql-test/include/galera_resume.inc +++ b/mysql-test/suite/galera_3nodes/include/galera_resume.inc diff --git a/mysql-test/suite/galera_3nodes/include/have_garbd.inc b/mysql-test/suite/galera_3nodes/include/have_garbd.inc new file mode 100644 index 00000000000..560372c22e9 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/include/have_garbd.inc @@ -0,0 +1,3 @@ +if (!$MTR_GARBD_EXE) { + skip Needs garbd; +} diff --git a/mysql-test/suite/galera_3nodes/suite.pm b/mysql-test/suite/galera_3nodes/suite.pm index 4a861f3b9fa..b808db6a50a 100644 --- a/mysql-test/suite/galera_3nodes/suite.pm +++ b/mysql-test/suite/galera_3nodes/suite.pm @@ -1,16 +1,11 @@ package My::Suite::GALERA_3NODES; -use File::Basename; -use My::Find; -@ISA = qw(My::Suite); - -return "Not run for embedded server" if $::opt_embedded_server; +use lib 'suite'; +use wsrep::common; -return "WSREP is not compiled in" if not ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); +@ISA = qw(My::Suite); -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( diff --git a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test index 8dfb4660f3e..cd5c020ae38 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test @@ -4,7 +4,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc ---source include/have_mariabackup.inc +--source suite/galera/include/have_mariabackup.inc --let $galera_connection_name = node_3 --let $galera_server_number = 3 diff --git a/mysql-test/suite/galera_sr/suite.pm b/mysql-test/suite/galera_sr/suite.pm index 878e2d0fffd..cc13421d66d 100644 --- a/mysql-test/suite/galera_sr/suite.pm +++ b/mysql-test/suite/galera_sr/suite.pm @@ -1,16 +1,11 @@ package My::Suite::Galera_sr; -use File::Basename; -use My::Find; -@ISA = qw(My::Suite); - -return "Not run for embedded server" if $::opt_embedded_server; +use lib 'suite'; +use wsrep::common; -return "WSREP is not compiled in" if not ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); +@ISA = qw(My::Suite); -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( diff --git a/mysql-test/suite/innodb/r/innodb-alter-timestamp.result b/mysql-test/suite/innodb/r/innodb-alter-timestamp.result index 56a1df7ce5d..6934484a488 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-timestamp.result +++ b/mysql-test/suite/innodb/r/innodb-alter-timestamp.result @@ -124,3 +124,18 @@ SELECT DISTINCT (CURRENT_TIMESTAMP()-d4) <= 60 FROM t1; (CURRENT_TIMESTAMP()-d4) <= 60 1 DROP TABLE t1; +CREATE TABLE t1(f1 int) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_4096; +connect purge_control,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1; +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +ALTER TABLE t1 ADD f2 DATE NOT NULL, ALGORITHM=INPLACE; +INSERT INTO t1 VALUES (1, now()); +Warnings: +Note 1265 Data truncated for column 'f2' at row 1 +ALTER TABLE t1 ADD f3 DATE NOT NULL, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +DROP TABLE t1; +disconnect purge_control; diff --git a/mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result b/mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result new file mode 100644 index 00000000000..32d87b4668a --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result @@ -0,0 +1,73 @@ +# +# Bug #29717909 MEMORY LIFETIME OF VARIABLES BETWEEN CHECK AND UPDATE INCORRECTLY MANAGED +# +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +create table user_stopword_1(value varchar(30)) engine = innodb; +create table user_stopword_2(value varchar(30)) engine = innodb; +set @blah = 'test/user_stopword_1'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/user_stopword_1 +set @blah = 'test/user_stopword_2'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/user_stopword_2 +SET GLOBAL innodb_ft_server_stopword_table= NULL; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +SET GLOBAL innodb_ft_server_stopword_table= default; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +drop table user_stopword_1, user_stopword_2; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +ib_buffer_pool +set @blah='hello'; +set global innodb_buffer_pool_filename = @blah; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +hello +set global innodb_buffer_pool_filename="bye"; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +bye +set global innodb_buffer_pool_filename=NULL; +ERROR 42000: Variable 'innodb_buffer_pool_filename' can't be set to the value of 'NULL' +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +bye +set global innodb_buffer_pool_filename=default; +select @@innodb_buffer_pool_filename; +@@innodb_buffer_pool_filename +ib_buffer_pool +CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; +CREATE TABLE t2 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +NULL +set @blah = 'test/t1'; +SET GLOBAL innodb_ft_aux_table = @blah; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +test/t1 +set @blah = 'test/t2'; +SET GLOBAL innodb_ft_aux_table = @blah; +SET GLOBAL innodb_ft_aux_table = NULL; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +NULL +SET GLOBAL innodb_ft_aux_table =default; +select @@innodb_ft_aux_table; +@@innodb_ft_aux_table +NULL +drop table t1,t2; diff --git a/mysql-test/suite/innodb/t/innodb-alter-timestamp.test b/mysql-test/suite/innodb/t/innodb-alter-timestamp.test index 1fabdc8f24d..28b09b18e10 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-timestamp.test +++ b/mysql-test/suite/innodb/t/innodb-alter-timestamp.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc CREATE TABLE t1 (i1 INT UNSIGNED NULL DEFAULT 42) ENGINE=innodb; INSERT INTO t1 VALUES(NULL); @@ -82,3 +83,23 @@ ALTER TABLE t1 ADD COLUMN d4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP; SELECT COUNT(DISTINCT d4),COUNT(d4),COUNT(*) FROM t1; SELECT DISTINCT (CURRENT_TIMESTAMP()-d4) <= 60 FROM t1; DROP TABLE t1; + +# MDEV-19611 INPLACE ALTER does not fail on bad implicit default value + +# Empty-table +CREATE TABLE t1(f1 int) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_4096; +connect(purge_control,localhost,root,,); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +DELETE FROM t1; +SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES,NO_ZERO_DATE'; +ALTER TABLE t1 ADD f2 DATE NOT NULL, ALGORITHM=INPLACE; + +# Non-empty table +INSERT INTO t1 VALUES (1, now()); +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t1 ADD f3 DATE NOT NULL, ALGORITHM=INPLACE; +DROP TABLE t1; +disconnect purge_control; diff --git a/mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test b/mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test new file mode 100644 index 00000000000..2e1391355b9 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test @@ -0,0 +1,70 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug #29717909 MEMORY LIFETIME OF VARIABLES BETWEEN CHECK AND UPDATE INCORRECTLY MANAGED +--echo # + +#Test innodb_ft_server_stopword_table (global variable) +select @@innodb_ft_server_stopword_table; +create table user_stopword_1(value varchar(30)) engine = innodb; +create table user_stopword_2(value varchar(30)) engine = innodb; + +set @blah = 'test/user_stopword_1'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; + +set @blah = 'test/user_stopword_2'; +SET GLOBAL innodb_ft_server_stopword_table= @blah; +select @@innodb_ft_server_stopword_table; + +SET GLOBAL innodb_ft_server_stopword_table= NULL; +select @@innodb_ft_server_stopword_table; + +SET GLOBAL innodb_ft_server_stopword_table= default; +select @@innodb_ft_server_stopword_table; + +drop table user_stopword_1, user_stopword_2; + +#Test innodb_buffer_pool_filename (global variable) + +select @@innodb_buffer_pool_filename; + +set @blah='hello'; +set global innodb_buffer_pool_filename = @blah; +select @@innodb_buffer_pool_filename; + +set global innodb_buffer_pool_filename="bye"; +select @@innodb_buffer_pool_filename; + +--error ER_WRONG_VALUE_FOR_VAR +set global innodb_buffer_pool_filename=NULL; +select @@innodb_buffer_pool_filename; + +set global innodb_buffer_pool_filename=default; +select @@innodb_buffer_pool_filename; + +#Test innodb_ft_aux_table (global variable) +CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; + +CREATE TABLE t2 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx +(opening_line)) ENGINE=InnoDB; + +select @@innodb_ft_aux_table; + +set @blah = 'test/t1'; +SET GLOBAL innodb_ft_aux_table = @blah; +select @@innodb_ft_aux_table; + +set @blah = 'test/t2'; +SET GLOBAL innodb_ft_aux_table = @blah; + +SET GLOBAL innodb_ft_aux_table = NULL; +select @@innodb_ft_aux_table; + +SET GLOBAL innodb_ft_aux_table =default; +select @@innodb_ft_aux_table; + +drop table t1,t2; diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result index 91f875377e2..8717d002d32 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result @@ -705,6 +705,11 @@ FULLTEXT(f2), FOREIGN KEY(f1) REFERENCES mdev20987_1(f1))ENGINE=InnoDB; INSERT INTO mdev20987_1 VALUES(1); INSERT INTO mdev20987_2 VALUES(1, 'mariadb'); +CREATE TABLE mdev22358 (a INT, b TEXT, FULLTEXT KEY ftidx (b)) ENGINE=InnoDB; +ALTER TABLE mdev22358 DROP KEY ftidx; +INSERT INTO mdev22358 (a) VALUES (2),(2); +ALTER TABLE mdev22358 ADD UNIQUE KEY uidx (a), ADD FULLTEXT KEY ftidx (b); +ERROR 23000: Duplicate entry '2' for key 'uidx' # restart SHOW CREATE TABLE t2; Table Create Table @@ -713,7 +718,7 @@ t2 CREATE TABLE `t2` ( PRIMARY KEY (`FTS_DOC_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DELETE FROM t1 WHERE MATCH(char_column) AGAINST ('bbb'); -DROP TABLE t1, t2, mdev20987_2, mdev20987_1; +DROP TABLE t1, t2, mdev20987_2, mdev20987_1, mdev22358; "----------Test28---------" create table `fts_test`(`a` text,fulltext key(`a`))engine=innodb; set session autocommit=0; diff --git a/mysql-test/suite/innodb_fts/r/stopword.result b/mysql-test/suite/innodb_fts/r/stopword.result new file mode 100644 index 00000000000..05516d10f34 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/stopword.result @@ -0,0 +1,748 @@ +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table not_defined does not exist."); +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table test/user_stopword_session does not exist."); +select * from information_schema.innodb_ft_default_stopword; +value +a +about +an +are +as +at +be +by +com +de +en +for +from +how +i +in +is +it +la +of +on +or +that +the +this +to +was +what +when +where +who +will +with +und +the +www +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL Tutorial','DBMS stands for DataBase ...') , +('How To Use MySQL Well','After you went through a ...'), +('Optimizing MySQL','In this tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH (title,body) +AGAINST ('the' IN NATURAL LANGUAGE MODE); +id title body +SET @innodb_ft_server_stopword_table_orig=@@innodb_ft_server_stopword_table; +SET @innodb_ft_enable_stopword_orig=@@innodb_ft_enable_stopword; +SET @innodb_ft_user_stopword_table_orig=@@innodb_ft_user_stopword_table; +set global innodb_ft_server_stopword_table = "not_defined"; +ERROR 42000: Variable 'innodb_ft_server_stopword_table' can't be set to the value of 'not_defined' +set global innodb_ft_server_stopword_table = NULL; +create table user_stopword(value varchar(30)) engine = innodb; +set global innodb_ft_server_stopword_table = "test/user_stopword"; +drop index title on articles; +create fulltext index idx on articles(title, body); +SELECT * FROM articles WHERE MATCH (title,body) +AGAINST ('the' IN NATURAL LANGUAGE MODE); +id title body +5 MySQL vs. YourSQL In the following database comparison ... +CREATE TABLE articles_2 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_2 (title, body) +VALUES ('test for stopwords','this is it...'); +SELECT * FROM articles_2 WHERE MATCH (title,body) +AGAINST ('this' IN NATURAL LANGUAGE MODE); +id title body +1 test for stopwords this is it... +insert into user_stopword values("this"); +CREATE TABLE articles_3 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_3 (title, body) +VALUES ('test for stopwords','this is it...'); +SELECT * FROM articles_3 WHERE MATCH (title,body) +AGAINST ('this' IN NATURAL LANGUAGE MODE); +id title body +create table user_stopword_session(value varchar(30)) engine = innodb; +insert into user_stopword_session values("session"); +set session innodb_ft_user_stopword_table="test/user_stopword_session"; +CREATE TABLE articles_4 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_4 (title, body) +VALUES ('test for session stopwords','this should also be excluded...'); +SELECT * FROM articles_4 WHERE MATCH (title,body) +AGAINST ('session' IN NATURAL LANGUAGE MODE); +id title body +SELECT * FROM articles_4 WHERE MATCH (title,body) +AGAINST ('this' IN NATURAL LANGUAGE MODE); +id title body +1 test for session stopwords this should also be excluded... +connect con1,localhost,root,,; +CREATE TABLE articles_5 ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT (title,body) +) ENGINE=InnoDB; +INSERT INTO articles_5 (title, body) +VALUES ('test for session stopwords','this should also be excluded...'); +SELECT * FROM articles_5 WHERE MATCH (title,body) +AGAINST ('session' IN NATURAL LANGUAGE MODE); +id title body +1 test for session stopwords this should also be excluded... +connection default; +drop table articles; +drop table articles_2; +drop table articles_3; +drop table articles_4; +drop table articles_5; +drop table user_stopword; +drop table user_stopword_session; +SET GLOBAL innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`title`,`body`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 7; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 7; +id title body +7 update the record to see will is indexed or not +DELETE FROM articles WHERE id = 7; +SET global innodb_ft_server_stopword_table = NULL; +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +0 +SET global innodb_ft_user_stopword_table = NULL; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 8; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +SELECT * FROM articles WHERE id = 8; +id title body +8 update the record to see will is indexed or not +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 8; +id title body +8 update the record to see will is indexed or not +DELETE FROM articles WHERE id = 8; +ALTER TABLE articles DROP INDEX idx; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1 +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +ANALYZE TABLE articles; +Table Op Msg_type Msg_text +test.articles analyze status Engine-independent statistics collected +test.articles analyze Warning Engine-independent statistics are not collected for column 'body' +test.articles analyze status OK +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +1 MySQL from Tutorial DBMS stands for DataBase ... +6 MySQL Security When configured properly, MySQL ... +2 when To Use MySQL Well After that you went through a ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +2 when To Use MySQL Well After that you went through a ... +3 where will Optimizing MySQL In what tutorial we will show ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +9 the record will not index the , will words +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +9 the record will not index the , will words +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT COUNT(*),max(id) FROM articles; +COUNT(*) max(id) +7 9 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +9 update the record to see will is indexed or not +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +9 update the record to see will is indexed or not +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 9; +id title body +DROP TABLE articles; +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET SESSION innodb_ft_user_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +create table user_stopword(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword"; +create table server_stopword(value varchar(30)) engine = innodb; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +insert into user_stopword values("this"),("will"),("the"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +insert into server_stopword values("what"),("where"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +DELETE FROM user_stopword; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +insert into user_stopword values("this"),("will"),("the"); +ALTER TABLE articles DROP INDEX idx; +SET SESSION innodb_ft_enable_stopword = 0; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SET SESSION innodb_ft_enable_stopword = 1; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table = default; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +DROP TABLE articles,user_stopword,server_stopword; +SET innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`title`,`body`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +create table user_stopword(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword"; +insert into user_stopword values("mysqld"),("DBMS"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); +id title body +set session innodb_ft_user_stopword_table = default; +create table server_stopword(value varchar(30)) engine = innodb; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +insert into server_stopword values("root"),("properly"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +id title body +set session innodb_ft_user_stopword_table = "test/user_stopword"; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +id title body +6 MySQL Security When configured properly, MySQL ... +set session innodb_ft_user_stopword_table = "test/user_stopword"; +DELETE FROM user_stopword; +set global innodb_ft_server_stopword_table = "test/server_stopword"; +DELETE FROM server_stopword; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +id title body +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); +id title body +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +DROP TABLE articles,user_stopword,server_stopword; +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; +CREATE TABLE articles ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +title VARCHAR(200), +body TEXT, +FULLTEXT `idx` (title,body) +) ENGINE=InnoDB; +SHOW CREATE TABLE articles; +Table Create Table +articles CREATE TABLE `articles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(200) DEFAULT NULL, + `body` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `idx` (`title`,`body`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO articles (title,body) VALUES +('MySQL from Tutorial','DBMS stands for DataBase ...') , +('when To Use MySQL Well','After that you went through a ...'), +('where will Optimizing MySQL','In what tutorial we will show ...'), +('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), +('MySQL vs. YourSQL','In the following database comparison ...'), +('MySQL Security','When configured properly, MySQL ...'); +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +0 +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +"In connection 1" +connection con1; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +1 +ANALYZE TABLE articles; +Table Op Msg_type Msg_text +test.articles analyze status Engine-independent statistics collected +test.articles analyze Warning Engine-independent statistics are not collected for column 'body' +test.articles analyze status OK +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +1 MySQL from Tutorial DBMS stands for DataBase ... +6 MySQL Security When configured properly, MySQL ... +2 when To Use MySQL Well After that you went through a ... +4 1001 MySQL Tricks 1. Never run mysqld as root. 2. ... +5 MySQL vs. YourSQL In the following database comparison ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +2 when To Use MySQL Well After that you went through a ... +3 where will Optimizing MySQL In what tutorial we will show ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +1 MySQL from Tutorial DBMS stands for DataBase ... +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SET SESSION innodb_ft_enable_stopword = 1; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +1 +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +"In connection default" +connection default; +select @@innodb_ft_enable_stopword; +@@innodb_ft_enable_stopword +0 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); +id title body +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +SET SESSION innodb_ft_enable_stopword = 1; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +id title body +"In connection 1" +connection con1; +SET SESSION innodb_ft_enable_stopword = 1; +create table user_stopword(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword"; +insert into user_stopword values("this"),("will"),("the"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +"In connection default" +connection default; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +id title body +select @@innodb_ft_user_stopword_table; +@@innodb_ft_user_stopword_table +NULL +create table user_stopword_1(value varchar(30)) engine = innodb; +set session innodb_ft_user_stopword_table = "test/user_stopword_1"; +insert into user_stopword_1 values("when"); +SET SESSION innodb_ft_enable_stopword = 1; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); +id title body +2 when To Use MySQL Well After that you went through a ... +6 MySQL Security When configured properly, MySQL ... +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); +id title body +"In connection 1" +connection con1; +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_user_stopword_table; +@@innodb_ft_user_stopword_table +NULL +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +NULL +create table server_stopword(value varchar(30)) engine = innodb; +SET GLOBAL innodb_ft_server_stopword_table = "test/server_stopword"; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/server_stopword +insert into server_stopword values("when"),("the"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); +id title body +disconnect con1; +"In connection default" +connection default; +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_server_stopword_table; +@@innodb_ft_server_stopword_table +test/server_stopword +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +insert into server_stopword values("where"),("will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +id title body +3 where will Optimizing MySQL In what tutorial we will show ... +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); +id title body +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +id title body +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +id title body +DROP TABLE articles,user_stopword,user_stopword_1,server_stopword; +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test index e1f4874a1d4..8f4902fd2de 100644 --- a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test +++ b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test @@ -672,10 +672,16 @@ CREATE TABLE mdev20987_2(f1 INT NOT NULL, f2 CHAR(100), FOREIGN KEY(f1) REFERENCES mdev20987_1(f1))ENGINE=InnoDB; INSERT INTO mdev20987_1 VALUES(1); INSERT INTO mdev20987_2 VALUES(1, 'mariadb'); + +CREATE TABLE mdev22358 (a INT, b TEXT, FULLTEXT KEY ftidx (b)) ENGINE=InnoDB; +ALTER TABLE mdev22358 DROP KEY ftidx; +INSERT INTO mdev22358 (a) VALUES (2),(2); +--error ER_DUP_ENTRY +ALTER TABLE mdev22358 ADD UNIQUE KEY uidx (a), ADD FULLTEXT KEY ftidx (b); --source include/restart_mysqld.inc SHOW CREATE TABLE t2; DELETE FROM t1 WHERE MATCH(char_column) AGAINST ('bbb'); -DROP TABLE t1, t2, mdev20987_2, mdev20987_1; +DROP TABLE t1, t2, mdev20987_2, mdev20987_1, mdev22358; --echo "----------Test28---------" create table `fts_test`(`a` text,fulltext key(`a`))engine=innodb; diff --git a/mysql-test/suite/innodb_fts/t/stopword.opt b/mysql-test/suite/innodb_fts/t/stopword.opt new file mode 100644 index 00000000000..d6938c3b1ea --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/stopword.opt @@ -0,0 +1 @@ +--innodb-ft-default-stopword diff --git a/mysql-test/suite/innodb_fts/t/stopword.test b/mysql-test/suite/innodb_fts/t/stopword.test new file mode 100644 index 00000000000..5105a6d2fec --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/stopword.test @@ -0,0 +1,657 @@ +# This is the basic function tests for innodb FTS + +-- source include/have_innodb.inc + +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table not_defined does not exist."); +call mtr.add_suppression("\\[ERROR\\] InnoDB: user stopword table test/user_stopword_session does not exist."); + +select * from information_schema.innodb_ft_default_stopword; + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL Tutorial','DBMS stands for DataBase ...') , + ('How To Use MySQL Well','After you went through a ...'), + ('Optimizing MySQL','In this tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# "the" is in the default stopword, it would not be selected +SELECT * FROM articles WHERE MATCH (title,body) + AGAINST ('the' IN NATURAL LANGUAGE MODE); + +SET @innodb_ft_server_stopword_table_orig=@@innodb_ft_server_stopword_table; +SET @innodb_ft_enable_stopword_orig=@@innodb_ft_enable_stopword; +SET @innodb_ft_user_stopword_table_orig=@@innodb_ft_user_stopword_table; + +# Provide user defined stopword table, if not (correctly) defined, +# it will be rejected +--error ER_WRONG_VALUE_FOR_VAR +set global innodb_ft_server_stopword_table = "not_defined"; +set global innodb_ft_server_stopword_table = NULL; + +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; + +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/user_stopword"; + +drop index title on articles; + +create fulltext index idx on articles(title, body); + +# Now we should be able to find "the" +SELECT * FROM articles WHERE MATCH (title,body) + AGAINST ('the' IN NATURAL LANGUAGE MODE); + +# Nothing inserted into the default stopword, so essentially +# nothing get screened. The new stopword could only be +# effective for table created thereafter +CREATE TABLE articles_2 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_2 (title, body) + VALUES ('test for stopwords','this is it...'); + +# Now we can find record with "this" +SELECT * FROM articles_2 WHERE MATCH (title,body) + AGAINST ('this' IN NATURAL LANGUAGE MODE); + +# Ok, let's instantiate some value into user supplied stop word +# table +insert into user_stopword values("this"); + +# Ok, let's repeat with the new table again. +CREATE TABLE articles_3 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_3 (title, body) + VALUES ('test for stopwords','this is it...'); + +# Now we should NOT find record with "this" +SELECT * FROM articles_3 WHERE MATCH (title,body) + AGAINST ('this' IN NATURAL LANGUAGE MODE); + +# Test session level stopword control "innodb_user_stopword_table" +create table user_stopword_session(value varchar(30)) engine = innodb; + +insert into user_stopword_session values("session"); + +set session innodb_ft_user_stopword_table="test/user_stopword_session"; + +CREATE TABLE articles_4 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_4 (title, body) + VALUES ('test for session stopwords','this should also be excluded...'); + +# "session" is excluded +SELECT * FROM articles_4 WHERE MATCH (title,body) + AGAINST ('session' IN NATURAL LANGUAGE MODE); + +# But we can find record with "this" +SELECT * FROM articles_4 WHERE MATCH (title,body) + AGAINST ('this' IN NATURAL LANGUAGE MODE); + +--connect (con1,localhost,root,,) +CREATE TABLE articles_5 ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT (title,body) + ) ENGINE=InnoDB; + +INSERT INTO articles_5 (title, body) + VALUES ('test for session stopwords','this should also be excluded...'); + +# "session" should be found since the stopword table is session specific +SELECT * FROM articles_5 WHERE MATCH (title,body) + AGAINST ('session' IN NATURAL LANGUAGE MODE); + +--connection default +drop table articles; +drop table articles_2; +drop table articles_3; +drop table articles_4; +drop table articles_5; +drop table user_stopword; +drop table user_stopword_session; + +SET GLOBAL innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; + +#--------------------------------------------------------------------------------------- +# Behavior : +# The stopword is loaded into memory at +# 1) create fulltext index time, +# 2) boot server, +# 3) first time FTs is used +# So if you already created a FTS index, and then turn off stopword +# or change stopword table content it won't affect the FTS +# that already created since the stopword list are already loaded. +# It will only affect the new FTS index created after you changed +# the settings. + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +SHOW CREATE TABLE articles; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# Case : server_stopword=default +# Try to Search default stopword from innodb, "where", "will", "what" +# and "when" are all stopwords +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +# boolean No result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +# no result expected +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +# no result expected +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +# Not going to update as where condition can not find record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +# Update the record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 7; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Delete will not work as where condition do not return +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 7; +DELETE FROM articles WHERE id = 7; + + + +# Case : Turn OFF stopword list variable and search stopword on OLD index. +# disable stopword list +SET global innodb_ft_server_stopword_table = NULL; +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; +SET global innodb_ft_user_stopword_table = NULL; + +# search default stopword with innodb_ft_enable_stopword is OFF. +# No records expected even though we turned OFF stopwod filtering +# (refer Behavior (at the top of the test) for explanation ) +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +# Not going to update as where condition can not find record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +# Update the record +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE id = 8; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +SELECT * FROM articles WHERE id = 8; +# Delete will not work as where condition do not return +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 8; +DELETE FROM articles WHERE id = 8; + +# Case : Turn OFF stopword list variable and search stopword on NEW index. +# Drop index +ALTER TABLE articles DROP INDEX idx; +SHOW CREATE TABLE articles; + +# Create the FTS index Using Alter Table. +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); + +ANALYZE TABLE articles; + +# search default stopword with innodb_ft_enable_stopword is OFF. +# All records expected as stopwod filtering is OFF and we created +# new FTS index. +# (refer Behavior (at the top of the test) for explanation ) +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); +# Update will succeed. +UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); + +SELECT COUNT(*),max(id) FROM articles; +# Update the record - uncommet on fix +#UPDATE articles SET title = "update the record" , body = 'to see will is indexed or not' +#WHERE id = 9; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Delete will succeed. +DELETE FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE id = 9; + + +DROP TABLE articles; + +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET SESSION innodb_ft_user_stopword_table=default; + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# No records expeced for select +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword"; +# Define a correct formated server stopword table +create table server_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +# Add values into user supplied stop word table +insert into user_stopword values("this"),("will"),("the"); + +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Add values into server supplied stop word table +insert into server_stopword values("what"),("where"); +# Follwoing should return result as server stopword list was empty at create index time +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); + +# Delete stopword from user list +DELETE FROM user_stopword; +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# Follwoing should return result even though to server stopword list +# conatin these words. Session level stopword list takes priority +# Here user_stopword is set using innodb_ft_user_stopword_table +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); + +# Follwoing should return result as user stopword list was empty at create index time +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Add values into user supplied stop word table +insert into user_stopword values("this"),("will"),("the"); + +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +SET SESSION innodb_ft_enable_stopword = 0; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Session level stopword list takes priority +SET SESSION innodb_ft_enable_stopword = 1; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + +# Make user stopword list deafult so as to server stopword list takes priority +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table = default; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + + +DROP TABLE articles,user_stopword,server_stopword; + +# Restore Defaults +SET innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; + +#--------------------------------------------------------------------------------------- +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +SHOW CREATE TABLE articles; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# No records expeced for select +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword"; +insert into user_stopword values("mysqld"),("DBMS"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); + + +# Drop existing index and create the FTS index Using Alter Table. +# user stopword list will take effect. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); + +# set user stopword list empty +set session innodb_ft_user_stopword_table = default; +# Define a correct formated user stopword table +create table server_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +insert into server_stopword values("root"),("properly"); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); + + +# set user stopword list empty +set session innodb_ft_user_stopword_table = "test/user_stopword"; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +# user stopword list take effect as its session level +# Result expected for select +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); + +# set user stopword list +set session innodb_ft_user_stopword_table = "test/user_stopword"; +DELETE FROM user_stopword; +# The set operation should be successful +set global innodb_ft_server_stopword_table = "test/server_stopword"; +DELETE FROM server_stopword; +# user stopword list take affect as its session level +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+wha* +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('what'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+root +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('properly'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+DBMS +mysql" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysqld'); + +DROP TABLE articles,user_stopword,server_stopword; + +# Restore Values +SET SESSION innodb_ft_enable_stopword=@innodb_ft_enable_stopword_orig; +SET GLOBAL innodb_ft_server_stopword_table=default; +SET SESSION innodb_ft_user_stopword_table=default; + + +#------------------------------------------------------------------------------ +# FTS stopword list test - check varaibles across sessions + +# Create FTS table +CREATE TABLE articles ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + title VARCHAR(200), + body TEXT, + FULLTEXT `idx` (title,body) + ) ENGINE=InnoDB; + +SHOW CREATE TABLE articles; + +# Insert six rows +INSERT INTO articles (title,body) VALUES + ('MySQL from Tutorial','DBMS stands for DataBase ...') , + ('when To Use MySQL Well','After that you went through a ...'), + ('where will Optimizing MySQL','In what tutorial we will show ...'), + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + +# session varaible innodb_ft_enable_stopword=0 will take effect for new FTS index +SET SESSION innodb_ft_enable_stopword = 0; +select @@innodb_ft_enable_stopword; + +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); + + +--echo "In connection 1" +--connection con1 +select @@innodb_ft_enable_stopword; + +ANALYZE TABLE articles; + +# result expected as index created before setting innodb_ft_enable_stopword varaible off +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +SET SESSION innodb_ft_enable_stopword = 1; +select @@innodb_ft_enable_stopword; +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected turned innodb_ft_enable_stopword is ON +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + + +--echo "In connection default" +--connection default +select @@innodb_ft_enable_stopword; +# no result expected as word not indexed from connection 1 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("when"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("what" WITH QUERY EXPANSION); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("whe*" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+what +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+from" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+where +(show what)" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@6' IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"where will"@9' IN BOOLEAN MODE); + +INSERT INTO articles(title,body) values ('the record will' , 'not index the , will words'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); + +SET SESSION innodb_ft_enable_stopword = 1; +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+the +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('"the will"@11' IN BOOLEAN MODE); + + +--echo "In connection 1" +--connection con1 +SET SESSION innodb_ft_enable_stopword = 1; +# Define a correct formated user stopword table +create table user_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword"; +# Add values into user supplied stop word table +insert into user_stopword values("this"),("will"),("the"); +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected as innodb_ft_user_stopword_table filter it +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); + + +--echo "In connection default" +--connection default +# no result expected as innodb_ft_user_stopword_table filter it from connection1 +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+show +will" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('will'); +select @@innodb_ft_user_stopword_table; +# Define a correct formated user stopword table +create table user_stopword_1(value varchar(30)) engine = innodb; +# The set operation should be successful +set session innodb_ft_user_stopword_table = "test/user_stopword_1"; +insert into user_stopword_1 values("when"); +SET SESSION innodb_ft_enable_stopword = 1; +# result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('when'); + +--echo "In connection 1" +--connection con1 +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_user_stopword_table; +select @@innodb_ft_server_stopword_table; +# Define a correct formated server stopword table +create table server_stopword(value varchar(30)) engine = innodb; +# The set operation should be successful +SET GLOBAL innodb_ft_server_stopword_table = "test/server_stopword"; +select @@innodb_ft_server_stopword_table; +insert into server_stopword values("when"),("the"); +# Drop existing index and create the FTS index Using Alter Table. +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); + +disconnect con1; +--source include/wait_until_disconnected.inc + +--echo "In connection default" +--connection default +SET SESSION innodb_ft_enable_stopword = 1; +SET SESSION innodb_ft_user_stopword_table=default; +select @@innodb_ft_server_stopword_table; +# result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +insert into server_stopword values("where"),("will"); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); +ALTER TABLE articles DROP INDEX idx; +ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); +# no result expected +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+when" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('the'); +SELECT * FROM articles WHERE MATCH(title,body) AGAINST("+will +where" IN BOOLEAN MODE); +SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('where'); + + +DROP TABLE articles,user_stopword,user_stopword_1,server_stopword; + +# Restore Values +SET GLOBAL innodb_ft_user_stopword_table=@innodb_ft_user_stopword_table_orig; +SET GLOBAL innodb_ft_server_stopword_table=@innodb_ft_server_stopword_table_orig; diff --git a/mysql-test/suite/innodb_gis/r/rtree_split.result b/mysql-test/suite/innodb_gis/r/rtree_split.result index 518319ff3d6..df88960ba3d 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_split.result +++ b/mysql-test/suite/innodb_gis/r/rtree_split.result @@ -1,52 +1,24 @@ create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb; -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +begin; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; SET @saved_dbug = @@SESSION.debug_dbug; -SET debug_dbug = '+d, rtr_page_need_second_split'; -insert into t1 select * from t1; +SET debug_dbug = '+d,rtr_page_need_second_split'; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; SET debug_dbug = @saved_dbug; -delete from t1; -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -start transaction; -insert into t1 select * from t1; +rollback; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; +begin; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; rollback; check table t1; Table Op Msg_type Msg_text test.t1 check status OK -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_71424; check table t1; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/innodb_gis/t/rtree_split.test b/mysql-test/suite/innodb_gis/t/rtree_split.test index 856fb485234..6f285187508 100644 --- a/mysql-test/suite/innodb_gis/t/rtree_split.test +++ b/mysql-test/suite/innodb_gis/t/rtree_split.test @@ -1,5 +1,5 @@ # WL#6745 InnoDB R-tree support -# This test case will test R-tree split, mostly on duplciate records. +# This test case will test R-tree split, mostly on duplicate records. # Not supported in embedded --source include/not_embedded.inc @@ -8,66 +8,34 @@ --source include/big_test.inc --source include/not_valgrind.inc --source include/have_debug.inc +--source include/have_sequence.inc let $restart_noprint=2; # Create table with R-tree index. create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb; +begin; # Insert enough values to let R-tree split. -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); - -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; #Check second round spliting. SET @saved_dbug = @@SESSION.debug_dbug; -SET debug_dbug = '+d, rtr_page_need_second_split'; -insert into t1 select * from t1; +SET debug_dbug = '+d,rtr_page_need_second_split'; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_576; SET debug_dbug = @saved_dbug; +rollback; -delete from t1; - -insert into t1 values(1, Point(1,1)); -insert into t1 values(2, Point(2,2)); -insert into t1 values(3, Point(3,3)); -insert into t1 values(4, Point(4,4)); -insert into t1 values(5, Point(5,5)); -insert into t1 values(6, Point(6,6)); -insert into t1 values(7, Point(7,7)); -insert into t1 values(8, Point(8,8)); -insert into t1 values(9, Point(9,9)); - -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; - -insert into t1 select * from t1; -insert into t1 select * from t1; - -insert into t1 select * from t1; -insert into t1 select * from t1; -start transaction; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; +begin; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_2304; rollback; check table t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; -insert into t1 select * from t1; +insert into t1 select @s:=1+(seq mod 9), point(@s, @s) +from seq_1_to_71424; check table t1; select count(*) from t1; diff --git a/mysql-test/suite/mariabackup/backup_lock_wait_timeout.result b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.result new file mode 100644 index 00000000000..9806bc29b47 --- /dev/null +++ b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.result @@ -0,0 +1,11 @@ +CREATE TABLE t(i INT) ENGINE INNODB; +connect con1,localhost,root,,; +BEGIN; +LOCK TABLES t WRITE; +connection default; +# xtrabackup backup +connection con1; +COMMIT; +connection default; +disconnect con1; +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/backup_lock_wait_timeout.test b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.test new file mode 100644 index 00000000000..e0f43910ef6 --- /dev/null +++ b/mysql-test/suite/mariabackup/backup_lock_wait_timeout.test @@ -0,0 +1,28 @@ +--source include/have_innodb.inc +--source include/count_sessions.inc + +CREATE TABLE t(i INT) ENGINE INNODB; + +connect (con1,localhost,root,,); +BEGIN; +LOCK TABLES t WRITE; + +--connection default + +echo # xtrabackup backup; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; + +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --ftwrl-wait-timeout=1 --target-dir=$targetdir; +--enable_result_log + +--connection con1 +COMMIT; + +--connection default +--disconnect con1 + +DROP TABLE t; +rmdir $targetdir; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/mariabackup/suite.pm b/mysql-test/suite/mariabackup/suite.pm index 14e38d16158..f0db4482156 100644 --- a/mysql-test/suite/mariabackup/suite.pm +++ b/mysql-test/suite/mariabackup/suite.pm @@ -7,12 +7,13 @@ use strict; return "Not run for embedded server" if $::opt_embedded_server; -return "No mariabackup" unless ::have_mariabackup(); +return "No mariabackup" unless $ENV{XTRABACKUP}; my $have_qpress = index(`qpress 2>&1`,"Compression") > 0; sub skip_combinations { my %skip; + $skip{'include/have_file_key_management.inc'} = 'needs file_key_management plugin' unless $ENV{FILE_KEY_MANAGEMENT_SO}; $skip{'compress_qpress.test'}= 'needs qpress executable in PATH' unless $have_qpress; %skip; } diff --git a/mysql-test/suite/plugins/r/multiauth.result b/mysql-test/suite/plugins/r/multiauth.result index 2bff91cc285..aed46ac8964 100644 --- a/mysql-test/suite/plugins/r/multiauth.result +++ b/mysql-test/suite/plugins/r/multiauth.result @@ -153,8 +153,10 @@ show create user mysqltest1; CREATE USER for mysqltest1@% CREATE USER `mysqltest1`@`%` IDENTIFIED VIA mysql_native_password USING '*BFE3F4604CFD21E6595080A261D92EF0183B5971' OR unix_socket drop user mysqltest1; +# switching from mysql.global_priv to mysql.user create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); ERROR HY000: Column count of mysql.user is wrong. Expected 3, found 47. Created with MariaDB XX.YY.ZZ, now running XX.YY.ZZ. Please use mariadb-upgrade to fix this error +# switching back from mysql.user to mysql.global_priv create user USER identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; create user mysqltest1 identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; update mysql.global_priv set priv=replace(priv, '1234567890123456789012345678901234567890a', 'invalid password'); @@ -192,3 +194,16 @@ user() current_user() database() mysqltest1@localhost mysqltest1@% test drop user mysqltest1; uninstall soname 'auth_ed25519'; +create user mysqltest1 identified via mysql_native_password as password("good") OR unix_socket; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER `mysqltest1`@`%` IDENTIFIED VIA mysql_native_password USING '*8409037B3E362D6DAE24C8E667F4D3B66716144E' OR unix_socket +alter user mysqltest1 identified via mysql_native_password as password("better"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER `mysqltest1`@`%` IDENTIFIED BY PASSWORD '*6E6CABC9967AB586F009616BA69DAC2953849C88' +flush privileges; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER `mysqltest1`@`%` IDENTIFIED BY PASSWORD '*6E6CABC9967AB586F009616BA69DAC2953849C88' +drop user mysqltest1; diff --git a/mysql-test/suite/plugins/t/multiauth.test b/mysql-test/suite/plugins/t/multiauth.test index d6d3fc587cd..73538f23832 100644 --- a/mysql-test/suite/plugins/t/multiauth.test +++ b/mysql-test/suite/plugins/t/multiauth.test @@ -198,3 +198,14 @@ drop user mysqltest1; uninstall soname 'auth_ed25519'; --remove_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt + +# +# MDEV-21928 ALTER USER doesn't remove excess authentication plugins from mysql.global_priv +# +create user mysqltest1 identified via mysql_native_password as password("good") OR unix_socket; +show create user mysqltest1; +alter user mysqltest1 identified via mysql_native_password as password("better"); +show create user mysqltest1; +flush privileges; +show create user mysqltest1; +drop user mysqltest1; diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result index 841f6515d47..55cbbd8843d 100644 --- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result +++ b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result @@ -1,3 +1,4 @@ +# switching from mysql.global_priv to mysql.user connect mysql, localhost, root,,; use mysql; alter table user drop column is_role; @@ -26,3 +27,4 @@ update user set is_role='N'; flush privileges; create role test_role; drop role test_role; +# switching back from mysql.user to mysql.global_priv diff --git a/mysql-test/suite/sql_sequence/rebuild.test b/mysql-test/suite/sql_sequence/rebuild.test index 7163a79e884..ae8a06671a3 100644 --- a/mysql-test/suite/sql_sequence/rebuild.test +++ b/mysql-test/suite/sql_sequence/rebuild.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_perfschema.inc --echo # --echo # MDEV-15977 Assertion `! thd->in_sub_stmt' failed in trans_commit_stmt diff --git a/mysql-test/suite/wsrep/common.pm b/mysql-test/suite/wsrep/common.pm new file mode 100644 index 00000000000..8ac3b3ea94c --- /dev/null +++ b/mysql-test/suite/wsrep/common.pm @@ -0,0 +1,117 @@ +package wsrep::common; + +use base qw(Exporter); +our @EXPORT= qw(wsrep_not_ok); + +use File::Basename; +use Memoize; +memoize 'wrong_wsrep_version'; +memoize 'check_garbd_support'; +memoize 'check_wsrep_support'; +memoize 'wsrep_not_ok'; + +use mtr_report; + +my $extra_path; +my $mariabackup_path; +my $mariabackup_exe; +my $garbd_exe; +my $file_wsrep_provider; + +sub wrong_wsrep_version() { + my $check_version= dirname($My::SafeProcess::safe_process_cmd[0]) . '/wsrep_check_version'; + my $checked = `$check_version -p`; + chomp($checked); + return $? ? $checked : undef; +} + +sub which($) { return `sh -c "command -v $_[0]"` } + +sub check_garbd_support() { + my $wsrep_path= dirname($file_wsrep_provider); + $garbd_exe= ::mtr_file_exists($wsrep_path."/garb/garbd", + $wsrep_path."/../../bin/garb/garbd", + '/usr/bin/garbd'); + $ENV{MTR_GARBD_EXE}= $garbd_exe if $garbd_exe; +} + +sub check_wsrep_support() { + mtr_report(" - binaries built with wsrep patch"); + + # ADD scripts to $PATH to that wsrep_sst_* can be found + my ($spath) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir; + mtr_error("No SST scripts") unless $spath; + $ENV{PATH}="$spath:$ENV{PATH}"; + + # ADD mysql client library path to path so that wsrep_notify_cmd can find mysql + # client for loading the tables. (Don't assume each machine has mysql install) + my ($cpath) = grep { -f "$_/mysql"; } "$::bindir/scripts", $::path_client_bindir; + mtr_error("No scritps") unless $cpath; + $ENV{PATH}="$cpath:$ENV{PATH}" unless $cpath eq $spath; + + # ADD my_print_defaults script path to path so that SST scripts can find it + my $my_print_defaults_exe= + ::mtr_exe_maybe_exists( + "$::bindir/extra/my_print_defaults", + "$::path_client_bindir/my_print_defaults"); + my $epath= ""; + if ($my_print_defaults_exe ne "") { + $epath= dirname($my_print_defaults_exe); + } + mtr_error("No my_print_defaults") unless $epath; + $ENV{PATH}="$epath:$ENV{PATH}" unless ($epath eq $spath) or + ($epath eq $cpath); + + $extra_path= $epath; + + if (which("socat")) { + $ENV{MTR_GALERA_TFMT}="socat"; + } elsif (which("nc")) { + $ENV{MTR_GALERA_TFMT}="nc"; + } + + $ENV{PATH}=dirname($ENV{XTRABACKUP}).":$ENV{PATH}" if $ENV{XTRABACKUP}; + + # Check whether WSREP_PROVIDER environment variable is set. + if (defined $ENV{'WSREP_PROVIDER'}) { + $file_wsrep_provider= ""; + if ($ENV{'WSREP_PROVIDER'} ne "none") { + if (::mtr_file_exists($ENV{'WSREP_PROVIDER'}) ne "") { + $file_wsrep_provider= $ENV{'WSREP_PROVIDER'}; + } else { + mtr_error("WSREP_PROVIDER env set to an invalid path"); + } + check_garbd_support(); + } + # WSREP_PROVIDER is valid; set to a valid path or "none"). + mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}"); + } else { + # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider + # library. + $file_wsrep_provider= + ::mtr_file_exists("/usr/lib64/galera-4/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so", + "/usr/lib/galera-4/libgalera_smm.so", + "/usr/lib/galera/libgalera_smm.so"); + if ($file_wsrep_provider ne "") { + # wsrep provider library found ! + mtr_verbose("wsrep provider library found : $file_wsrep_provider"); + $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; + check_garbd_support(); + } else { + mtr_verbose("Could not find wsrep provider library, setting it to 'none'"); + $ENV{'WSREP_PROVIDER'}= "none"; + } + } +} + +sub wsrep_not_ok() { + return "Not run for embedded server" if $::opt_embedded_server; + return "WSREP is not compiled in" if not $::mysqld_variables{'wsrep-on'}; + check_wsrep_support(); + return "No wsrep provider library" unless $file_wsrep_provider; + return wrong_wsrep_version() if wrong_wsrep_version(); + undef; +} + +1; diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 7b3dae7c8c3..2ee33d83275 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -1,16 +1,11 @@ package My::Suite::WSREP; -use File::Basename; -use My::Find; -@ISA = qw(My::Suite); - -return "Not run for embedded server" if $::opt_embedded_server; +use lib 'suite'; +use wsrep::common; -return "WSREP is not compiled in" unless ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); +@ISA = qw(My::Suite); -return ::wsrep_version_message() unless ::check_wsrep_version(); +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 1f84809e50f..24b4b3aff15 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -137,7 +137,7 @@ void my_thread_global_reinit(void) my_thread_destroy_internal_mutex(); my_thread_init_internal_mutex(); - tmp= my_pthread_getspecific(struct st_my_thread_var*, THR_KEY_mysys); + tmp= my_thread_var; DBUG_ASSERT(tmp); my_thread_destory_thr_mutex(tmp); @@ -274,7 +274,7 @@ my_bool my_thread_init(void) fprintf(stderr,"my_thread_init(): pthread_self: %p\n", pthread_self()); #endif - if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) + if (my_thread_var) { #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n", @@ -292,7 +292,7 @@ my_bool my_thread_init(void) error= 1; goto end; } - pthread_setspecific(THR_KEY_mysys,tmp); + set_mysys_var(tmp); tmp->pthread_self= pthread_self(); my_thread_init_thr_mutex(tmp); @@ -329,7 +329,7 @@ end: void my_thread_end(void) { struct st_my_thread_var *tmp; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_end(): tmp: %p pthread_self: %p thread_id: %ld\n", @@ -350,7 +350,7 @@ void my_thread_end(void) as the key is used by DBUG. */ DBUG_POP(); - pthread_setspecific(THR_KEY_mysys,0); + set_mysys_var(NULL); if (tmp && tmp->init) { @@ -434,7 +434,7 @@ extern void **my_thread_var_dbug() struct st_my_thread_var *tmp; if (!my_thread_global_init_done) return NULL; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; return tmp && tmp->init ? &tmp->dbug : 0; } #endif /* DBUG_OFF */ @@ -446,7 +446,7 @@ safe_mutex_t **my_thread_var_mutex_in_use() struct st_my_thread_var *tmp; if (!my_thread_global_init_done) return NULL; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; return tmp ? &tmp->mutex_in_use : 0; } diff --git a/plugin/auth_pam/CMakeLists.txt b/plugin/auth_pam/CMakeLists.txt index 89d5cc6a8af..f1b95e7d91e 100644 --- a/plugin/auth_pam/CMakeLists.txt +++ b/plugin/auth_pam/CMakeLists.txt @@ -22,7 +22,7 @@ IF(HAVE_PAM_APPL_H) IF(HAVE_STRNDUP) ADD_DEFINITIONS(-DHAVE_STRNDUP) ENDIF(HAVE_STRNDUP) - FIND_LIBRARY(PAM_LIBRARY pam) + FIND_LIBRARY(PAM_LIBRARY pam) # for srpm build-depends detection ADD_DEFINITIONS(-D_GNU_SOURCE) MYSQL_ADD_PLUGIN(auth_pam_v1 auth_pam_v1.c LINK_LIBRARIES pam MODULE_ONLY) MYSQL_ADD_PLUGIN(auth_pam auth_pam.c LINK_LIBRARIES pam dl MODULE_ONLY) @@ -42,7 +42,7 @@ IF(HAVE_PAM_APPL_H) SET_TARGET_PROPERTIES (pam_user_map PROPERTIES PREFIX "") IF(INSTALL_PAMDIR) INSTALL(TARGETS pam_user_map DESTINATION ${INSTALL_PAMDIR} COMPONENT Server) - INSTALL(FILES mapper/user_map.conf DESTINATION /etc/security COMPONENT Server) + INSTALL(FILES mapper/user_map.conf DESTINATION ${INSTALL_PAMDATADIR} COMPONENT Server) ENDIF() ENDIF() ENDIF(HAVE_PAM_APPL_H) diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm index 9170a337bf4..c7d4b0adf5b 100644 --- a/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm +++ b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm @@ -4,15 +4,9 @@ use My::Find; @ISA = qw(My::Suite); -return "Not run for embedded server" if $::opt_embedded_server; - -return "WSREP is not compiled in" if not ::have_wsrep(); - -return "No wsrep provider library" unless ::have_wsrep_provider(); - -return ::wsrep_version_message() unless ::check_wsrep_version(); - -return "No WSREP_INFO plugin" unless $ENV{WSREP_INFO_SO}; +use lib 'suite'; +use wsrep::common; +return wsrep_not_ok() if wsrep_not_ok(); push @::global_suppressions, ( diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 1518bbd5a2a..a9fc865401c 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -648,6 +648,7 @@ UPDATE user SET Delete_history_priv = Super_priv WHERE @had_user_delete_history_ ALTER TABLE user ADD plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, ADD authentication_string TEXT NOT NULL; +ALTER TABLE user CHANGE auth_string authentication_string TEXT NOT NULL; ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, MODIFY authentication_string TEXT NOT NULL; ALTER TABLE user ADD password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; diff --git a/sql/handler.cc b/sql/handler.cc index 4f99b6e675f..359ead530af 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4803,7 +4803,7 @@ Alter_inplace_info::Alter_inplace_info(HA_CREATE_INFO *create_info_arg, Alter_info *alter_info_arg, KEY *key_info_arg, uint key_count_arg, partition_info *modified_part_info_arg, - bool ignore_arg) + bool ignore_arg, bool error_non_empty) : create_info(create_info_arg), alter_info(alter_info_arg), key_info_buffer(key_info_arg), @@ -4819,7 +4819,8 @@ Alter_inplace_info::Alter_inplace_info(HA_CREATE_INFO *create_info_arg, modified_part_info(modified_part_info_arg), ignore(ignore_arg), online(false), - unsupported_reason(nullptr) + unsupported_reason(nullptr), + error_if_not_empty(error_non_empty) {} void Alter_inplace_info::report_unsupported_error(const char *not_supported, diff --git a/sql/handler.h b/sql/handler.h index 316f7d3c796..0fa492a2a6f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2496,11 +2496,14 @@ public: */ const char *unsupported_reason; + /** true when InnoDB should abort the alter when table is not empty */ + bool error_if_not_empty; + Alter_inplace_info(HA_CREATE_INFO *create_info_arg, Alter_info *alter_info_arg, KEY *key_info_arg, uint key_count_arg, partition_info *modified_part_info_arg, - bool ignore_arg); + bool ignore_arg, bool error_non_empty); ~Alter_inplace_info() { diff --git a/sql/item_func.cc b/sql/item_func.cc index ead72007518..52eeaf10cd5 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2572,19 +2572,20 @@ void Item_func_rand::seed_random(Item *arg) TODO: do not do reinit 'rand' for every execute of PS/SP if args[0] is a constant. */ - uint32 tmp; + uint32 tmp= (uint32) arg->val_int(); #ifdef WITH_WSREP - THD *thd= current_thd; - if (WSREP(thd)) + if (WSREP_ON) { - if (wsrep_thd_is_applying(thd)) - tmp= thd->wsrep_rand; - else - tmp= thd->wsrep_rand= (uint32) arg->val_int(); - } - else + THD *thd= current_thd; + if (WSREP(thd)) + { + if (wsrep_thd_is_applying(thd)) + tmp= thd->wsrep_rand; + else + thd->wsrep_rand= tmp; + } + } #endif /* WITH_WSREP */ - tmp= (uint32) arg->val_int(); my_rnd_init(rand, (uint32) (tmp*0x10001L+55555555L), (uint32) (tmp*0x10000001L)); diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 9c69b67bce1..b6c626e7735 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -2120,7 +2120,8 @@ Query_log_event::do_shall_skip(rpl_group_info *rgi) } } #ifdef WITH_WSREP - else if (WSREP(thd) && wsrep_mysql_replication_bundle && opt_slave_domain_parallel_threads == 0 && + else if (WSREP(thd) && wsrep_mysql_replication_bundle && + opt_slave_domain_parallel_threads == 0 && thd->wsrep_mysql_replicated > 0 && (is_begin() || is_commit())) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f6aac3adfd8..1c3af7349b9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2020, MariaDB Corporation. + Copyright (c) 2008, 2020, 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 @@ -1947,10 +1947,10 @@ static void mysqld_exit(int exit_code) set_malloc_size_cb(NULL); if (global_status_var.global_memory_used) { -#ifdef SAFEMALLOC - sf_report_leaked_memory(0); -#endif - DBUG_SLOW_ASSERT(global_status_var.global_memory_used == 0); + fprintf(stderr, "Warning: Memory not freed: %lld\n", + (longlong) global_status_var.global_memory_used); + if (exit_code == 0) + SAFEMALLOC_REPORT_MEMORY(0); } cleanup_tls(); DBUG_LEAVE; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 71d527c6e43..4271340340b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1450,9 +1450,12 @@ class User_table_json: public User_table bool set_auth(const ACL_USER &u) const { - StringBuffer<JSON_SIZE> json(m_table->field[2]->charset()); - if (u.nauth == 1) + size_t array_len; + const char *array; + if (u.nauth == 1 && get_value("auth_or", JSV_ARRAY, &array, &array_len)) return set_auth1(u, 0); + + StringBuffer<JSON_SIZE> json(m_table->field[2]->charset()); bool top_done = false; json.append('['); for (uint i=0; i < u.nauth; i++) @@ -1949,10 +1952,13 @@ class Grant_tables int res= really_open(thd, first, &counter); /* if User_table_json wasn't found, let's try User_table_tabular */ - if (!res && (which_tables & Table_user) && !(tables[USER_TABLE].table)) + if (!res && (which_tables & Table_user) && !tables[USER_TABLE].table) { uint unused; TABLE_LIST *tl= tables + USER_TABLE; + TABLE *backup_open_tables= thd->open_tables; + thd->set_open_tables(NULL); + tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME_USER, NULL, lock_type); tl->open_type= OT_BASE_ONLY; @@ -1961,6 +1967,12 @@ class Grant_tables p_user_table= &m_user_table_tabular; counter++; res= really_open(thd, tl, &unused); + thd->set_open_tables(backup_open_tables); + if (tables[USER_TABLE].table) + { + tables[USER_TABLE].table->next= backup_open_tables; + thd->set_open_tables(tables[USER_TABLE].table); + } } if (res) DBUG_RETURN(res); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e22a23d197e..08dd03dc7f6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB + Copyright (c) 2010, 2020, 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 diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e7fbae9e0f7..1054796d170 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10332,7 +10332,7 @@ do_continue:; Alter_inplace_info ha_alter_info(create_info, alter_info, key_info, key_count, IF_PARTITIONING(thd->work_part_info, NULL), - ignore); + ignore, alter_ctx.error_if_not_empty); TABLE_SHARE altered_share; TABLE altered_table; bool use_inplace= true; @@ -10863,7 +10863,8 @@ err_new_table_cleanup: thd->get_stmt_da()->current_row_for_warning())) { Abort_on_warning_instant_set aws(thd, true); - alter_ctx.report_implicit_default_value_error(thd, new_table->s); + alter_ctx.report_implicit_default_value_error(thd, new_table + ? new_table->s : table->s); } if (new_table) diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index b0a5d38d5eb..213b1baf5ab 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012, 2020, MariaDB Corporation. +/* Copyright (C) 2012, 2020, 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 @@ -50,7 +50,6 @@ static void threadpool_remove_connection(THD *thd); static int threadpool_process_request(THD *thd); static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data); -extern "C" pthread_key(struct st_my_thread_var*, THR_KEY_mysys); extern bool do_command(THD*); static inline TP_connection *get_TP_connection(THD *thd) @@ -89,14 +88,14 @@ struct Worker_thread_context void save() { - psi_thread = PSI_CALL_get_thread(); - mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys); + psi_thread= PSI_CALL_get_thread(); + mysys_var= my_thread_var; } void restore() { PSI_CALL_set_thread(psi_thread); - pthread_setspecific(THR_KEY_mysys,mysys_var); + set_mysys_var(mysys_var); pthread_setspecific(THR_THD, 0); } }; @@ -147,7 +146,7 @@ static void thread_attach(THD* thd) attaching the thd. */ wsrep_wait_rollback_complete_and_acquire_ownership(thd); #endif /* WITH_WSREP */ - pthread_setspecific(THR_KEY_mysys,thd->mysys_var); + set_mysys_var(thd->mysys_var); thd->thread_stack=(char*)&thd; thd->store_globals(); PSI_CALL_set_thread(thd->get_psi()); @@ -231,9 +230,9 @@ static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data) Store them in THD. */ - pthread_setspecific(THR_KEY_mysys, 0); + set_mysys_var(NULL); my_thread_init(); - st_my_thread_var* mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys); + st_my_thread_var* mysys_var= my_thread_var; PSI_CALL_set_thread(PSI_CALL_new_thread(key_thread_one_connection, connect, 0)); if (!mysys_var ||!(thd= connect->create_thd(NULL))) { diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index ffc6acc8bd9..6405a5d2cb7 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 SkySQL Ab. +/* Copyright (C) 2014, 2020, 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 @@ -136,6 +136,10 @@ my_bool wsrep_get_debug() void wsrep_commit_ordered(THD* ) { } +void wsrep_log(void (*)(const char *, ...), const char *, ...) +{ +} + my_bool wsrep_thd_is_applying(const THD*) { return 0;} diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index f7b1d05854f..e57bb4d796e 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -25,6 +25,7 @@ Created April 08, 2011 Vasil Dimov *******************************************************/ #include "my_global.h" +#include "mysqld.h" #include "my_sys.h" #include "mysql/psi/mysql_stage.h" @@ -175,7 +176,7 @@ get_buf_dump_dir() /* The dump file should be created in the default data directory if innodb_data_home_dir is set as an empty string. */ - if (strcmp(srv_data_home, "") == 0) { + if (!*srv_data_home) { dump_dir = fil_path_to_mysql_datadir; } else { dump_dir = srv_data_home; @@ -187,16 +188,14 @@ get_buf_dump_dir() /** Generate the path to the buffer pool dump/load file. @param[out] path generated path @param[in] path_size size of 'path', used as in snprintf(3). */ -static -void -buf_dump_generate_path( - char* path, - size_t path_size) +static void buf_dump_generate_path(char *path, size_t path_size) { char buf[FN_REFLEN]; + mysql_mutex_lock(&LOCK_global_system_variables); snprintf(buf, sizeof(buf), "%s%c%s", get_buf_dump_dir(), OS_PATH_SEPARATOR, srv_buf_dump_filename); + mysql_mutex_unlock(&LOCK_global_system_variables); os_file_type_t type; bool exists = false; diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index f1b3dbaff0b..0b2e28b6476 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -32,6 +32,7 @@ Created Apr 25, 2012 Vasil Dimov #include "srv0start.h" #include "fil0fil.h" #ifdef WITH_WSREP +# include "trx0trx.h" # include "mysql/service_wsrep.h" # include "wsrep.h" # include "log.h" @@ -137,12 +138,12 @@ dict_stats_recalc_pool_add( schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table @param[in] thd current session */ -void dict_stats_update_if_needed(dict_table_t* table, THD* thd) +void dict_stats_update_if_needed(dict_table_t *table, const trx_t &trx) #else /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table */ -void dict_stats_update_if_needed_func(dict_table_t* table) +void dict_stats_update_if_needed_func(dict_table_t *table) #endif { ut_ad(table->stat_initialized); @@ -169,9 +170,9 @@ void dict_stats_update_if_needed_func(dict_table_t* table) generated row locks and allow BF thread lock waits to be enqueued at head of waiting queue. */ - if (wsrep_on(thd) - && !wsrep_thd_is_applying(thd) - && wsrep_thd_is_BF(thd, 0)) { + if (trx.is_wsrep() + && !wsrep_thd_is_applying(trx.mysql_thd) + && wsrep_thd_is_BF(trx.mysql_thd, 0)) { WSREP_DEBUG("Avoiding background statistics" " calculation for table %s.", table->name.m_name); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 59b7ea059fa..1a9a75eaa76 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -444,9 +444,9 @@ fts_read_stopword( /******************************************************************//** Load user defined stopword from designated user table -@return TRUE if load operation is successful */ +@return whether the operation is successful */ static -ibool +bool fts_load_user_stopword( /*===================*/ fts_t* fts, /*!< in: FTS struct */ @@ -454,27 +454,26 @@ fts_load_user_stopword( name */ fts_stopword_t* stopword_info) /*!< in: Stopword info */ { - pars_info_t* info; - que_t* graph; - dberr_t error = DB_SUCCESS; - ibool ret = TRUE; - trx_t* trx; - ibool has_lock = fts->dict_locked; - - trx = trx_create(); - trx->op_info = "Load user stopword table into FTS cache"; - - if (!has_lock) { + if (!fts->dict_locked) { mutex_enter(&dict_sys.mutex); } - /* Validate the user table existence and in the right - format */ + /* Validate the user table existence in the right format */ + bool ret= false; stopword_info->charset = fts_valid_stopword_table(stopword_table_name); if (!stopword_info->charset) { - ret = FALSE; - goto cleanup; - } else if (!stopword_info->cached_stopword) { +cleanup: + if (!fts->dict_locked) { + mutex_exit(&dict_sys.mutex); + } + + return ret; + } + + trx_t* trx = trx_create(); + trx->op_info = "Load user stopword table into FTS cache"; + + if (!stopword_info->cached_stopword) { /* Create the stopword RB tree with the stopword column charset. All comparison will use this charset */ stopword_info->cached_stopword = rbt_create_arg_cmp( @@ -483,14 +482,14 @@ fts_load_user_stopword( } - info = pars_info_create(); + pars_info_t* info = pars_info_create(); pars_info_bind_id(info, TRUE, "table_stopword", stopword_table_name); pars_info_bind_function(info, "my_func", fts_read_stopword, stopword_info); - graph = fts_parse_sql_no_dict_lock( + que_t* graph = fts_parse_sql_no_dict_lock( info, "DECLARE FUNCTION my_func;\n" "DECLARE CURSOR c IS" @@ -508,14 +507,13 @@ fts_load_user_stopword( "CLOSE c;"); for (;;) { - error = fts_eval_sql(trx, graph); + dberr_t error = fts_eval_sql(trx, graph); if (error == DB_SUCCESS) { fts_sql_commit(trx); stopword_info->status = STOPWORD_USER_TABLE; break; } else { - fts_sql_rollback(trx); if (error == DB_LOCK_WAIT_TIMEOUT) { @@ -534,14 +532,9 @@ fts_load_user_stopword( } que_graph_free(graph); - -cleanup: - if (!has_lock) { - mutex_exit(&dict_sys.mutex); - } - trx_free(trx); - return(ret); + ret = true; + goto cleanup; } /******************************************************************//** @@ -3359,7 +3352,7 @@ fts_add_doc_from_tuple( if (table->fts->cache->stopword_info.status & STOPWORD_NOT_INIT) { fts_load_stopword(table, NULL, NULL, - NULL, TRUE, TRUE); + true, true); } fts_cache_add_doc( @@ -3523,8 +3516,8 @@ fts_add_doc_by_id( if (table->fts->cache->stopword_info.status & STOPWORD_NOT_INIT) { - fts_load_stopword(table, NULL, NULL, - NULL, TRUE, TRUE); + fts_load_stopword(table, NULL, + NULL, true, true); } fts_cache_add_doc( @@ -7045,20 +7038,18 @@ This function loads the stopword into the FTS cache. It also records/fetches stopword configuration to/from FTS configure table, depending on whether we are creating or reloading the FTS. -@return TRUE if load operation is successful */ -ibool +@return true if load operation is successful */ +bool fts_load_stopword( /*==============*/ const dict_table_t* table, /*!< in: Table with FTS */ trx_t* trx, /*!< in: Transactions */ - const char* global_stopword_table, /*!< in: Global stopword table - name */ const char* session_stopword_table, /*!< in: Session stopword table name */ - ibool stopword_is_on, /*!< in: Whether stopword + bool stopword_is_on, /*!< in: Whether stopword option is turned on/off */ - ibool reload) /*!< in: Whether it is + bool reload) /*!< in: Whether it is for reloading FTS table */ { fts_table_t fts_table; @@ -7074,9 +7065,8 @@ fts_load_stopword( cache = table->fts->cache; - if (!reload && !(cache->stopword_info.status - & STOPWORD_NOT_INIT)) { - return(TRUE); + if (!reload && !(cache->stopword_info.status & STOPWORD_NOT_INIT)) { + return true; } if (!trx) { @@ -7126,12 +7116,11 @@ fts_load_stopword( goto cleanup; } - if (strlen((char*) str.f_str) > 0) { + if (*str.f_str) { stopword_to_use = (const char*) str.f_str; } } else { - stopword_to_use = (session_stopword_table) - ? session_stopword_table : global_stopword_table; + stopword_to_use = session_stopword_table; } if (stopword_to_use @@ -7169,7 +7158,7 @@ cleanup: &my_charset_latin1); } - return(error == DB_SUCCESS); + return error == DB_SUCCESS; } /**********************************************************************//** @@ -7370,7 +7359,7 @@ fts_init_index( } else { if (table->fts->cache->stopword_info.status & STOPWORD_NOT_INIT) { - fts_load_stopword(table, NULL, NULL, NULL, TRUE, TRUE); + fts_load_stopword(table, NULL, NULL, true, true); } for (ulint i = 0; i < ib_vector_size(cache->get_docs); ++i) { diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 9d42ed8cca1..8da1960601f 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -683,6 +683,121 @@ rtr_page_get_father( mem_heap_free(heap); } +/********************************************************************//** +Returns the upper level node pointer to a R-Tree page. It is assumed +that mtr holds an x-latch on the tree. */ +static void rtr_get_father_node( + dict_index_t* index, /*!< in: index */ + ulint level, /*!< in: the tree level of search */ + const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in + tuple must be set so that it cannot get + compared to the node ptr page number field! */ + btr_cur_t* sea_cur,/*!< in: search cursor */ + btr_cur_t* btr_cur,/*!< in/out: tree cursor; the cursor page is + s- or x-latched, but see also above! */ + ulint page_no,/*!< Current page no */ + mtr_t* mtr) /*!< in: mtr */ +{ + mem_heap_t* heap = NULL; + bool ret = false; + const rec_t* rec; + ulint n_fields; + bool new_rtr = false; + + /* Try to optimally locate the parent node. Level should always + less than sea_cur->tree_height unless the root is splitting */ + if (sea_cur && sea_cur->tree_height > level) { + + ut_ad(mtr_memo_contains_flagged(mtr, + dict_index_get_lock(index), + MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); + ret = rtr_cur_restore_position( + BTR_CONT_MODIFY_TREE, sea_cur, level, mtr); + + /* Once we block shrink tree nodes while there are + active search on it, this optimal locating should always + succeeds */ + ut_ad(ret); + + if (ret) { + btr_pcur_t* r_cursor = rtr_get_parent_cursor( + sea_cur, level, false); + + rec = btr_pcur_get_rec(r_cursor); + + ut_ad(r_cursor->rel_pos == BTR_PCUR_ON); + page_cur_position(rec, + btr_pcur_get_block(r_cursor), + btr_cur_get_page_cur(btr_cur)); + btr_cur->rtr_info = sea_cur->rtr_info; + btr_cur->tree_height = sea_cur->tree_height; + ut_ad(rtr_compare_cursor_rec( + index, btr_cur, page_no, &heap)); + goto func_exit; + } + } + + /* We arrive here in one of two scenario + 1) check table and btr_valide + 2) index root page being raised */ + ut_ad(!sea_cur || sea_cur->tree_height == level); + + if (btr_cur->rtr_info) { + rtr_clean_rtr_info(btr_cur->rtr_info, true); + } else { + new_rtr = true; + } + + btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index); + + if (sea_cur && sea_cur->tree_height == level) { + /* root split, and search the new root */ + btr_cur_search_to_nth_level( + index, level, tuple, PAGE_CUR_RTREE_LOCATE, + BTR_CONT_MODIFY_TREE, btr_cur, 0, + __FILE__, __LINE__, mtr); + + } else { + /* btr_validate */ + ut_ad(level >= 1); + ut_ad(!sea_cur); + + btr_cur_search_to_nth_level( + index, level, tuple, PAGE_CUR_RTREE_LOCATE, + BTR_CONT_MODIFY_TREE, btr_cur, 0, + __FILE__, __LINE__, mtr); + + rec = btr_cur_get_rec(btr_cur); + n_fields = dtuple_get_n_fields_cmp(tuple); + + if (page_rec_is_infimum(rec) + || (btr_cur->low_match != n_fields)) { + ret = rtr_pcur_getnext_from_path( + tuple, PAGE_CUR_RTREE_LOCATE, btr_cur, + level, BTR_CONT_MODIFY_TREE, + true, mtr); + + ut_ad(ret && btr_cur->low_match == n_fields); + } + } + + ret = rtr_compare_cursor_rec( + index, btr_cur, page_no, &heap); + + ut_ad(ret); + +func_exit: + if (heap) { + mem_heap_free(heap); + } + + if (new_rtr && btr_cur->rtr_info) { + rtr_clean_rtr_info(btr_cur->rtr_info, true); + btr_cur->rtr_info = NULL; + } +} + /** Returns the upper level node pointer to a R-Tree page. It is assumed that mtr holds an SX-latch or X-latch on the tree. @return rec_get_offsets() of the node pointer record */ @@ -803,123 +918,6 @@ rtr_page_get_father_block( cursor, mtr)); } -/********************************************************************//** -Returns the upper level node pointer to a R-Tree page. It is assumed -that mtr holds an x-latch on the tree. */ -void -rtr_get_father_node( -/*================*/ - dict_index_t* index, /*!< in: index */ - ulint level, /*!< in: the tree level of search */ - const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in - tuple must be set so that it cannot get - compared to the node ptr page number field! */ - btr_cur_t* sea_cur,/*!< in: search cursor */ - btr_cur_t* btr_cur,/*!< in/out: tree cursor; the cursor page is - s- or x-latched, but see also above! */ - ulint page_no,/*!< Current page no */ - mtr_t* mtr) /*!< in: mtr */ -{ - mem_heap_t* heap = NULL; - bool ret = false; - const rec_t* rec; - ulint n_fields; - bool new_rtr = false; - - /* Try to optimally locate the parent node. Level should always - less than sea_cur->tree_height unless the root is splitting */ - if (sea_cur && sea_cur->tree_height > level) { - - ut_ad(mtr_memo_contains_flagged(mtr, - dict_index_get_lock(index), - MTR_MEMO_X_LOCK - | MTR_MEMO_SX_LOCK)); - ret = rtr_cur_restore_position( - BTR_CONT_MODIFY_TREE, sea_cur, level, mtr); - - /* Once we block shrink tree nodes while there are - active search on it, this optimal locating should always - succeeds */ - ut_ad(ret); - - if (ret) { - btr_pcur_t* r_cursor = rtr_get_parent_cursor( - sea_cur, level, false); - - rec = btr_pcur_get_rec(r_cursor); - - ut_ad(r_cursor->rel_pos == BTR_PCUR_ON); - page_cur_position(rec, - btr_pcur_get_block(r_cursor), - btr_cur_get_page_cur(btr_cur)); - btr_cur->rtr_info = sea_cur->rtr_info; - btr_cur->tree_height = sea_cur->tree_height; - ut_ad(rtr_compare_cursor_rec( - index, btr_cur, page_no, &heap)); - goto func_exit; - } - } - - /* We arrive here in one of two scenario - 1) check table and btr_valide - 2) index root page being raised */ - ut_ad(!sea_cur || sea_cur->tree_height == level); - - if (btr_cur->rtr_info) { - rtr_clean_rtr_info(btr_cur->rtr_info, true); - } else { - new_rtr = true; - } - - btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index); - - if (sea_cur && sea_cur->tree_height == level) { - /* root split, and search the new root */ - btr_cur_search_to_nth_level( - index, level, tuple, PAGE_CUR_RTREE_LOCATE, - BTR_CONT_MODIFY_TREE, btr_cur, 0, - __FILE__, __LINE__, mtr); - - } else { - /* btr_validate */ - ut_ad(level >= 1); - ut_ad(!sea_cur); - - btr_cur_search_to_nth_level( - index, level, tuple, PAGE_CUR_RTREE_LOCATE, - BTR_CONT_MODIFY_TREE, btr_cur, 0, - __FILE__, __LINE__, mtr); - - rec = btr_cur_get_rec(btr_cur); - n_fields = dtuple_get_n_fields_cmp(tuple); - - if (page_rec_is_infimum(rec) - || (btr_cur->low_match != n_fields)) { - ret = rtr_pcur_getnext_from_path( - tuple, PAGE_CUR_RTREE_LOCATE, btr_cur, - level, BTR_CONT_MODIFY_TREE, - true, mtr); - - ut_ad(ret && btr_cur->low_match == n_fields); - } - } - - ret = rtr_compare_cursor_rec( - index, btr_cur, page_no, &heap); - - ut_ad(ret); - -func_exit: - if (heap) { - mem_heap_free(heap); - } - - if (new_rtr && btr_cur->rtr_info) { - rtr_clean_rtr_info(btr_cur->rtr_info, true); - btr_cur->rtr_info = NULL; - } -} - /*******************************************************************//** Create a RTree search info structure */ rtr_info_t* diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b8ff67d3faa..f46b3087e57 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2020, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. @@ -1560,20 +1560,14 @@ thd_trx_is_auto_commit( /** Enter InnoDB engine after checking the max number of user threads allowed, else the thread is put into sleep. @param[in,out] prebuilt row prebuilt handler */ -static inline -void -innobase_srv_conc_enter_innodb( - row_prebuilt_t* prebuilt) +static inline void innobase_srv_conc_enter_innodb(row_prebuilt_t *prebuilt) { + trx_t* trx = prebuilt->trx; + #ifdef WITH_WSREP - if (wsrep_on(prebuilt->trx->mysql_thd) && - wsrep_thd_is_BF(prebuilt->trx->mysql_thd, FALSE)) { - return; - } + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ - trx_t* trx = prebuilt->trx; - if (srv_thread_concurrency) { if (trx->n_tickets_to_enter_innodb > 0) { @@ -1600,22 +1594,16 @@ innobase_srv_conc_enter_innodb( /** Note that the thread wants to leave InnoDB only if it doesn't have any spare tickets. @param[in,out] m_prebuilt row prebuilt handler */ -static inline -void -innobase_srv_conc_exit_innodb( - row_prebuilt_t* prebuilt) +static inline void innobase_srv_conc_exit_innodb(row_prebuilt_t *prebuilt) { ut_ad(!sync_check_iterate(sync_check())); + trx_t* trx = prebuilt->trx; + #ifdef WITH_WSREP - if (wsrep_on(prebuilt->trx->mysql_thd) && - wsrep_thd_is_BF(prebuilt->trx->mysql_thd, FALSE)) { - return; - } + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ - trx_t* trx = prebuilt->trx; - /* This is to avoid making an unnecessary function call. */ if (trx->declared_to_be_inside_innodb && trx->n_tickets_to_enter_innodb == 0) { @@ -2485,6 +2473,9 @@ innobase_trx_init( trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS); +#ifdef WITH_WSREP + trx->wsrep = wsrep_on(thd); +#endif DBUG_VOID_RETURN; } @@ -4142,19 +4133,17 @@ innobase_commit_low( trx_t* trx) /*!< in: transaction handle */ { #ifdef WITH_WSREP - THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; - if (wsrep_on(thd)) { + if (trx->is_wsrep()) { #ifdef WSREP_PROC_INFO char info[64]; info[sizeof(info) - 1] = '\0'; snprintf(info, sizeof(info) - 1, "innobase_commit_low():trx_commit_for_mysql(%lld)", - (long long) wsrep_thd_trx_seqno(thd)); - tmp = thd_proc_info(thd, info); - + (long long) wsrep_thd_trx_seqno(trx->mysql_thd)); + tmp = thd_proc_info(trx->mysql_thd, info); #else - tmp = thd_proc_info(thd, "innobase_commit_low()"); + tmp = thd_proc_info(trx->mysql_thd, "innobase_commit_low()"); #endif /* WSREP_PROC_INFO */ } #endif /* WITH_WSREP */ @@ -4164,7 +4153,7 @@ innobase_commit_low( } trx->will_lock = 0; #ifdef WITH_WSREP - if (wsrep_on(thd)) { thd_proc_info(thd, tmp); } + if (trx->is_wsrep()) { thd_proc_info(trx->mysql_thd, tmp); } #endif /* WITH_WSREP */ } @@ -4277,7 +4266,7 @@ innobase_commit_ordered_2( #ifdef WITH_WSREP /* If the transaction is not run in 2pc, we must assign wsrep XID here in order to get it written in rollback segment. */ - if (wsrep_on(thd)) { + if (trx->is_wsrep()) { thd_get_xid(thd, (MYSQL_XID*)trx->xid); } #endif /* WITH_WSREP */ @@ -4856,28 +4845,25 @@ UNIV_INTERN void lock_cancel_waiting_and_release(lock_t* lock); /** Cancel any pending lock request associated with the current THD. @sa THD::awake() @sa ha_kill_query() */ -static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) +static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) { - DBUG_ENTER("innobase_kill_query"); + DBUG_ENTER("innobase_kill_query"); + + if (trx_t *trx= thd_to_trx(thd)) + { + ut_ad(trx->mysql_thd == thd); #ifdef WITH_WSREP - if (wsrep_on(thd) && wsrep_thd_is_aborting(thd)) { - /* if victim has been signaled by BF thread and/or aborting - is already progressing, following query aborting is not necessary - any more. - Also, BF thread should own trx mutex for the victim, which would - conflict with trx_mutex_enter() below - */ - DBUG_VOID_RETURN; - } + if (trx->is_wsrep() && wsrep_thd_is_aborting(thd)) + /* if victim has been signaled by BF thread and/or aborting is already + progressing, following query aborting is not necessary any more. + Also, BF thread should own trx mutex for the victim. */ + DBUG_VOID_RETURN; #endif /* WITH_WSREP */ + /* Cancel a pending lock request if there are any */ + lock_trx_handle_wait(trx); + } - if (trx_t* trx = thd_to_trx(thd)) { - ut_ad(trx->mysql_thd == thd); - /* Cancel a pending lock request if there are any */ - lock_trx_handle_wait(trx); - } - - DBUG_VOID_RETURN; + DBUG_VOID_RETURN; } @@ -7680,7 +7666,7 @@ ha_innobase::write_row( { dberr_t error; #ifdef WITH_WSREP - ibool auto_inc_inserted= FALSE; /* if NULL was inserted */ + bool wsrep_auto_inc_inserted= false; #endif int error_result = 0; bool auto_inc_used = false; @@ -7710,7 +7696,9 @@ ha_innobase::write_row( m_prebuilt->autoinc_error = DB_SUCCESS; #ifdef WITH_WSREP - auto_inc_inserted= (table->next_number_field->val_int() == 0); + wsrep_auto_inc_inserted = trx->is_wsrep() + && wsrep_drupal_282555_workaround + && table->next_number_field->val_int() == 0; #endif if ((error_result = update_auto_increment())) { @@ -7807,18 +7795,14 @@ ha_innobase::write_row( m_prebuilt->autoinc_offset, m_prebuilt->autoinc_increment); - if (wsrep_on(m_user_thd) && - auto_inc_inserted && - wsrep_drupal_282555_workaround && + if (wsrep_auto_inc_inserted && wsrep_thd_retry_counter(m_user_thd) == 0 && !thd_test_options(m_user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { WSREP_DEBUG( "retrying insert: %s", - (*wsrep_thd_query(m_user_thd)) ? - wsrep_thd_query(m_user_thd) : - (char *)"void"); + wsrep_thd_query(m_user_thd)); error= DB_SUCCESS; wsrep_thd_self_abort(m_user_thd); innobase_srv_conc_exit_innodb( @@ -7858,7 +7842,7 @@ set_max_autoinc: m_prebuilt autoinc values don't get properly assigned. Fetch values from server side. */ - if (wsrep_on(m_user_thd) && + if (trx->is_wsrep() && wsrep_thd_is_applying(m_user_thd)) { wsrep_thd_auto_increment_variables( @@ -7905,8 +7889,7 @@ report_error: error, m_prebuilt->table->flags, m_user_thd); #ifdef WITH_WSREP - if (!error_result - && wsrep_on(m_user_thd) + if (!error_result && trx->is_wsrep() && wsrep_thd_is_local(m_user_thd) && !wsrep_thd_ignore_table(m_user_thd) && !wsrep_consistency_check(m_user_thd) @@ -7918,10 +7901,9 @@ report_error: NULL)) { DBUG_PRINT("wsrep", ("row key failed")); error_result = HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + goto func_exit; } } -wsrep_error: #endif /* WITH_WSREP */ if (error_result == HA_FTS_INVALID_DOCID) { @@ -8574,8 +8556,7 @@ ha_innobase::update_row( m_prebuilt autoinc values don't get properly assigned. Fetch values from server side. */ - if (wsrep_on(m_user_thd) && - wsrep_thd_is_applying(m_user_thd)) + if (trx->is_wsrep() && wsrep_thd_is_applying(m_user_thd)) wsrep_thd_auto_increment_variables( m_user_thd, &offset, &increment); else @@ -8619,11 +8600,9 @@ func_exit: innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS - && wsrep_on(m_user_thd) + if (error == DB_SUCCESS && trx->is_wsrep() && wsrep_thd_is_local(m_user_thd) && !wsrep_thd_ignore_table(m_user_thd)) { - DBUG_PRINT("wsrep", ("update row key")); if (wsrep_append_keys(m_user_thd, @@ -8633,14 +8612,11 @@ func_exit: old_row, new_row)){ WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED"); DBUG_PRINT("wsrep", ("row key failed")); - err = HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } -wsrep_error: #endif /* WITH_WSREP */ - DBUG_RETURN(err); } @@ -8690,20 +8666,16 @@ ha_innobase::delete_row( innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS - && wsrep_on(m_user_thd) + if (error == DB_SUCCESS && trx->is_wsrep() && wsrep_thd_is_local(m_user_thd) && !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, record, NULL)) { DBUG_PRINT("wsrep", ("delete fail")); - error = (dberr_t) HA_ERR_INTERNAL_ERROR; - goto wsrep_error; + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } } -wsrep_error: #endif /* WITH_WSREP */ DBUG_RETURN(convert_error_code_to_mysql( error, m_prebuilt->table->flags, m_user_thd)); @@ -9879,29 +9851,26 @@ wsrep_append_foreign_key( Wsrep_service_key_type key_type) /*!< in: access type of this key (shared, exclusive, reference...) */ { - ut_a(trx); - THD* thd = (THD*)trx->mysql_thd; - ulint rcode = DB_SUCCESS; - char cache_key[513] = {'\0'}; - size_t cache_key_len=0; - - if (!wsrep_on(trx->mysql_thd) || - wsrep_thd_is_local(trx->mysql_thd) == false) { + if (!trx->is_wsrep() || !wsrep_thd_is_local(trx->mysql_thd)) { return DB_SUCCESS; } - if (!thd || !foreign || + THD* thd = trx->mysql_thd; + + if (!foreign || (!foreign->referenced_table && !foreign->foreign_table)) { WSREP_INFO("FK: %s missing in: %s", - (!thd) ? "thread" : - ((!foreign) ? "constraint" : - ((!foreign->referenced_table) ? + (!foreign ? "constraint" : + (!foreign->referenced_table ? "referenced table" : "foreign table")), - (thd && wsrep_thd_query(thd)) ? - wsrep_thd_query(thd) : "void"); + wsrep_thd_query(thd)); return DB_ERROR; } + ulint rcode = DB_SUCCESS; + char cache_key[513] = {'\0'}; + size_t cache_key_len = 0; + if ( !((referenced) ? foreign->referenced_table : foreign->foreign_table)) { WSREP_DEBUG("pulling %s table into cache", @@ -11417,10 +11386,17 @@ innobase_fts_load_stopword( trx_t* trx, /*!< in: transaction */ THD* thd) /*!< in: current thread */ { - return(fts_load_stopword(table, trx, - innobase_server_stopword_table, - THDVAR(thd, ft_user_stopword_table), - THDVAR(thd, ft_enable_stopword), FALSE)); + const char *stopword_table= THDVAR(thd, ft_user_stopword_table); + if (!stopword_table) + { + mysql_mutex_lock(&LOCK_global_system_variables); + if (innobase_server_stopword_table) + stopword_table= thd_strdup(thd, innobase_server_stopword_table); + mysql_mutex_unlock(&LOCK_global_system_variables); + } + + return fts_load_stopword(table, trx, stopword_table, + THDVAR(thd, ft_enable_stopword), false); } /** Parse the table name into normal name and remote path if needed. @@ -15832,9 +15808,7 @@ ha_innobase::external_lock( DBUG_PRINT("enter",("lock_type: %d", lock_type)); update_thd(thd); - - trx_t* trx = m_prebuilt->trx; - + trx_t* trx = m_prebuilt->trx; ut_ad(m_prebuilt->table); /* Statement based binlogging does not work in isolation level @@ -15849,25 +15823,20 @@ ha_innobase::external_lock( && thd_binlog_format(thd) == BINLOG_FORMAT_STMT && thd_binlog_filter_ok(thd) && thd_sqlcom_can_generate_row_events(thd)) { - - bool skip = false; - + bool skip = false; +#ifdef WITH_WSREP + skip = trx->is_wsrep() && !wsrep_thd_is_local(thd); +#endif /* WITH_WSREP */ /* used by test case */ DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;); if (!skip) { -#ifdef WITH_WSREP - if (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd)) { -#endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when" " transaction isolation level is" " READ COMMITTED or READ UNCOMMITTED."); DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ } } @@ -17587,7 +17556,6 @@ innodb_stopword_table_validate( char buff[STRING_BUFFER_USUAL_SIZE]; int len = sizeof(buff); trx_t* trx; - int ret = 1; ut_a(save != NULL); ut_a(value != NULL); @@ -17600,14 +17568,22 @@ innodb_stopword_table_validate( /* Validate the stopword table's (if supplied) existence and of the right format */ - if (!stopword_table_name - || fts_valid_stopword_table(stopword_table_name)) { - *static_cast<const char**>(save) = stopword_table_name; - ret = 0; - } + int ret = stopword_table_name && !fts_valid_stopword_table( + stopword_table_name); row_mysql_unlock_data_dictionary(trx); + if (!ret) { + if (stopword_table_name == buff) { + ut_ad(static_cast<size_t>(len) < sizeof buff); + stopword_table_name = thd_strmake(thd, + stopword_table_name, + len); + } + + *static_cast<const char**>(save) = stopword_table_name; + } + return(ret); } @@ -17636,9 +17612,10 @@ innodb_buffer_pool_size_update(THD*,st_mysql_sys_var*,void*, const void* save) static char* innodb_ft_aux_table; /** Update innodb_ft_aux_table_id on SET GLOBAL innodb_ft_aux_table. +@param[in,out] thd connection @param[out] save new value of innodb_ft_aux_table @param[in] value user-specified value */ -static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, +static int innodb_ft_aux_table_validate(THD *thd, st_mysql_sys_var*, void* save, st_mysql_value* value) { char buf[STRING_BUFFER_USUAL_SIZE]; @@ -17652,6 +17629,15 @@ static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, dict_table_close(table, FALSE, FALSE); if (id) { innodb_ft_aux_table_id = id; + if (table_name == buf) { + ut_ad(static_cast<size_t>(len) + < sizeof buf); + table_name = thd_strmake(thd, + table_name, + len); + } + + *static_cast<const char**>(save) = table_name; return 0; } @@ -18195,49 +18181,43 @@ exit: return; } -#ifdef _WIN32 -/*************************************************************//** -Validate if passed-in "value" is a valid value for -innodb_buffer_pool_filename. On Windows, file names with colon (:) -are not allowed. - -@return 0 for valid name */ -static -int -innodb_srv_buf_dump_filename_validate( -/*==================================*/ - THD* thd, /*!< in: thread handle */ - struct st_mysql_sys_var* var, /*!< in: pointer to system - variable */ - void* save, /*!< out: immediate result - for update function */ - struct st_mysql_value* value) /*!< in: incoming string */ +/** Validate SET GLOBAL innodb_buffer_pool_filename. +On Windows, file names with colon (:) are not allowed. +@param thd connection +@param save &srv_buf_dump_filename +@param value new value to be validated +@return 0 for valid name */ +static int innodb_srv_buf_dump_filename_validate(THD *thd, st_mysql_sys_var*, + void *save, + st_mysql_value *value) { - char buff[OS_FILE_MAX_PATH]; - int len = sizeof(buff); - - ut_a(save != NULL); - ut_a(value != NULL); + char buff[OS_FILE_MAX_PATH]; + int len= sizeof buff; - if (const char* buf_name = value->val_str(value, buff, &len)) { - if (is_filename_allowed(buf_name, len, FALSE)){ - *static_cast<const char**>(save) = buf_name; - return(0); - } else { - push_warning_printf(thd, - Sql_condition::WARN_LEVEL_WARN, - ER_WRONG_ARGUMENTS, - "InnoDB: innodb_buffer_pool_filename" - " cannot have colon (:) in the file name."); + if (const char *buf_name= value->val_str(value, buff, &len)) + { +#ifdef _WIN32 + if (!is_filename_allowed(buf_name, len, FALSE)) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: innodb_buffer_pool_filename " + "cannot have colon (:) in the file name."); + return 1; + } +#endif /* _WIN32 */ + if (buf_name == buff) + { + ut_ad(static_cast<size_t>(len) < sizeof buff); + buf_name= thd_strmake(thd, buf_name, len); + } - } - } + *static_cast<const char**>(save)= buf_name; + return 0; + } - return(1); + return 1; } -#else /* _WIN32 */ -# define innodb_srv_buf_dump_filename_validate NULL -#endif /* _WIN32 */ #ifdef UNIV_DEBUG static char* srv_buffer_pool_evict; @@ -18246,9 +18226,7 @@ static char* srv_buffer_pool_evict; Evict all uncompressed pages of compressed tables from the buffer pool. Keep the compressed pages in the buffer pool. @return whether all uncompressed pages were evicted */ -static MY_ATTRIBUTE((warn_unused_result)) -bool -innodb_buffer_pool_evict_uncompressed() +static bool innodb_buffer_pool_evict_uncompressed() { bool all_evicted = true; @@ -18263,8 +18241,13 @@ innodb_buffer_pool_evict_uncompressed() if (!buf_LRU_free_page(&block->page, false)) { all_evicted = false; + block = prev_block; + } else { + /* Because buf_LRU_free_page() may release + and reacquire buf_pool.mutex, prev_block + may be invalid. */ + block = UT_LIST_GET_LAST(buf_pool.unzip_LRU); } - block = prev_block; } mutex_exit(&buf_pool.mutex); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 8ee10849e43..932ec414231 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1872,6 +1872,62 @@ innobase_fts_check_doc_id_col( return(false); } +/** Check whether the table is empty. +@param[in] table table to be checked +@return true if table is empty */ +static bool innobase_table_is_empty(const dict_table_t *table) +{ + dict_index_t *clust_index= dict_table_get_first_index(table); + mtr_t mtr; + btr_pcur_t pcur; + buf_block_t *block; + page_cur_t *cur; + const rec_t *rec; + bool next_page= false; + + mtr.start(); + btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, + &pcur, true, 0, &mtr); + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + if (!rec_is_metadata(btr_pcur_get_rec(&pcur), *clust_index)) + btr_pcur_move_to_prev_on_page(&pcur); +scan_leaf: + cur= btr_pcur_get_page_cur(&pcur); + page_cur_move_to_next(cur); +next_page: + if (next_page) + { + uint32_t next_page_no= btr_page_get_next(page_cur_get_page(cur)); + if (next_page_no == FIL_NULL) + { + mtr.commit(); + return true; + } + + next_page= false; + block= page_cur_get_block(cur); + block= btr_block_get(*clust_index, next_page_no, BTR_SEARCH_LEAF, false, + &mtr); + btr_leaf_page_release(page_cur_get_block(cur), BTR_SEARCH_LEAF, &mtr); + page_cur_set_before_first(block, cur); + page_cur_move_to_next(cur); + } + + rec= page_cur_get_rec(cur); + if (rec_get_deleted_flag(rec, dict_table_is_comp(table))); + else if (!page_rec_is_supremum(rec)) + { + mtr.commit(); + return false; + } + else + { + next_page= true; + goto next_page; + } + goto scan_leaf; +} + /** Check if InnoDB supports a particular alter table in-place @param altered_table TABLE object for new version of table. @param ha_alter_info Structure describing changes to be done @@ -2095,6 +2151,13 @@ innodb_instant_alter_column_allowed_reason: DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } + /* '0000-00-00' value isn't allowed for datetime datatype + for newly added column when table is not empty */ + if (ha_alter_info->error_if_not_empty + && !innobase_table_is_empty(m_prebuilt->table)) { + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + const bool add_drop_v_cols = !!(ha_alter_info->handler_flags & (ALTER_ADD_VIRTUAL_COLUMN | ALTER_DROP_VIRTUAL_COLUMN @@ -6926,7 +6989,7 @@ op_ok: goto error_handling; } - trx_commit(ctx->trx); + ctx->trx->commit(); trx_start_for_ddl(ctx->trx, op); if (!ctx->new_table->fts @@ -10877,7 +10940,7 @@ ha_innobase::commit_inplace_alter_table( } else { ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); ut_ad(trx->has_logged()); - trx_commit(trx); + trx->commit(); } /* If server crashes here, the dictionary in diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index b803e9c5f49..cf0e2adab76 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -115,16 +115,16 @@ dict_stats_deinit( /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table -@param[in] thd current session */ -void dict_stats_update_if_needed(dict_table_t* table, THD* thd) - MY_ATTRIBUTE((nonnull(1))); +@param[in] trx transaction */ +void dict_stats_update_if_needed(dict_table_t *table, const trx_t &trx) + MY_ATTRIBUTE((nonnull)); #else /** Update the table modification counter and if necessary, schedule new estimates for table and index statistics to be calculated. @param[in,out] table persistent or temporary table */ -void dict_stats_update_if_needed_func(dict_table_t* table) +void dict_stats_update_if_needed_func(dict_table_t *table) MY_ATTRIBUTE((nonnull)); -# define dict_stats_update_if_needed(t,thd) dict_stats_update_if_needed_func(t) +# define dict_stats_update_if_needed(t,trx) dict_stats_update_if_needed_func(t) #endif /*********************************************************************//** diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 3a01d965a24..f83f65827d3 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 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 @@ -880,20 +880,18 @@ fts_valid_stopword_table( name */ /****************************************************************//** This function loads specified stopword into FTS cache -@return TRUE if success */ -ibool +@return true if success */ +bool fts_load_stopword( /*==============*/ const dict_table_t* table, /*!< in: Table with FTS */ trx_t* trx, /*!< in: Transaction */ - const char* global_stopword_table, /*!< in: Global stopword table - name */ const char* session_stopword_table, /*!< in: Session stopword table name */ - ibool stopword_is_on, /*!< in: Whether stopword + bool stopword_is_on, /*!< in: Whether stopword option is turned on/off */ - ibool reload); /*!< in: Whether it is during + bool reload); /*!< in: Whether it is during reload of FTS table */ /****************************************************************//** diff --git a/storage/innobase/include/gis0rtree.h b/storage/innobase/include/gis0rtree.h index 66929348c36..4bf1b4fedb7 100644 --- a/storage/innobase/include/gis0rtree.h +++ b/storage/innobase/include/gis0rtree.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, 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 @@ -162,22 +162,6 @@ rtr_ins_enlarge_mbr( btr_cur_t* cursor, /*!< in: btr cursor */ mtr_t* mtr); /*!< in: mtr */ -/********************************************************************//** -*/ -void -rtr_get_father_node( -/*================*/ - dict_index_t* index, /*!< in: index */ - ulint level, /*!< in: the tree level of search */ - const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in - tuple must be set so that it cannot get - compared to the node ptr page number field! */ - btr_cur_t* sea_cur,/*!< in: search cursor */ - btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is - s- or x-latched */ - ulint page_no,/*!< in: current page no */ - mtr_t* mtr); /*!< in: mtr */ - /**************************************************************//** push a nonleaf index node to the search path */ UNIV_INLINE diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index bdeba94e610..8be6f7a453d 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -980,10 +980,6 @@ std::string lock_get_info( const lock_t*); -/*******************************************************************//** -@return whether wsrep_on is true on trx->mysql_thd*/ -#define wsrep_on_trx(trx) wsrep_on((trx)->mysql_thd) - #endif /* WITH_WSREP */ #include "lock0lock.ic" diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 9022bd9f5ce..4c80ec9b9e7 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -298,16 +298,6 @@ row_upd_changes_some_index_ord_field_binary( /*========================================*/ const dict_table_t* table, /*!< in: table */ const upd_t* update);/*!< in: update vector for the row */ -/** Stores to the heap the row on which the node->pcur is positioned. -@param[in] node row update node -@param[in] thd mysql thread handle -@param[in,out] mysql_table NULL, or mysql table object when - user thread invokes dml */ -void -row_upd_store_row( - upd_node_t* node, - THD* thd, - TABLE* mysql_table); /***********************************************************//** Updates a row in a table. This is a high-level function used in SQL execution graphs. diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index ef47b5d395c..af96bb16434 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -180,17 +180,6 @@ trx_start_for_ddl_low( trx_start_for_ddl_low((t), (o)) #endif /* UNIV_DEBUG */ -/****************************************************************//** -Commits a transaction. */ -void -trx_commit( -/*=======*/ - trx_t* trx); /*!< in/out: transaction */ - -/** Commit a transaction and a mini-transaction. -@param[in,out] trx transaction -@param[in,out] mtr mini-transaction (NULL if no modifications) */ -void trx_commit_low(trx_t* trx, mtr_t* mtr); /**********************************************************************//** Does the transaction commit for MySQL. @return DB_SUCCESS or error number */ @@ -839,6 +828,13 @@ public: Transitions to COMMITTED are protected by trx_t::mutex. */ trx_state_t state; +#ifdef WITH_WSREP + /** whether wsrep_on(mysql_thd) held at the start of transaction */ + bool wsrep; + bool is_wsrep() const { return UNIV_UNLIKELY(wsrep); } +#else /* WITH_WSREP */ + bool is_wsrep() const { return false; } +#endif /* WITH_WSREP */ ReadView read_view; /*!< consistent read view used in the transaction, or NULL if not yet set */ @@ -890,10 +886,10 @@ public: defer flush of the logs to disk until after we release the mutex. */ - bool must_flush_log_later;/*!< this flag is set to TRUE in - trx_commit() if flush_log_later was - TRUE, and there were modifications by - the transaction; in that case we must + bool must_flush_log_later;/*!< set in commit() + if flush_log_later was + set and redo log was written; + in that case we will flush the log in trx_commit_complete_for_mysql() */ ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */ @@ -1105,11 +1101,22 @@ public: @param[in] table_id table identifier */ void evict_table(table_id_t table_id); + /** Finish rollback. + @return whether the rollback was completed normally + @retval false if the rollback was aborted by shutdown */ + inline bool rollback_finish(); +private: + /** Mark a transaction committed in the main memory data structures. */ + inline void commit_in_memory(const mtr_t *mtr); + /** Commit the transaction in a mini-transaction. + @param mtr mini-transaction (if there are any persistent modifications) */ + void commit_low(mtr_t *mtr= nullptr); +public: + /** Commit the transaction. */ + void commit(); - bool is_referenced() - { - return n_ref > 0; - } + + bool is_referenced() const { return n_ref > 0; } void reference() diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index d36bd822ab6..aad7dbe0b27 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1073,9 +1073,7 @@ wsrep_kill_victim( ut_ad(trx_mutex_own(lock->trx)); /* quit for native mysql */ - if (!wsrep_on(trx->mysql_thd)) { - return; - } + if (!trx->is_wsrep()) return; if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { return; @@ -1157,7 +1155,7 @@ lock_rec_other_has_conflicting( if (lock_rec_has_to_wait(true, trx, mode, lock, is_supremum)) { #ifdef WITH_WSREP - if (wsrep_on_trx(trx)) { + if (trx->is_wsrep()) { trx_mutex_enter(lock->trx); /* Below function will roll back either trx or lock->trx depending on priority of the @@ -1399,7 +1397,7 @@ lock_rec_create_low( ut_ad(index->table->get_ref_count() > 0 || !index->table->can_be_evicted); #ifdef WITH_WSREP - if (c_lock && wsrep_on_trx(trx) + if (c_lock && trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = (lock_t *)c_lock->hash; lock_t *prev = NULL; @@ -1805,8 +1803,7 @@ lock_rec_add_to_queue( #ifdef WITH_WSREP //ut_a(!other_lock || (wsrep_thd_is_BF(trx->mysql_thd, FALSE) && // wsrep_thd_is_BF(other_lock->trx->mysql_thd, TRUE))); - if (other_lock && - wsrep_on(trx->mysql_thd) && + if (other_lock && trx->is_wsrep() && !wsrep_thd_is_BF(trx->mysql_thd, FALSE) && !wsrep_thd_is_BF(other_lock->trx->mysql_thd, TRUE)) { @@ -3502,7 +3499,7 @@ lock_table_create( UT_LIST_ADD_LAST(trx->lock.trx_locks, lock); #ifdef WITH_WSREP - if (c_lock && wsrep_on_trx(trx)) { + if (c_lock && trx->is_wsrep()) { if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { ut_list_insert(table->locks, c_lock, lock, TableLockGetNode()); @@ -3732,7 +3729,7 @@ lock_table_enqueue_waiting( } #ifdef WITH_WSREP - if (trx->lock.was_chosen_as_deadlock_victim && wsrep_on_trx(trx)) { + if (trx->is_wsrep() && trx->lock.was_chosen_as_deadlock_victim) { return(DB_DEADLOCK); } #endif /* WITH_WSREP */ @@ -3805,7 +3802,7 @@ lock_table_other_has_incompatible( && (wait || !lock_get_wait(lock))) { #ifdef WITH_WSREP - if (wsrep_on(lock->trx->mysql_thd)) { + if (lock->trx->is_wsrep()) { if (wsrep_debug) { ib::info() << "WSREP: table lock abort for table:" << table->name.m_name; @@ -4872,7 +4869,7 @@ func_exit: explicit granted lock. */ #ifdef WITH_WSREP - if (wsrep_on(other_lock->trx->mysql_thd)) { + if (other_lock->trx->is_wsrep()) { if (!lock_get_wait(other_lock) ) { ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" << ((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << @@ -6754,7 +6751,7 @@ DeadlockChecker::trx_rollback() print("*** WE ROLL BACK TRANSACTION (1)\n"); #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && wsrep_thd_is_SR(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_thd_is_SR(trx->mysql_thd)) { wsrep_handle_SR_rollback(m_start->mysql_thd, trx->mysql_thd); } #endif @@ -6847,8 +6844,7 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx) print("*** WE ROLL BACK TRANSACTION (2)\n"); #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) - && wsrep_thd_is_SR(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_thd_is_SR(trx->mysql_thd)) { wsrep_handle_SR_rollback(trx->mysql_thd, victim_trx->mysql_thd); } diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index a9d0e0f501d..7b184495aa3 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -195,8 +195,7 @@ wsrep_is_BF_lock_timeout( const trx_t* trx, bool locked = true) { - if (wsrep_on_trx(trx) - && wsrep_thd_is_BF(trx->mysql_thd, FALSE) + if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, FALSE) && trx->error_state != DB_DEADLOCK) { ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id) << " query: " << wsrep_thd_query(trx->mysql_thd); @@ -403,8 +402,9 @@ lock_wait_suspend_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout #ifdef WITH_WSREP - && (!wsrep_on_trx(trx) || - (!wsrep_is_BF_lock_timeout(trx, false) && trx->error_state != DB_DEADLOCK)) + && (!trx->is_wsrep() + || (!wsrep_is_BF_lock_timeout(trx, false) + && trx->error_state != DB_DEADLOCK)) #endif /* WITH_WSREP */ ) { diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 6a493c856f6..22e63f44827 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1038,7 +1038,7 @@ row_prebuilt_free( rtr_clean_rtr_info(prebuilt->rtr_info, true); } if (prebuilt->table) { - dict_table_close(prebuilt->table, dict_locked, TRUE); + dict_table_close(prebuilt->table, dict_locked, FALSE); } mem_heap_free(prebuilt->heap); @@ -1574,7 +1574,7 @@ error_exit: memcpy(prebuilt->row_id, node->sys_buf, DATA_ROW_ID_LEN); } - dict_stats_update_if_needed(table, trx->mysql_thd); + dict_stats_update_if_needed(table, *trx); trx->op_info = ""; if (blob_heap != NULL) { @@ -1958,7 +1958,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) } if (update_statistics) { - dict_stats_update_if_needed(prebuilt->table, trx->mysql_thd); + dict_stats_update_if_needed(prebuilt->table, *trx); } else { /* Always update the table modification counter. */ prebuilt->table->stat_modified_counter++; @@ -2199,7 +2199,7 @@ static dberr_t row_update_vers_insert(que_thr_t* thr, upd_node_t* node) case DB_SUCCESS: srv_stats.n_rows_inserted.inc( static_cast<size_t>(trx->id)); - dict_stats_update_if_needed(table, trx->mysql_thd); + dict_stats_update_if_needed(table, *trx); goto exit; } } @@ -2293,8 +2293,7 @@ row_update_cascade_for_mysql( } if (stats) { - dict_stats_update_if_needed(node->table, - trx->mysql_thd); + dict_stats_update_if_needed(node->table, *trx); } else { /* Always update the table modification counter. */ diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index c05ab6bb73f..cbef674dfcb 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1051,8 +1051,7 @@ row_purge_record_func( if (node->table->stat_initialized && srv_stats_include_delete_marked) { dict_stats_update_if_needed( - node->table, - thr->graph->trx->mysql_thd); + node->table, *thr->graph->trx); } MONITOR_INC(MONITOR_N_DEL_ROW_PURGE); } diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 96ba4ae8a9b..d356ce75c20 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -578,8 +578,8 @@ row_undo_ins( already be holding dict_sys.mutex, which would be acquired when updating statistics. */ if (!dict_locked) { - dict_stats_update_if_needed( - node->table, node->trx->mysql_thd); + dict_stats_update_if_needed(node->table, + *node->trx); } } break; diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 4edab754a2b..d44c74b2236 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1399,8 +1399,8 @@ rollback_clust: already be holding dict_sys.mutex, which would be acquired when updating statistics. */ if (update_statistics && !dict_locked) { - dict_stats_update_if_needed( - node->table, node->trx->mysql_thd); + dict_stats_update_if_needed(node->table, + *node->trx); } else { node->table->stat_modified_counter++; } diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index cacb929eff4..a7ed35a645e 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -432,7 +432,7 @@ func_exit: inline bool wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) { - if (!wsrep_on_trx(trx)) { + if (!trx->is_wsrep()) { return false; } return que_node_get_type(node->common.parent) != QUE_NODE_UPDATE @@ -1884,6 +1884,7 @@ row_upd_store_v_row( @param[in] thd mysql thread handle @param[in,out] mysql_table NULL, or mysql table object when user thread invokes dml */ +static void row_upd_store_row( upd_node_t* node, @@ -2498,9 +2499,8 @@ check_fk: mtr_commit(mtr); - err = row_ins_clust_index_entry(index, entry, thr, node->upd_ext - ? node->upd_ext->n_ext - : dtuple_get_n_ext(entry)); + err = row_ins_clust_index_entry(index, entry, thr, + dtuple_get_n_ext(entry)); node->state = UPD_NODE_INSERT_CLUSTERED; mem_heap_free(heap); diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 1d38a6753be..ab51c6be79b 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -606,7 +606,6 @@ row_vers_build_cur_vrow_low( /** Check a virtual column value index secondary virtual index matches that of current cluster index record, which is recreated from information stored in undo log -@param[in] in_purge called by purge thread @param[in] rec record in the clustered index @param[in] icentry the index entry built from a cluster row @param[in] clust_index cluster index @@ -622,7 +621,6 @@ stored in undo log static bool row_vers_vc_matches_cluster( - bool in_purge, const rec_t* rec, const dtuple_t* icentry, dict_index_t* clust_index, @@ -683,12 +681,6 @@ row_vers_vc_matches_cluster( version = rec; - /* If this is called by purge thread, set TRX_UNDO_PREV_IN_PURGE - bit to search the undo log until we hit the current undo log with - roll_ptr */ - ulint status = (in_purge ? TRX_UNDO_PREV_IN_PURGE : 0) - | TRX_UNDO_GET_OLD_V_VALUE; - while (n_cmp_v_col < n_fields - n_non_v_col) { heap2 = heap; heap = mem_heap_create(1024); @@ -696,11 +688,12 @@ row_vers_vc_matches_cluster( version, clust_index, clust_offsets); ut_ad(cur_roll_ptr != 0); - ut_ad(in_purge == (roll_ptr != 0)); + ut_ad(roll_ptr != 0); trx_undo_prev_version_build( rec, mtr, version, clust_index, clust_offsets, - heap, &prev_version, NULL, vrow, status); + heap, &prev_version, NULL, vrow, + TRX_UNDO_PREV_IN_PURGE | TRX_UNDO_GET_OLD_V_VALUE); if (heap2) { mem_heap_free(heap2); @@ -958,7 +951,7 @@ row_vers_old_has_index_entry( secondary indexes.) */ if (entry && row_vers_vc_matches_cluster( - also_curr, rec, entry, + rec, entry, clust_index, clust_offsets, index, ientry, roll_ptr, trx_id, NULL, &vrow, mtr)) { diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index 09159815d2b..2f358901f2e 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -119,8 +119,7 @@ srv_conc_enter_innodb_with_atomics( for (;;) { ulint sleep_in_us; #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_aborting(trx->mysql_thd)) { + if (trx->is_wsrep() && wsrep_thd_is_aborting(trx->mysql_thd)) { if (wsrep_get_debug()) { ib::info() << "srv_conc_enter due to MUST_ABORT"; diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index f0b7b9e2766..346b208700f 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -55,45 +55,43 @@ bool trx_rollback_is_active; const trx_t* trx_roll_crash_recv_trx; /** Finish transaction rollback. -@param[in,out] trx transaction @return whether the rollback was completed normally @retval false if the rollback was aborted by shutdown */ -static bool trx_rollback_finish(trx_t* trx) +inline bool trx_t::rollback_finish() { - trx->mod_tables.clear(); - bool finished = trx->error_state == DB_SUCCESS; - if (UNIV_LIKELY(finished)) { - trx_commit(trx); - } else { - ut_a(trx->error_state == DB_INTERRUPTED); - ut_ad(!srv_is_being_started); - ut_a(!srv_undo_sources); - ut_ad(srv_fast_shutdown); - ut_d(trx->in_rollback = false); - if (trx_undo_t*& undo = trx->rsegs.m_redo.old_insert) { - UT_LIST_REMOVE(trx->rsegs.m_redo.rseg->old_insert_list, - undo); - ut_free(undo); - undo = NULL; - } - if (trx_undo_t*& undo = trx->rsegs.m_redo.undo) { - UT_LIST_REMOVE(trx->rsegs.m_redo.rseg->undo_list, - undo); - ut_free(undo); - undo = NULL; - } - if (trx_undo_t*& undo = trx->rsegs.m_noredo.undo) { - UT_LIST_REMOVE(trx->rsegs.m_noredo.rseg->undo_list, - undo); - ut_free(undo); - undo = NULL; - } - trx_commit_low(trx, NULL); - } - - trx->lock.que_state = TRX_QUE_RUNNING; + mod_tables.clear(); + if (UNIV_LIKELY(error_state == DB_SUCCESS)) + { + commit(); + return true; + } - return finished; + ut_a(error_state == DB_INTERRUPTED); + ut_ad(!srv_is_being_started); + ut_a(!srv_undo_sources); + ut_ad(srv_fast_shutdown); + ut_d(in_rollback= false); + if (trx_undo_t *&undo= rsegs.m_redo.old_insert) + { + UT_LIST_REMOVE(rsegs.m_redo.rseg->old_insert_list, undo); + ut_free(undo); + undo= nullptr; + } + if (trx_undo_t *&undo= rsegs.m_redo.undo) + { + UT_LIST_REMOVE(rsegs.m_redo.rseg->undo_list, undo); + ut_free(undo); + undo= nullptr; + } + if (trx_undo_t *&undo= rsegs.m_noredo.undo) + { + UT_LIST_REMOVE(rsegs.m_noredo.rseg->undo_list, undo); + ut_free(undo); + undo= nullptr; + } + commit_low(); + lock.que_state = TRX_QUE_RUNNING; + return false; } /*******************************************************************//** @@ -144,8 +142,8 @@ trx_rollback_to_savepoint_low( roll_node->undo_thr->common.parent)); } - if (savept == NULL) { - trx_rollback_finish(trx); + if (!savept) { + trx->rollback_finish(); MONITOR_INC(MONITOR_TRX_ROLLBACK); } else { ut_a(trx->error_state == DB_SUCCESS); @@ -182,8 +180,7 @@ trx_rollback_to_savepoint( complete rollback */ { #ifdef WITH_WSREP - if (savept == NULL && wsrep_on(trx->mysql_thd) - && wsrep_thd_is_SR(trx->mysql_thd)) { + if (!savept && trx->is_wsrep() && wsrep_thd_is_SR(trx->mysql_thd)) { wsrep_handle_SR_rollback(NULL, trx->mysql_thd); } #endif /* WITH_WSREP */ @@ -454,7 +451,7 @@ trx_rollback_to_savepoint_for_mysql_low( trx->op_info = ""; #ifdef WITH_WSREP - trx->lock.was_chosen_as_wsrep_victim = FALSE; + trx->lock.was_chosen_as_wsrep_victim = false; #endif return(err); } @@ -668,7 +665,7 @@ trx_rollback_active( que_graph_free( static_cast<que_t*>(roll_node->undo_thr->common.parent)); - if (UNIV_UNLIKELY(!trx_rollback_finish(trx))) { + if (UNIV_UNLIKELY(!trx->rollback_finish())) { ut_ad(!dictionary_locked); goto func_exit; } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 71a0c1befb4..b6b376215c4 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -109,6 +109,9 @@ trx_init( trx->state = TRX_STATE_NOT_STARTED; trx->is_recovered = false; +#ifdef WITH_WSREP + trx->wsrep = false; +#endif /* WITH_WSREP */ trx->op_info = ""; @@ -1320,318 +1323,255 @@ void trx_t::evict_table(table_id_t table_id) } } -/****************************************************************//** -Commits a transaction in memory. */ -static -void -trx_commit_in_memory( -/*=================*/ - trx_t* trx, /*!< in/out: transaction */ - const mtr_t* mtr) /*!< in: mini-transaction of - trx_write_serialisation_history(), or NULL if - the transaction did not modify anything */ +/** Mark a transaction committed in the main memory data structures. */ +inline void trx_t::commit_in_memory(const mtr_t *mtr) { - trx->must_flush_log_later = false; - trx->read_view.close(); - - if (trx_is_autocommit_non_locking(trx)) { - ut_ad(trx->id == 0); - ut_ad(trx->read_only); - ut_a(!trx->is_recovered); - ut_ad(trx->rsegs.m_redo.rseg == NULL); - - /* Note: We are asserting without holding the lock mutex. But - that is OK because this transaction is not waiting and cannot - be rolled back and no new locks can (or should) be added - because it is flagged as a non-locking read-only transaction. */ - - ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); - - /* This state change is not protected by any mutex, therefore - there is an inherent race here around state transition during - printouts. We ignore this race for the sake of efficiency. - However, the trx_sys_t::mutex will protect the trx_t instance - and it cannot be removed from the trx_list and freed - without first acquiring the trx_sys_t::mutex. */ - - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); + must_flush_log_later= false; + read_view.close(); - MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT); - - DBUG_LOG("trx", "Autocommit in memory: " << trx); - trx->state = TRX_STATE_NOT_STARTED; - } else { + if (trx_is_autocommit_non_locking(this)) + { + ut_ad(id == 0); + ut_ad(read_only); + ut_a(!is_recovered); + ut_ad(!rsegs.m_redo.rseg); + + /* Note: We are asserting without holding the lock mutex. But + that is OK because this transaction is not waiting and cannot + be rolled back and no new locks can (or should) be added + because it is flagged as a non-locking read-only transaction. */ + ut_a(UT_LIST_GET_LEN(lock.trx_locks) == 0); + + /* This state change is not protected by any mutex, therefore + there is an inherent race here around state transition during + printouts. We ignore this race for the sake of efficiency. + However, the trx_sys_t::mutex will protect the trx_t instance + and it cannot be removed from the trx_list and freed + without first acquiring the trx_sys_t::mutex. */ + ut_ad(trx_state_eq(this, TRX_STATE_ACTIVE)); + + MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT); + + DBUG_LOG("trx", "Autocommit in memory: " << this); + state= TRX_STATE_NOT_STARTED; + } + else + { #ifdef UNIV_DEBUG - if (!UT_LIST_GET_LEN(trx->lock.trx_locks)) { - for (lock_list::iterator it - = trx->lock.table_locks.begin(); - it != trx->lock.table_locks.end(); - it++) { - ut_ad(!*it); - } - } + if (!UT_LIST_GET_LEN(lock.trx_locks)) + for (auto l : lock.table_locks) + ut_ad(!l); #endif /* UNIV_DEBUG */ - trx->commit_state(); - - if (trx->id) { - trx_sys.deregister_rw(trx); - - /* Wait for any implicit-to-explicit lock - conversions to cease, so that there will be no - race condition in lock_release(). */ - while (UNIV_UNLIKELY(trx->is_referenced())) { - ut_delay(srv_spin_wait_delay); - } - - trx->release_locks(); - trx->id = 0; - } else { - ut_ad(trx->read_only || !trx->rsegs.m_redo.rseg); - trx->release_locks(); - } + commit_state(); - DEBUG_SYNC_C("after_trx_committed_in_memory"); - - if (trx->read_only || !trx->rsegs.m_redo.rseg) { - MONITOR_INC(MONITOR_TRX_RO_COMMIT); - } else { - trx_update_mod_tables_timestamp(trx); - MONITOR_INC(MONITOR_TRX_RW_COMMIT); - trx->is_recovered = false; - } - - while (dict_table_t* table = UT_LIST_GET_FIRST( - trx->lock.evicted_tables)) { - UT_LIST_REMOVE(trx->lock.evicted_tables, table); - dict_mem_table_free(table); - } - } - - ut_ad(!trx->rsegs.m_redo.undo); - ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0); - - if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) { - mutex_enter(&rseg->mutex); - ut_ad(rseg->trx_ref_count > 0); - --rseg->trx_ref_count; - mutex_exit(&rseg->mutex); - - if (trx_undo_t*& insert = trx->rsegs.m_redo.old_insert) { - ut_ad(insert->rseg == rseg); - trx_undo_commit_cleanup(insert, false); - insert = NULL; - } - } - - ut_ad(!trx->rsegs.m_redo.old_insert); - - if (mtr != NULL) { - if (trx_undo_t*& undo = trx->rsegs.m_noredo.undo) { - ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg); - trx_undo_commit_cleanup(undo, true); - undo = NULL; - } + if (id) + { + trx_sys.deregister_rw(this); + + /* Wait for any implicit-to-explicit lock conversions to cease, + so that there will be no race condition in lock_release(). */ + while (UNIV_UNLIKELY(is_referenced())) + ut_delay(srv_spin_wait_delay); + release_locks(); + id= 0; + } + else + { + ut_ad(read_only || !rsegs.m_redo.rseg); + release_locks(); + } - /* NOTE that we could possibly make a group commit more - efficient here: call os_thread_yield here to allow also other - trxs to come to commit! */ + DEBUG_SYNC_C("after_trx_committed_in_memory"); - /*-------------------------------------*/ + if (read_only || !rsegs.m_redo.rseg) + { + MONITOR_INC(MONITOR_TRX_RO_COMMIT); + } + else + { + trx_update_mod_tables_timestamp(this); + MONITOR_INC(MONITOR_TRX_RW_COMMIT); + is_recovered= false; + } - /* Depending on the my.cnf options, we may now write the log - buffer to the log files, making the transaction durable if - the OS does not crash. We may also flush the log files to - disk, making the transaction durable also at an OS crash or a - power outage. + while (dict_table_t *table= UT_LIST_GET_FIRST(lock.evicted_tables)) + { + UT_LIST_REMOVE(lock.evicted_tables, table); + dict_mem_table_free(table); + } + } - The idea in InnoDB's group commit is that a group of - transactions gather behind a trx doing a physical disk write - to log files, and when that physical write has been completed, - one of those transactions does a write which commits the whole - group. Note that this group commit will only bring benefit if - there are > 2 users in the database. Then at least 2 users can - gather behind one doing the physical log write to disk. + ut_ad(!rsegs.m_redo.undo); + ut_ad(UT_LIST_GET_LEN(lock.evicted_tables) == 0); - If we are calling trx_commit() under prepare_commit_mutex, we - will delay possible log write and flush to a separate function - trx_commit_complete_for_mysql(), which is only called when the - thread has released the mutex. This is to make the - group commit algorithm to work. Otherwise, the prepare_commit - mutex would serialize all commits and prevent a group of - transactions from gathering. */ - - lsn_t lsn = mtr->commit_lsn(); - - if (lsn == 0) { - /* Nothing to be done. */ - } else if (trx->flush_log_later) { - /* Do nothing yet */ - trx->must_flush_log_later = true; - } else if (srv_flush_log_at_trx_commit == 0) { - /* Do nothing */ - } else { - trx_flush_log_if_needed(lsn, trx); - } + if (trx_rseg_t *rseg= rsegs.m_redo.rseg) + { + mutex_enter(&rseg->mutex); + ut_ad(rseg->trx_ref_count > 0); + --rseg->trx_ref_count; + mutex_exit(&rseg->mutex); - trx->commit_lsn = lsn; + if (trx_undo_t *&insert= rsegs.m_redo.old_insert) + { + ut_ad(insert->rseg == rseg); + trx_undo_commit_cleanup(insert, false); + insert= nullptr; + } + } - /* Tell server some activity has happened, since the trx - does changes something. Background utility threads like - master thread, purge thread or page_cleaner thread might - have some work to do. */ - srv_active_wake_master_thread(); - } + ut_ad(!rsegs.m_redo.old_insert); - ut_ad(!trx->rsegs.m_noredo.undo); + if (mtr) + { + if (trx_undo_t *&undo= rsegs.m_noredo.undo) + { + ut_ad(undo->rseg == rsegs.m_noredo.rseg); + trx_undo_commit_cleanup(undo, true); + undo= nullptr; + } - /* Free all savepoints, starting from the first. */ - trx_named_savept_t* savep = UT_LIST_GET_FIRST(trx->trx_savepoints); + /* NOTE that we could possibly make a group commit more efficient + here: call os_thread_yield here to allow also other trxs to come + to commit! */ + + /*-------------------------------------*/ + + /* Depending on the my.cnf options, we may now write the log + buffer to the log files, making the transaction durable if the OS + does not crash. We may also flush the log files to disk, making + the transaction durable also at an OS crash or a power outage. + + The idea in InnoDB's group commit is that a group of transactions + gather behind a trx doing a physical disk write to log files, and + when that physical write has been completed, one of those + transactions does a write which commits the whole group. Note that + this group commit will only bring benefit if there are > 2 users + in the database. Then at least 2 users can gather behind one doing + the physical log write to disk. + + If we are calling trx_t::commit() under prepare_commit_mutex, we + will delay possible log write and flush to a separate function + trx_commit_complete_for_mysql(), which is only called when the + thread has released the mutex. This is to make the group commit + algorithm to work. Otherwise, the prepare_commit mutex would + serialize all commits and prevent a group of transactions from + gathering. */ + + commit_lsn= mtr->commit_lsn(); + if (!commit_lsn) + /* Nothing to be done. */; + else if (flush_log_later) + /* Do nothing yet */ + must_flush_log_later= true; + else if (srv_flush_log_at_trx_commit) + trx_flush_log_if_needed(commit_lsn, this); + + /* Tell server some activity has happened, since the trx does + changes something. Background utility threads like master thread, + purge thread or page_cleaner thread might have some work to do. */ + srv_active_wake_master_thread(); + } - trx_roll_savepoints_free(trx, savep); + ut_ad(!rsegs.m_noredo.undo); - if (trx->fts_trx != NULL) { - trx_finalize_for_fts(trx, trx->undo_no != 0); - } + /* Free all savepoints, starting from the first. */ + trx_named_savept_t *savep= UT_LIST_GET_FIRST(trx_savepoints); - trx_mutex_enter(trx); - trx->dict_operation = TRX_DICT_OP_NONE; -#ifdef WITH_WSREP - trx->lock.was_chosen_as_wsrep_victim = FALSE; -#endif + trx_roll_savepoints_free(this, savep); - DBUG_LOG("trx", "Commit in memory: " << trx); - trx->state = TRX_STATE_NOT_STARTED; + if (fts_trx) + trx_finalize_for_fts(this, undo_no != 0); - assert_trx_is_free(trx); + trx_mutex_enter(this); + dict_operation= TRX_DICT_OP_NONE; + lock.was_chosen_as_deadlock_victim= false; - trx_init(trx); + DBUG_LOG("trx", "Commit in memory: " << this); + state= TRX_STATE_NOT_STARTED; - trx_mutex_exit(trx); + assert_trx_is_free(this); + trx_init(this); + trx_mutex_exit(this); - ut_a(trx->error_state == DB_SUCCESS); - if (!srv_read_only_mode) { - srv_wake_purge_thread_if_not_active(); - } + ut_a(error_state == DB_SUCCESS); + if (!srv_read_only_mode) + srv_wake_purge_thread_if_not_active(); } -/** Commit a transaction and a mini-transaction. -@param[in,out] trx transaction -@param[in,out] mtr mini-transaction (NULL if no modifications) */ -void trx_commit_low(trx_t* trx, mtr_t* mtr) +/** Commit the transaction in a mini-transaction. +@param mtr mini-transaction (if there are any persistent modifications) */ +void trx_t::commit_low(mtr_t *mtr) { - assert_trx_nonlocking_or_in_list(trx); - ut_ad(!trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY)); - ut_ad(!mtr || mtr->is_active()); - ut_d(bool aborted = trx->in_rollback - && trx->error_state == DB_DEADLOCK); - ut_ad(!mtr == (aborted || !trx->has_logged_or_recovered())); - ut_ad(!mtr || !aborted); - - /* undo_no is non-zero if we're doing the final commit. */ - if (trx->fts_trx != NULL && trx->undo_no != 0) { - dberr_t error; - - ut_a(!trx_is_autocommit_non_locking(trx)); - - error = fts_commit(trx); - - /* FTS-FIXME: Temporarily tolerate DB_DUPLICATE_KEY - instead of dying. This is a possible scenario if there - is a crash between insert to DELETED table committing - and transaction committing. The fix would be able to - return error from this function */ - if (error != DB_SUCCESS && error != DB_DUPLICATE_KEY) { - /* FTS-FIXME: once we can return values from this - function, we should do so and signal an error - instead of just dying. */ - - ut_error; - } - } + assert_trx_nonlocking_or_in_list(this); + ut_ad(!trx_state_eq(this, TRX_STATE_COMMITTED_IN_MEMORY)); + ut_ad(!mtr || mtr->is_active()); + ut_d(bool aborted = in_rollback && error_state == DB_DEADLOCK); + ut_ad(!mtr == (aborted || !has_logged_or_recovered())); + ut_ad(!mtr || !aborted); + + /* undo_no is non-zero if we're doing the final commit. */ + if (fts_trx && undo_no) + { + ut_a(!trx_is_autocommit_non_locking(this)); + dberr_t error= fts_commit(this); + /* FTS-FIXME: Temporarily tolerate DB_DUPLICATE_KEY instead of + dying. This is a possible scenario if there is a crash between + insert to DELETED table committing and transaction committing. The + fix would be able to return error from this function */ + ut_a(error == DB_SUCCESS || error == DB_DUPLICATE_KEY); + } #ifndef DBUG_OFF - const bool debug_sync = trx->mysql_thd && trx->has_logged_persistent(); + const bool debug_sync= mysql_thd && has_logged_persistent(); #endif - if (mtr != NULL) { - trx_write_serialisation_history(trx, mtr); - - /* The following call commits the mini-transaction, making the - whole transaction committed in the file-based world, at this - log sequence number. The transaction becomes 'durable' when - we write the log to disk, but in the logical sense the commit - in the file-based data structures (undo logs etc.) happens - here. - - NOTE that transaction numbers, which are assigned only to - transactions with an update undo log, do not necessarily come - in exactly the same order as commit lsn's, if the transactions - have different rollback segments. To get exactly the same - order we should hold the kernel mutex up to this point, - adding to the contention of the kernel mutex. However, if - a transaction T2 is able to see modifications made by - a transaction T1, T2 will always get a bigger transaction - number and a bigger commit lsn than T1. */ - - /*--------------*/ - mtr_commit(mtr); - - DBUG_EXECUTE_IF("ib_crash_during_trx_commit_in_mem", - if (trx->has_logged()) { - log_write_up_to(mtr->commit_lsn(), - true); - DBUG_SUICIDE(); - }); - /*--------------*/ - } + if (mtr) + { + trx_write_serialisation_history(this, mtr); + + /* The following call commits the mini-transaction, making the + whole transaction committed in the file-based world, at this log + sequence number. The transaction becomes 'durable' when we write + the log to disk, but in the logical sense the commit in the + file-based data structures (undo logs etc.) happens here. + + NOTE that transaction numbers, which are assigned only to + transactions with an update undo log, do not necessarily come in + exactly the same order as commit lsn's, if the transactions have + different rollback segments. To get exactly the same order we + should hold the kernel mutex up to this point, adding to the + contention of the kernel mutex. However, if a transaction T2 is + able to see modifications made by a transaction T1, T2 will always + get a bigger transaction number and a bigger commit lsn than T1. */ + + mtr->commit(); + } #ifndef DBUG_OFF - /* In case of this function is called from a stack executing - THD::release_resources -> ... - innobase_connection_close() -> - trx_rollback_for_mysql... -> . - mysql's thd does not seem to have - thd->debug_sync_control defined any longer. However the stack - is possible only with a prepared trx not updating any data. - */ - if (debug_sync) { - DEBUG_SYNC_C("before_trx_state_committed_in_memory"); - } + if (debug_sync) + DEBUG_SYNC_C("before_trx_state_committed_in_memory"); #endif - trx_commit_in_memory(trx, mtr); + commit_in_memory(mtr); } -/****************************************************************//** -Commits a transaction. */ -void -trx_commit( -/*=======*/ - trx_t* trx) /*!< in/out: transaction */ -{ - mtr_t* mtr; - mtr_t local_mtr; - - DBUG_EXECUTE_IF("ib_trx_commit_crash_before_trx_commit_start", - DBUG_SUICIDE();); - if (trx->has_logged_or_recovered()) { - mtr = &local_mtr; - mtr->start(); - } else { - - mtr = NULL; - } +void trx_t::commit() +{ + mtr_t *mtr= nullptr; + mtr_t local_mtr; - trx_commit_low(trx, mtr); + if (has_logged_or_recovered()) + { + mtr= &local_mtr; + local_mtr.start(); + } + commit_low(mtr); #ifdef WITH_WSREP - /* Serialization history has been written and the - transaction is committed in memory, which makes - this commit ordered. Release commit order critical - section. */ - if (wsrep_on(trx->mysql_thd)) - { - wsrep_commit_ordered(trx->mysql_thd); - } + /* Serialization history has been written and the transaction is + committed in memory, which makes this commit ordered. Release commit + order critical section. */ + if (mtr && is_wsrep()) + wsrep_commit_ordered(mysql_thd); #endif /* WITH_WSREP */ } @@ -1725,11 +1665,8 @@ trx_commit_step( trx_commit_or_rollback_prepare(trx); trx->lock.que_state = TRX_QUE_COMMITTING; - - trx_commit(trx); - + trx->commit(); ut_ad(trx->lock.wait_thr == NULL); - trx->lock.que_state = TRX_QUE_RUNNING; thr = NULL; @@ -1767,9 +1704,7 @@ trx_commit_for_mysql( case TRX_STATE_PREPARED: case TRX_STATE_PREPARED_RECOVERED: trx->op_info = "committing"; - - trx_commit(trx); - + trx->commit(); MONITOR_DEC(MONITOR_TRX_ACTIVE); trx->op_info = ""; return(DB_SUCCESS); diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index c5d280ddc72..c15469ecb75 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -297,7 +297,7 @@ static MYSQL_SYSVAR_BOOL(encrypt_tables, maria_encrypt_tables, PLUGIN_VAR_OPCMDA "and not FIXED/DYNAMIC)", 0, 0, 0); -#ifdef HAVE_PSI_INTERFACE +#if defined HAVE_PSI_INTERFACE && !defined EMBEDDED_LIBRARY static PSI_mutex_info all_aria_mutexes[]= { diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 0b2002267bf..cf1414f991a 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -156,7 +156,7 @@ struct st_pagecache_hash_link /* simple states of a block */ #define PCBLOCK_ERROR 1 /* an error occurred when performing disk i/o */ -#define PCBLOCK_READ 2 /* the is page in the block buffer */ +#define PCBLOCK_READ 2 /* there is an active page in the block buffer */ /* A tread is reading the data to the page. @@ -3752,6 +3752,7 @@ restart: */ if (reg_request) unreg_request(pagecache, block, 1); + dec_counter_for_resize_op(pagecache); pagecache_pthread_mutex_unlock(&pagecache->cache_lock); DBUG_PRINT("info", ("restarting...")); goto restart; @@ -4028,6 +4029,7 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache, DBUG_ASSERT((block->status & (PCBLOCK_IN_SWITCH | PCBLOCK_REASSIGNED)) == 0); + /* This lock is deleted in pagecache_delete_internal() called below */ inc_counter_for_resize_op(pagecache); /* make_lock_and_pin() can't fail here, because we are keeping pin on the @@ -4172,6 +4174,7 @@ restart: */ if (pin == PAGECACHE_PIN) unreg_request(pagecache, block, 1); + dec_counter_for_resize_op(pagecache); pagecache_pthread_mutex_unlock(&pagecache->cache_lock); DBUG_PRINT("info", ("restarting...")); goto restart; |