summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-04-29 15:40:51 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-04-29 15:40:51 +0300
commit496d0372ef2ff2a570c20923af4df32a03781acd (patch)
treec15d45eeff0fbbfe6112816a72e10352551269ee
parentd4da131cff004e4157b755e417c49daef45ca80e (diff)
parent5ba2aa1ddc074dc89db7f265ddb61ce96f714fc8 (diff)
downloadmariadb-git-496d0372ef2ff2a570c20923af4df32a03781acd.tar.gz
Merge 10.4 into 10.5
-rw-r--r--cmake/install_layout.cmake4
-rw-r--r--debian/mariadb-server-10.5.preinst2
-rw-r--r--extra/mariabackup/backup_mysql.cc88
-rw-r--r--include/my_pthread.h3
-rw-r--r--mysql-test/include/galera_have_debug_sync.inc2
-rw-r--r--mysql-test/include/have_garbd.inc4
-rw-r--r--mysql-test/include/have_mariabackup.inc4
-rw-r--r--mysql-test/include/switch_to_mysql_global_priv.inc1
-rw-r--r--mysql-test/include/switch_to_mysql_user.inc1
-rw-r--r--mysql-test/lib/My/SafeProcess.pm6
-rw-r--r--mysql-test/lib/My/SafeProcess/CMakeLists.txt2
-rw-r--r--mysql-test/lib/My/SafeProcess/wsrep_check_version.c141
-rw-r--r--mysql-test/main/connect.result4
-rw-r--r--mysql-test/main/empty_user_table.result2
-rw-r--r--mysql-test/main/grant.result2
-rw-r--r--mysql-test/main/grant4.result4
-rw-r--r--mysql-test/main/grant_4332.result2
-rw-r--r--mysql-test/main/grant_repair.result9
-rw-r--r--mysql-test/main/grant_repair.test21
-rw-r--r--mysql-test/main/mysql_upgrade.result12
-rw-r--r--mysql-test/main/mysql_upgrade.test13
-rw-r--r--mysql-test/main/mysql_upgrade_noengine.result3
-rw-r--r--mysql-test/main/mysql_upgrade_to_100502.result1
-rw-r--r--mysql-test/main/password_expiration.result2
-rw-r--r--mysql-test/main/plugin_auth.result1
-rw-r--r--mysql-test/main/set_password.result2
-rw-r--r--mysql-test/main/sp_notembedded.result4
-rw-r--r--mysql-test/main/system_mysql_db_507.result2
-rwxr-xr-xmysql-test/mysql-test-run.pl195
-rw-r--r--mysql-test/suite.pm15
-rw-r--r--mysql-test/suite/galera/include/have_mariabackup.inc7
-rw-r--r--mysql-test/suite/galera/suite.pm19
-rw-r--r--mysql-test/suite/galera/t/galera_ist_mariabackup.cnf3
-rw-r--r--mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.cnf3
-rw-r--r--mysql-test/suite/galera_3nodes/include/galera_resume.inc (renamed from mysql-test/include/galera_resume.inc)0
-rw-r--r--mysql-test/suite/galera_3nodes/include/have_garbd.inc3
-rw-r--r--mysql-test/suite/galera_3nodes/suite.pm13
-rw-r--r--mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test2
-rw-r--r--mysql-test/suite/galera_sr/suite.pm13
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter-timestamp.result15
-rw-r--r--mysql-test/suite/innodb/r/innodb_sys_var_valgrind.result73
-rw-r--r--mysql-test/suite/innodb/t/innodb-alter-timestamp.test21
-rw-r--r--mysql-test/suite/innodb/t/innodb_sys_var_valgrind.test70
-rw-r--r--mysql-test/suite/innodb_fts/r/innodb_fts_misc.result7
-rw-r--r--mysql-test/suite/innodb_fts/r/stopword.result748
-rw-r--r--mysql-test/suite/innodb_fts/t/innodb_fts_misc.test8
-rw-r--r--mysql-test/suite/innodb_fts/t/stopword.opt1
-rw-r--r--mysql-test/suite/innodb_fts/t/stopword.test657
-rw-r--r--mysql-test/suite/innodb_gis/r/rtree_split.result56
-rw-r--r--mysql-test/suite/innodb_gis/t/rtree_split.test64
-rw-r--r--mysql-test/suite/mariabackup/backup_lock_wait_timeout.result11
-rw-r--r--mysql-test/suite/mariabackup/backup_lock_wait_timeout.test28
-rw-r--r--mysql-test/suite/mariabackup/suite.pm3
-rw-r--r--mysql-test/suite/plugins/r/multiauth.result15
-rw-r--r--mysql-test/suite/plugins/t/multiauth.test11
-rw-r--r--mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result2
-rw-r--r--mysql-test/suite/sql_sequence/rebuild.test1
-rw-r--r--mysql-test/suite/wsrep/common.pm117
-rw-r--r--mysql-test/suite/wsrep/suite.pm13
-rw-r--r--mysys/my_thr_init.c14
-rw-r--r--plugin/auth_pam/CMakeLists.txt4
-rw-r--r--plugin/wsrep_info/mysql-test/wsrep_info/suite.pm12
-rw-r--r--scripts/mysql_system_tables_fix.sql1
-rw-r--r--sql/handler.cc5
-rw-r--r--sql/handler.h5
-rw-r--r--sql/item_func.cc21
-rw-r--r--sql/log_event_server.cc3
-rw-r--r--sql/mysqld.cc10
-rw-r--r--sql/sql_acl.cc18
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_table.cc5
-rw-r--r--sql/threadpool_common.cc15
-rw-r--r--sql/wsrep_dummy.cc6
-rw-r--r--storage/innobase/buf/buf0dump.cc11
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc11
-rw-r--r--storage/innobase/fts/fts0fts.cc81
-rw-r--r--storage/innobase/gis/gis0sea.cc232
-rw-r--r--storage/innobase/handler/ha_innodb.cc291
-rw-r--r--storage/innobase/handler/handler0alter.cc67
-rw-r--r--storage/innobase/include/dict0stats.h10
-rw-r--r--storage/innobase/include/fts0fts.h12
-rw-r--r--storage/innobase/include/gis0rtree.h18
-rw-r--r--storage/innobase/include/lock0lock.h4
-rw-r--r--storage/innobase/include/row0upd.h10
-rw-r--r--storage/innobase/include/trx0trx.h45
-rw-r--r--storage/innobase/lock/lock0lock.cc24
-rw-r--r--storage/innobase/lock/lock0wait.cc10
-rw-r--r--storage/innobase/row/row0mysql.cc11
-rw-r--r--storage/innobase/row/row0purge.cc3
-rw-r--r--storage/innobase/row/row0uins.cc4
-rw-r--r--storage/innobase/row/row0umod.cc4
-rw-r--r--storage/innobase/row/row0upd.cc8
-rw-r--r--storage/innobase/row/row0vers.cc15
-rw-r--r--storage/innobase/srv/srv0conc.cc5
-rw-r--r--storage/innobase/trx/trx0roll.cc79
-rw-r--r--storage/innobase/trx/trx0trx.cc499
-rw-r--r--storage/maria/ha_maria.cc2
-rw-r--r--storage/maria/ma_pagecache.c5
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;