From 51e049cff6a3110504b67644bf02a037dc8b1c5c Mon Sep 17 00:00:00 2001 From: Balasubramanian Kandasamy Date: Mon, 27 Nov 2017 15:33:02 +0530 Subject: [PATCH 01/42] Raise version number after cloning 5.5.59 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 87b72051a84..44f719ca097 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=59 +MYSQL_VERSION_PATCH=60 MYSQL_VERSION_EXTRA= From 8bc828b982f678d6b57c1853bbe78080c8f84e84 Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Mon, 27 Nov 2017 19:59:29 +0530 Subject: [PATCH 02/42] BUG#26502135: MYSQLD SEGFAULTS IN MDL_CONTEXT::TRY_ACQUIRE_LOCK_IMPL ANALYSIS: ========= Server sometimes exited when multiple threads tried to acquire and release metadata locks simultaneously (for example, necessary to access a table). The same problem could have occurred when new objects were registered/ deregistered in Performance Schema. The problem was caused by a bug in LF_HASH - our lock free hash implementation which is used by metadata locking subsystem in 5.7 branch. In 5.5 and 5.6 we only use LF_HASH in Performance Schema Instrumentation implementation. So for these versions, the problem was limited to P_S. The problem was in my_lfind() function, which searches for the specific hash element by going through the elements list. During this search it loads information about element checked such as key pointer and hash value into local variables. Then it confirms that they are not corrupted by concurrent delete operation (which will set pointer to 0) by checking if element is still in the list. The latter check did not take into account that compiler (and processor) can reorder reads in such a way that load of key pointer will happen after it, making result of the check invalid. FIX: ==== This patch fixes the problem by ensuring that no such reordering can take place. This is achieved by using my_atomic_loadptr() which contains compiler and processor memory barriers for the check mentioned above and other similar places. The default (for non-Windows systems) implementation of my_atomic*() relies on old __sync intrisics and implements my_atomic_loadptr() as read-modify operation. To avoid scalability/performance penalty associated with addition of my_atomic_loadptr()'s we change the my_atomic*() to use newer __atomic intrisics when available. This new default implementation doesn't have such a drawback. --- mysys/lf_hash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c index dc019b07bd9..3a3f665a4f1 100644 --- a/mysys/lf_hash.c +++ b/mysys/lf_hash.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -83,7 +83,8 @@ retry: do { /* PTR() isn't necessary below, head is a dummy node */ cursor->curr= (LF_SLIST *)(*cursor->prev); _lf_pin(pins, 1, cursor->curr); - } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF); + } while (my_atomic_loadptr((void**)cursor->prev) != cursor->curr && + LF_BACKOFF); for (;;) { if (unlikely(!cursor->curr)) @@ -97,7 +98,7 @@ retry: cur_hashnr= cursor->curr->hashnr; cur_key= cursor->curr->key; cur_keylen= cursor->curr->keylen; - if (*cursor->prev != (intptr)cursor->curr) + if (my_atomic_loadptr((void**)cursor->prev) != cursor->curr) { (void)LF_BACKOFF; goto retry; From ecc5a07874d44307b835ff5dbd091343961fbc93 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Sat, 2 Dec 2017 15:12:32 +0530 Subject: [PATCH 03/42] Bug#26585560 - MYSQL DAEMON SHOULD CREATE ITS PID FILE AS ROOT DESCRIPTION =========== If the .pid file is created at a world-writable location, it can be compromised by replacing the server's pid with another running server's (or some other non-mysql process) PID causing abnormal behaviour. ANALYSIS ======== In such a case, user should be warned that .pid file is being created at a world-writable location. FIX === A new function is_file_or_dir_world_writable() is defined and it is called in create_pid_file() before .pid file creation. If the location is world-writable, a relevant warning is thrown. NOTE ==== 1. PID file is always created with permission bit 0664, so for outside world its read-only. 2. Ignoring the case when permission is denied to get the dir stats since the .pid file creation would fail anyway in such a case. --- include/sql_common.h | 1 + mysql-test/include/mtr_warnings.sql | 8 ++++- sql-common/my_path_permissions.cc | 54 +++++++++++++++++++++++++++++ sql/CMakeLists.txt | 2 +- sql/mysqld.cc | 36 ++++++++++++++++++- 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 sql-common/my_path_permissions.cc diff --git a/include/sql_common.h b/include/sql_common.h index 05bbb5a4f53..45e90d438fb 100644 --- a/include/sql_common.h +++ b/include/sql_common.h @@ -107,6 +107,7 @@ void mysql_client_plugin_deinit(); struct st_mysql_client_plugin; extern struct st_mysql_client_plugin *mysql_client_builtins[]; extern my_bool libmysql_cleartext_plugin_enabled; +int is_file_or_dir_world_writable(const char *filepath); #ifdef __cplusplus } diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 0a3c3bc60b3..fb6d24c03e9 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -1,4 +1,4 @@ --- Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. +-- Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. -- -- 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 @@ -209,6 +209,12 @@ INSERT INTO global_suppressions VALUES */ ("Insecure configuration for --secure-file-priv:*"), + /* + Bug#26585560, warning related to --pid-file + */ + ("Insecure configuration for --pid-file:*"), + ("Few location(s) are inaccessible while checking PID filepath"), + ("THE_LAST_SUPPRESSION")|| diff --git a/sql-common/my_path_permissions.cc b/sql-common/my_path_permissions.cc new file mode 100644 index 00000000000..22cd748ff03 --- /dev/null +++ b/sql-common/my_path_permissions.cc @@ -0,0 +1,54 @@ +/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + + 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 Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA */ + +#include "my_dir.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Check if a file/dir is world-writable (only on non-Windows platforms) + + @param [in] Path of the file/dir to be checked + + @returns Status of the file/dir check + @retval -2 Permission denied to check attributes of file/dir + @retval -1 Error in reading file/dir + @retval 0 File/dir is not world-writable + @retval 1 File/dir is world-writable + */ + +int is_file_or_dir_world_writable(const char *path) +{ + MY_STAT stat_info; + (void)path; // avoid unused param warning when built on Windows +#ifndef _WIN32 + if (!my_stat(path, &stat_info, MYF(0))) + { + return (errno == EACCES) ? -2 : -1; + } + if ((stat_info.st_mode & S_IWOTH) && + ((stat_info.st_mode & S_IFMT) == S_IFREG || /* file */ + (stat_info.st_mode & S_IFMT) == S_IFDIR)) /* or dir */ + return 1; +#endif + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 531561ac36d..aa7e0312e05 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -78,7 +78,7 @@ SET (SQL_SOURCE sql_profile.cc event_parse_data.cc sql_alter.cc sql_signal.cc rpl_handler.cc mdl.cc sql_admin.cc transaction.cc sys_vars.cc sql_truncate.cc datadict.cc - sql_reload.cc + sql_reload.cc ../sql-common/my_path_permissions.cc ${GEN_SOURCES} ${CONF_SOURCES} ${MYSYS_LIBWRAP_SOURCE}) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c969fd8a62a..fd39e252c26 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify @@ -7996,6 +7996,40 @@ static int test_if_case_insensitive(const char *dir_name) static void create_pid_file() { File file; + bool check_parent_path= 1, is_path_accessible= 1; + char pid_filepath[FN_REFLEN], *pos= NULL; + /* Copy pid file name to get pid file path */ + strcpy(pid_filepath, pidfile_name); + + /* Iterate through the entire path to check if even one of the sub-dirs + is world-writable */ + while (check_parent_path && (pos= strrchr(pid_filepath, FN_LIBCHAR)) + && (pos != pid_filepath)) /* shouldn't check root */ + { + *pos= '\0'; /* Trim the inner-most dir */ + switch (is_file_or_dir_world_writable(pid_filepath)) + { + case -2: + is_path_accessible= 0; + break; + case -1: + sql_perror("Can't start server: can't check PID filepath"); + exit(1); + case 1: + sql_print_warning("Insecure configuration for --pid-file: Location " + "'%s' in the path is accessible to all OS users. " + "Consider choosing a different directory.", + pid_filepath); + check_parent_path= 0; + break; + case 0: + continue; /* Keep checking the parent dir */ + } + } + if (!is_path_accessible) + { + sql_print_warning("Few location(s) are inaccessible while checking PID filepath."); + } if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664, O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) { From 9e1035c64f2db233995082397921f553810bdfbc Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Tue, 5 Dec 2017 19:49:59 +0530 Subject: [PATCH 04/42] BUG#26881798: SERVER EXITS WHEN PRIMARY KEY IN MYSQL.PROC IS DROPPED ANALYSIS: ========= It is advised not to tamper with the system tables. When primary key is dropped from a system table, certain operations on the table which tries to access the table key information may lead to server exit. FIX: ==== An appropriate error is now reported in such a case. --- sql/event_db_repository.cc | 4 +++- sql/sp.cc | 4 ++-- sql/sql_acl.cc | 4 +++- sql/sql_plugin.cc | 12 +++++++++++- sql/table.cc | 16 ++++++++++++++-- sql/table.h | 5 +++-- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 74da4d8f587..96d1279573d 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -174,6 +174,8 @@ protected: error_log_print(ERROR_LEVEL, fmt, args); va_end(args); } +public: + Event_db_intact() { has_keys= TRUE; } }; /** In case of an error, a message is printed to the error log. */ diff --git a/sql/sp.cc b/sql/sp.cc index 56a439481f5..82d25880168 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -351,7 +351,7 @@ private: bool m_print_once; public: - Proc_table_intact() : m_print_once(TRUE) {} + Proc_table_intact() : m_print_once(TRUE) { has_keys= TRUE; } protected: void report_error(uint code, const char *fmt, ...); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b48b8562679..385484f2b01 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -949,6 +949,8 @@ protected: va_end(args); } } +public: + Acl_table_intact() { has_keys= TRUE; } }; #define IP_ADDR_STRLEN (3 + 1 + 3 + 1 + 3 + 1 + 3) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 9ec0390483a..3af9136d37f 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -1899,6 +1899,16 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) DBUG_RETURN(TRUE); + if (!table->key_info) + { + my_printf_error(ER_UNKNOWN_ERROR, + "The table '%s.%s' does not have the necessary key(s) " + "defined on it. Please check the table definition and " + "create index(s) accordingly.", MYF(0), + table->s->db.str, table->s->table_name.str); + DBUG_RETURN(TRUE); + } + /* Pre-acquire audit plugins for events that may potentially occur during [UN]INSTALL PLUGIN. diff --git a/sql/table.cc b/sql/table.cc index 5bc3ccdbf39..46397b794ee 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -3013,7 +3013,7 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) /* Whether the table definition has already been validated. */ if (table->s->table_field_def_cache == table_def) - DBUG_RETURN(FALSE); + goto end; if (table->s->fields != table_def->count) { @@ -3129,6 +3129,18 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def) if (! error) table->s->table_field_def_cache= table_def; +end: + + if (has_keys && !error && !table->key_info) + { + my_printf_error(ER_UNKNOWN_ERROR, + "The table '%s.%s' does not have the necessary key(s) " + "defined on it. Please check the table definition and " + "create index(s) accordingly.", MYF(0), + table->s->db.str, table->s->table_name.str); + error= TRUE; + } + DBUG_RETURN(error); } diff --git a/sql/table.h b/sql/table.h index ac3533dc5d7..31cd385ef35 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1,7 +1,7 @@ #ifndef TABLE_INCLUDED #define TABLE_INCLUDED -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 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 @@ -484,10 +484,11 @@ typedef struct st_ha_data_partition class Table_check_intact { protected: + bool has_keys; virtual void report_error(uint code, const char *fmt, ...)= 0; public: - Table_check_intact() {} + Table_check_intact() : has_keys(FALSE) {} virtual ~Table_check_intact() {} /** Checks whether a table is intact. */ From 7cf10132cb83a04f6e0f59a7266fd54c03e2ade2 Mon Sep 17 00:00:00 2001 From: "mysql-builder@oracle.com" <> Date: Thu, 21 Dec 2017 10:11:49 +0530 Subject: [PATCH 05/42] From 2b1fe48504cb91eb6d18ec2188a5cc1737f3003e Mon Sep 17 00:00:00 2001 From: "mysql-builder@oracle.com" <> Date: Thu, 21 Dec 2017 18:12:26 +0530 Subject: [PATCH 06/42] From 20e75a3efdd12540bf0078e27c62e0daad034cb7 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 11 Jan 2018 09:31:36 +0100 Subject: [PATCH 07/42] Bug #27021754 MYSQLTEST MAN PAGES WILL BE REMOVED, PACKAGING MUST BE PREPARED Followup: now that the man pages have actually been removed, we no longer need to take deliberate action to ignore them. Thus we can remove that part of the original change. RPM: drop the conditional removal DEB: remove from the exclude list --- packaging/rpm-oel/mysql.spec.in | 13 ++++--------- packaging/rpm-sles/mysql.spec.in | 13 ++++--------- support-files/mysql.spec.sh | 11 ++++------- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/packaging/rpm-oel/mysql.spec.in b/packaging/rpm-oel/mysql.spec.in index 755f922026e..f3f65da6605 100644 --- a/packaging/rpm-oel/mysql.spec.in +++ b/packaging/rpm-oel/mysql.spec.in @@ -1,4 +1,4 @@ -# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. # # 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 @@ -609,14 +609,6 @@ rm -rf %{buildroot}%{_bindir}/mysql_embedded rm -rf %{buildroot}%{_bindir}/mysql_setpermission rm -rf %{buildroot}%{_mandir}/man1/mysql_setpermission.1* -# Remove obsoleted man pages -rm -f %{buildroot}%{_mandir}/man1/mysql-stress-test.pl.1 -rm -f %{buildroot}%{_mandir}/man1/mysql-test-run.pl.1 -rm -f %{buildroot}%{_mandir}/man1/mysql_client_test.1 -rm -f %{buildroot}%{_mandir}/man1/mysql_client_test_embedded.1 -rm -f %{buildroot}%{_mandir}/man1/mysqltest.1 -rm -f %{buildroot}%{_mandir}/man1/mysqltest_embedded.1 - %check %if 0%{?runselftest} pushd release @@ -920,6 +912,9 @@ fi %endif %changelog +* Wed Jan 10 2018 Bjorn Munch - 5.5.60-1 +- No longer need to remove obsoleted mysqltest man pages + * Tue Oct 31 2017 Bjorn Munch - 5.5.59-1 - Remove obsoleted mysqltest man pages diff --git a/packaging/rpm-sles/mysql.spec.in b/packaging/rpm-sles/mysql.spec.in index d5a3ba8deff..75e0271b590 100644 --- a/packaging/rpm-sles/mysql.spec.in +++ b/packaging/rpm-sles/mysql.spec.in @@ -1,4 +1,4 @@ -# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. # # 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 @@ -446,14 +446,6 @@ rm -rf %{buildroot}%{_bindir}/mysql_embedded rm -rf %{buildroot}%{_bindir}/mysql_setpermission rm -rf %{buildroot}%{_mandir}/man1/mysql_setpermission.1* -# Remove obsoleted man pages -rm -f %{buildroot}%{_mandir}/man1/mysql-stress-test.pl.1 -rm -f %{buildroot}%{_mandir}/man1/mysql-test-run.pl.1 -rm -f %{buildroot}%{_mandir}/man1/mysql_client_test.1 -rm -f %{buildroot}%{_mandir}/man1/mysql_client_test_embedded.1 -rm -f %{buildroot}%{_mandir}/man1/mysqltest.1 -rm -f %{buildroot}%{_mandir}/man1/mysqltest_embedded.1 - # rcmysql symlink install -d %{buildroot}%{_sbindir} ln -sf %{_initrddir}/mysql %{buildroot}%{_sbindir}/rcmysql @@ -742,6 +734,9 @@ fi %attr(755, root, root) %{_libdir}/mysql/libmysqld.so %changelog +* Wed Jan 10 2018 Bjorn Munch - 5.5.60-1 +- No longer need to remove obsoleted mysqltest man pages + * Tue Oct 31 2017 Bjorn Munch - 5.5.59-1 - Remove obsoleted mysqltest man pages diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 4060284ce9d..cb1462c57e5 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. # # 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 @@ -621,12 +621,6 @@ install -m 644 "%{malloc_lib_source}" \ # Remove man pages we explicitly do not want to package, avoids 'unpackaged # files' warning. # This has become obsolete: rm -f $RBR%{_mandir}/man1/make_win_bin_dist.1* -rm -f $RBR%{_mandir}/man1/mysql-stress-test.pl.1 -rm -f $RBR%{_mandir}/man1/mysql-test-run.pl.1 -rm -f $RBR%{_mandir}/man1/mysql_client_test.1 -rm -f $RBR%{_mandir}/man1/mysql_client_test_embedded.1 -rm -f $RBR%{_mandir}/man1/mysqltest.1 -rm -f $RBR%{_mandir}/man1/mysqltest_embedded.1 ############################################################################## # Post processing actions, i.e. when installed @@ -1228,6 +1222,9 @@ echo "=====" >> $STATUS_HISTORY # merging BK trees) ############################################################################## %changelog +* Wed Jan 10 2018 Bjorn Munch +- No longer need to remove obsoleted mysqltest man pages + * Tue Oct 31 2017 Bjorn Munch - Remove obsoleted mysqltest man pages From 2af9e8af6efba951e33e148d0b1a34beb25be831 Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Thu, 11 Jan 2018 19:48:12 +0530 Subject: [PATCH 08/42] BUG#27160888: MISSING FILE PRIVILEDGE CHECKS ON SOME STATEMENTS ANALYSIS: ========= A user not having FILE privilege is not allowed to create custom data/index directories for a table or for its partitions via CREATE TABLE but is allowed to do so via ALTER TABLE statement. ALTER TABLE ignores DATA DIRECTORY and INDEX DIRECTORY when given as table options. The issue occurs during the creation of partitions for a table via ALTER TABLE statement with the DATA DIRECTORY and/or INDEX DIRECTORY options. The issue exists because of the absence of FILE privilege check for the user. FIX: ==== A FILE privilege check has been introduced for resolving the above scenario. --- sql/sql_alter.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 6247d581830..660efe2d177 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -18,6 +18,8 @@ // mysql_exchange_partition #include "sql_alter.h" +bool has_external_data_or_index_dir(partition_info &pi); + bool Alter_table_statement::execute(THD *thd) { LEX *lex= thd->lex; @@ -42,6 +44,16 @@ bool Alter_table_statement::execute(THD *thd) if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */ DBUG_RETURN(TRUE); + +#ifdef WITH_PARTITION_STORAGE_ENGINE + { + partition_info *part_info= thd->lex->part_info; + if (part_info != NULL && has_external_data_or_index_dir(*part_info) && + check_access(thd, FILE_ACL, any_db, NULL, NULL, FALSE, FALSE)) + + DBUG_RETURN(TRUE); + } +#endif /* We also require DROP priv for ALTER TABLE ... DROP PARTITION, as well as for RENAME TO, as being done by SQLCOM_RENAME_TABLE From 3fb2f8db179c2ea9a15fcc2f142c5b98c5aab17a Mon Sep 17 00:00:00 2001 From: Joao Gramacho Date: Fri, 2 Feb 2018 11:45:56 +0000 Subject: [PATCH 09/42] BUG#24365972 BINLOG DECODING ISN'T RESILIENT TO CORRUPT BINLOG FILES Problem ======= When facing decoding of corrupt binary log files, server may misbehave without detecting the events corruption. This patch makes MySQL server more resilient to binary log decoding. Fixes for events de-serialization and apply =========================================== @sql/log_event.cc Query_log_event::Query_log_event: added a check to ensure query length is respecting event buffer limits. Query_log_event::do_apply_event: extended a debug print, added a check to character set to determine if it is "parseable" or not, verified if database name is valid for system collation. Start_log_event_v3::do_apply_event: report an error on applying a non-supported binary log version. Load_log_event::copy_log_event: added a check to table_name length. User_var_log_event::User_var_log_event: added checks to avoid reading out of buffer limits. User_var_log_event::do_apply_event: reported an sanity check error properly and added individual sanity checks for variable types that expect fixed (or minimum) amount of bytes to be read. Rows_log_event::Rows_log_event: added checks to avoid reading out of buffer limits. @sql/log_event_old.cc Old_rows_log_event::Old_rows_log_event: added a sanity check to avoid reading out of buffer limits. @sql/sql_priv.h Added a sanity check to available_buffer() function. --- sql/log_event.cc | 126 ++++++++++++++++++++++++++++++++++++++++--- sql/log_event_old.cc | 11 +++- sql/sql_priv.h | 7 ++- 3 files changed, 136 insertions(+), 8 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 5dbeb1eb4b9..ac1e105be8c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -3024,6 +3024,25 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, db= (char *)start; query= (char *)(start + db_len + 1); q_len= data_len - db_len -1; + + if (data_len && (data_len < db_len || + data_len < q_len || + data_len != (db_len + q_len + 1))) + { + q_len= 0; + query= NULL; + DBUG_VOID_RETURN; + } + + unsigned int max_length; + max_length= (event_len - ((const char*)(end + db_len + 1) - + (buf - common_header_len))); + if (q_len != max_length) + { + q_len= 0; + query= NULL; + DBUG_VOID_RETURN; + } /** Append the db length at the end of the buffer. This will be used by Query_cache::send_result_to_client() in case the query cache is On. @@ -3278,6 +3297,26 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, you. */ thd->catalog= catalog_len ? (char *) catalog : (char *)""; + + size_t valid_len; + bool len_error; + bool is_invalid_db_name= validate_string(system_charset_info, db, db_len, + &valid_len, &len_error); + + DBUG_PRINT("debug",("is_invalid_db_name= %s, valid_len=%zu, len_error=%s", + is_invalid_db_name ? "true" : "false", + valid_len, + len_error ? "true" : "false")); + + if (is_invalid_db_name || len_error) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER_THD(thd, ER_SLAVE_FATAL_ERROR), + "Invalid database name in Query event."); + thd->is_slave_error= true; + goto end; + } + new_db.length= db_len; new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length); thd->set_db(new_db.str, new_db.length); /* allocates a copy of 'db' */ @@ -3454,7 +3493,23 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, } else thd->variables.collation_database= thd->db_charset; - + + { + const CHARSET_INFO *cs= thd->charset(); + /* + We cannot ask for parsing a statement using a character set + without state_maps (parser internal data). + */ + if (!cs->state_map) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER_THD(thd, ER_SLAVE_FATAL_ERROR), + "character_set cannot be parsed"); + thd->is_slave_error= true; + goto end; + } + } + thd->table_map_for_update= (table_map)table_map_for_update; thd->set_invoker(&user, &host); /* @@ -3898,7 +3953,13 @@ int Start_log_event_v3::do_apply_event(Relay_log_info const *rli) */ break; default: - /* this case is impossible */ + /* + This case is not expected. It can be either an event corruption or an + unsupported binary log version. + */ + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER_THD(thd, ER_SLAVE_FATAL_ERROR), + "Binlog version not supported"); DBUG_RETURN(1); } DBUG_RETURN(error); @@ -4724,6 +4785,9 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, fields = (char*)field_lens + num_fields; table_name = fields + field_block_len; + if (strlen(table_name) > NAME_LEN) + goto err; + db = table_name + table_name_len + 1; DBUG_EXECUTE_IF ("simulate_invalid_address", db_len = data_len;); @@ -5889,6 +5953,13 @@ User_var_log_event(const char* buf, uint event_len, buf+= description_event->common_header_len + description_event->post_header_len[USER_VAR_EVENT-1]; name_len= uint4korr(buf); + /* Avoid reading out of buffer */ + if ((buf - buf_start) + UV_NAME_LEN_SIZE + name_len > event_len) + { + error= true; + goto err; + } + name= (char *) buf + UV_NAME_LEN_SIZE; /* @@ -5948,8 +6019,11 @@ User_var_log_event(const char* buf, uint event_len, we keep the flags set to UNDEF_F. */ uint bytes_read= ((val + val_len) - start); - DBUG_ASSERT(bytes_read==data_written || - bytes_read==(data_written-1)); + if (bytes_read > event_len) + { + error= true; + goto err; + } if ((data_written - bytes_read) > 0) { flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + @@ -6165,7 +6239,12 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli) } if (!(charset= get_charset(charset_number, MYF(MY_WME)))) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER_THD(thd, ER_SLAVE_FATAL_ERROR), + "Invalid character set for User var event"); return 1; + } LEX_STRING user_var_name; user_var_name.str= name; user_var_name.length= name_len; @@ -6186,12 +6265,26 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli) { switch (type) { case REAL_RESULT: + if (val_len != 8) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER_THD(thd, ER_SLAVE_FATAL_ERROR), + "Invalid variable length at User var event"); + return 1; + } float8get(real_val, val); it= new Item_float(real_val, 0); val= (char*) &real_val; // Pointer to value in native format val_len= 8; break; case INT_RESULT: + if (val_len != 8) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER_THD(thd, ER_SLAVE_FATAL_ERROR), + "Invalid variable length at User var event"); + return 1; + } int_val= (longlong) uint8korr(val); it= new Item_int(int_val); val= (char*) &int_val; // Pointer to value in native format @@ -6199,6 +6292,13 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli) break; case DECIMAL_RESULT: { + if (val_len < 3) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER_THD(thd, ER_SLAVE_FATAL_ERROR), + "Invalid variable length at User var event"); + return 1; + } Item_decimal *dec= new Item_decimal((uchar*) val+2, val[0], val[1]); it= dec; val= (char *)dec->val_decimal(NULL); @@ -7646,6 +7746,15 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); m_width = net_field_length(&ptr_after_width); DBUG_PRINT("debug", ("m_width=%lu", m_width)); + /* Avoid reading out of buffer */ + if (static_cast((ptr_after_width + + (m_width + 7) / 8) - + (uchar*)buf) > event_len) + { + m_cols.bitmap= NULL; + DBUG_VOID_RETURN; + } + /* if bitmap_init fails, catched in is_valid() */ if (likely(!bitmap_init(&m_cols, m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, @@ -7694,7 +7803,12 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; - size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf); + size_t const read_size= ptr_rows_data - (const unsigned char *) buf; + if (read_size > event_len) + { + DBUG_VOID_RETURN; + } + size_t const data_size= event_len - read_size; DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu", m_table_id, m_flags, m_width, (ulong) data_size)); diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index eb9678ddaa5..6be4e086925 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -1357,6 +1357,15 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len, DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); m_width = net_field_length(&ptr_after_width); DBUG_PRINT("debug", ("m_width=%lu", m_width)); + /* Avoid reading out of buffer */ + if (static_cast(m_width + + (ptr_after_width - + (const uchar *)buf)) > event_len) + { + m_cols.bitmap= NULL; + DBUG_VOID_RETURN; + } + /* if bitmap_init fails, catched in is_valid() */ if (likely(!bitmap_init(&m_cols, m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, diff --git a/sql/sql_priv.h b/sql/sql_priv.h index 523220b3c03..b12d22e3fc7 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -191,6 +191,11 @@ template T available_buffer(const char* buf_start, const char* buf_current, T buf_len) { + /* Sanity check */ + if (buf_current < buf_start || + buf_len < static_cast(buf_current - buf_start)) + return static_cast(0); + return buf_len - (buf_current - buf_start); } From e585decb459740ec53b1ac1b85f332f7bd3c8ccf Mon Sep 17 00:00:00 2001 From: Pavan Naik Date: Mon, 5 Feb 2018 19:30:37 +0530 Subject: [PATCH 10/42] BUG#27448061: MYSQLD--DEFAULTS-FILE TEST FAILS FOR NDB RELEASES PREVIOUS TO MYSQL 8.0 Description : ------------- The mysqld--defaults-file test fails when the test suite is run from a non-canonical path, which happens when the current working directory when mysql-test-run.pl is started contains a symbolic link. The problem is that this test case uses --replace-result with $MYSQL_TEST_DIR. This variable is a potentially non-canonical path based on the current working directory when mtr is started. However, the path in the expected error message from mysqld contains a canonical path. This means it does not contain $MYSQL_TEST_DIR if mtr's working directory is not the canonical path of the working directory. Because other tests produce output that may contain non-canonical paths, making $MYSQL_TEST_DIR always canonical is not a fix. Fix : ----- Introduced a new environment variable '$ABS_MYSQL_TEST_DIR' which will contin the canonical path to the test directory and replaced $MYSQL_TEST_DIR with the new variable in main.mysqld--defaults-file test file. This is a back-port of BUG#24579973. Change-Id: I3b8df6f2d7ce2b04e188a896d76250cc1addbbc1 --- mysql-test/mysql-test-run.pl | 3 ++- mysql-test/t/mysqld--defaults-file.test | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 2ca5c83e3f4..99d3203fb51 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # -*- cperl -*- -# Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. # # 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 @@ -2344,6 +2344,7 @@ sub environment_setup { $ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'port'}; $ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir; $ENV{'MYSQLTEST_VARDIR'}= $opt_vardir; + $ENV{'MYSQL_TEST_DIR_ABS'}= getcwd(); $ENV{'MYSQL_BINDIR'}= "$bindir"; $ENV{'MYSQL_SHAREDIR'}= $path_language; $ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir; diff --git a/mysql-test/t/mysqld--defaults-file.test b/mysql-test/t/mysqld--defaults-file.test index 3bfe0aa891f..e2d5b40adbc 100644 --- a/mysql-test/t/mysqld--defaults-file.test +++ b/mysql-test/t/mysqld--defaults-file.test @@ -13,19 +13,21 @@ exec $MYSQLD --defaults-file=/path/with/no/extension --print-defaults 2>&1; --error 1 exec $MYSQLD --defaults-file=/path/with.ext --print-defaults 2>&1; ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +# Using $MYSQL_TEST_DIR_ABS which contains canonical path to the +# test directory since --print-default prints the absolute path. +--replace_result $MYSQL_TEST_DIR_ABS MYSQL_TEST_DIR --error 1 exec $MYSQLD --defaults-file=relative/path/with.ext --print-defaults 2>&1; ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--replace_result $MYSQL_TEST_DIR_ABS MYSQL_TEST_DIR --error 1 exec $MYSQLD --defaults-file=relative/path/without/extension --print-defaults 2>&1; ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--replace_result $MYSQL_TEST_DIR_ABS MYSQL_TEST_DIR --error 1 exec $MYSQLD --defaults-file=with.ext --print-defaults 2>&1; ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--replace_result $MYSQL_TEST_DIR_ABS MYSQL_TEST_DIR --error 1 exec $MYSQLD --defaults-file=no_extension --print-defaults 2>&1; From e4784703ee44d0a0a497a1a411dea20987d501ad Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Mon, 12 Feb 2018 15:19:43 +0530 Subject: [PATCH 11/42] Bug#25471090: MYSQL USE AFTER FREE Description:- Mysql client crashes when trying to connect to a fake server which is sending incorrect packets. Analysis:- Mysql client crashes when it tries to read server version details. Fix:- A check is added in "red_one_row()". --- include/mysql_com.h | 3 ++- sql-common/client.c | 16 +++++++++------- sql-common/pack.c | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 5cd40915743..52e8a367e3d 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -561,6 +561,7 @@ void my_thread_end(void); #ifdef _global_h ulong STDCALL net_field_length(uchar **packet); +ulong STDCALL net_field_length_checked(uchar **packet, ulong max_length); my_ulonglong net_field_length_ll(uchar **packet); uchar *net_store_length(uchar *pkg, ulonglong length); #endif diff --git a/sql-common/client.c b/sql-common/client.c index 759d95117cb..9972ca741f2 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -1723,18 +1723,20 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) end_pos=pos+pkt_len; for (field=0 ; field < fields ; field++) { - if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH) + len=(ulong) net_field_length_checked(&pos, (ulong)(end_pos - pos)); + if (pos > end_pos) + { + set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); + return -1; + } + + if (len == NULL_LENGTH) { /* null field */ row[field] = 0; *lengths++=0; } else { - if (len > (ulong) (end_pos - pos)) - { - set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); - return -1; - } row[field] = (char*) pos; pos+=len; *lengths++=len; diff --git a/sql-common/pack.c b/sql-common/pack.c index 02e91b5c3e3..57ff55689a2 100644 --- a/sql-common/pack.c +++ b/sql-common/pack.c @@ -1,5 +1,4 @@ -/* Copyright (c) 2000-2003, 2007 MySQL AB - Use is subject to license terms +/* Copyright (c) 2000, 2018 Oracle and/or its affiliates. All rights reserved. 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 @@ -46,6 +45,40 @@ ulong STDCALL net_field_length(uchar **packet) return (ulong) uint4korr(pos+1); } +/* The same as above but with max length check */ +ulong STDCALL net_field_length_checked(uchar **packet, ulong max_length) +{ + ulong len; + uchar *pos= (uchar *)*packet; + + if (*pos < 251) + { + (*packet)++; + len= (ulong) *pos; + return (len > max_length) ? max_length : len; + } + if (*pos == 251) + { + (*packet)++; + return NULL_LENGTH; + } + if (*pos == 252) + { + (*packet)+=3; + len= (ulong) uint2korr(pos+1); + return (len > max_length) ? max_length : len; + } + if (*pos == 253) + { + (*packet)+=4; + len= (ulong) uint3korr(pos+1); + return (len > max_length) ? max_length : len; + } + (*packet)+=9; /* Must be 254 when here */ + len= (ulong) uint4korr(pos+1); + return (len > max_length) ? max_length : len; +} + /* The same as above but returns longlong */ my_ulonglong net_field_length_ll(uchar **packet) { From ddaf0f14704be3fd3d6960f7a3e2fdd0125e2dfd Mon Sep 17 00:00:00 2001 From: Karthik Kamath Date: Wed, 14 Feb 2018 09:35:18 +0530 Subject: [PATCH 12/42] --- storage/innobase/handler/ha_innodb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1c6763ef93a..0591987f4ae 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -9225,8 +9225,10 @@ ha_innobase::start_stmt( case SQLCOM_INSERT: case SQLCOM_UPDATE: case SQLCOM_DELETE: + case SQLCOM_REPLACE: init_table_handle_for_HANDLER(); prebuilt->select_lock_type = LOCK_X; + prebuilt->stored_select_lock_type = LOCK_X; error = row_lock_table_for_mysql(prebuilt, NULL, 1); if (error != DB_SUCCESS) { From 873f8c25b6de24d267cbdedc70de40dc4b5b83aa Mon Sep 17 00:00:00 2001 From: Lars Tangvald Date: Tue, 13 Feb 2018 13:58:43 +0100 Subject: [PATCH 13/42] Bug#27538614 DROP EXTRA CHANGELOG FILE FROM DEB/RPM PACKAGES Change the file to refer to published git repository directly --- Docs/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Docs/ChangeLog diff --git a/Docs/ChangeLog b/Docs/ChangeLog new file mode 100644 index 00000000000..05c9065c3b9 --- /dev/null +++ b/Docs/ChangeLog @@ -0,0 +1,2 @@ +You can find a detailed list of changes at + to https://github.com/mysql/mysql-server/commits/5.5 From c0b4d74b52e7eec9b13af732193f7f8d7abe05de Mon Sep 17 00:00:00 2001 From: Nisha Gopalakrishnan Date: Mon, 26 Feb 2018 14:37:39 +0530 Subject: [PATCH 14/42] BUG#27216817: INNODB: FAILING ASSERTION: PREBUILT->TABLE->N_MYSQL_HANDLES_OPENED == 1 ANALYSIS: ========= Adding unique index to a InnoDB table which is locked as mutliple instances may trigger an InnoDB assert. When we add a primary key or an unique index, we need to drop the original table and rebuild all indexes. InnoDB expects that only the instance of the table that is being rebuilt, is open during the process. In the current scenario we have opened multiple instances of the table. This triggers an assert during table rebuild. 'Locked_tables_list' encapsulates a list of all instances of tables locked by LOCK TABLES statement. FIX: === We are now temporarily closing all the instances of the table except the one which is being altered and later reopen them via Locked_tables_list::reopen_tables(). --- sql/sql_admin.cc | 4 ++-- sql/sql_base.cc | 18 +++++++++++++----- sql/sql_base.h | 5 +++-- sql/sql_partition.cc | 6 +++--- sql/sql_table.cc | 22 ++++++++++++++++++---- sql/sql_trigger.cc | 4 ++-- sql/sql_truncate.cc | 4 ++-- 7 files changed, 43 insertions(+), 20 deletions(-) diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index efdb67d01c4..bfe4edb67c4 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify @@ -168,7 +168,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, */ if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) goto end; - close_all_tables_for_name(thd, table_list->table->s, FALSE); + close_all_tables_for_name(thd, table_list->table->s, FALSE, NULL); table_list->table= 0; } /* diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 27dcbee7b8f..e9ce652cdb1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -1096,7 +1096,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, result= TRUE; goto err_with_reopen; } - close_all_tables_for_name(thd, table->s, FALSE); + close_all_tables_for_name(thd, table->s, FALSE, NULL); } } @@ -1367,13 +1367,16 @@ static void close_open_tables(THD *thd) In that case the documented behaviour is to implicitly remove the table from LOCK TABLES list. + @param[in] skip_table + TABLE instance that should be kept open. @pre Must be called with an X MDL lock on the table. */ void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, - bool remove_from_locked_tables) + bool remove_from_locked_tables, + TABLE *skip_table) { char key[MAX_DBKEY_LENGTH]; uint key_length= share->table_cache_key.length; @@ -1388,7 +1391,8 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, TABLE *table= *prev; if (table->s->table_cache_key.length == key_length && - !memcmp(table->s->table_cache_key.str, key, key_length)) + !memcmp(table->s->table_cache_key.str, key, key_length) && + table != skip_table) { thd->locked_tables_list.unlink_from_list(thd, table->pos_in_locked_tables, @@ -1401,7 +1405,8 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, mysql_lock_remove(thd, thd->lock, table); /* Inform handler that table will be dropped after close */ - if (table->db_stat) /* Not true for partitioned tables. */ + if (table->db_stat && /* Not true for partitioned tables. */ + skip_table == NULL) table->file->extra(HA_EXTRA_PREPARE_FOR_DROP); close_thread_table(thd, prev); } @@ -1411,9 +1416,12 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, prev= &table->next; } } + + if (skip_table == NULL) { /* Remove the table share from the cache. */ tdc_remove_table(thd, TDC_RT_REMOVE_ALL, db, table_name, FALSE); + } } diff --git a/sql/sql_base.h b/sql/sql_base.h index b118c93ac28..28568acc081 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -306,7 +306,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool wait_for_refresh, ulong timeout); bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string); void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, - bool remove_from_locked_tables); + bool remove_from_locked_tables, + TABLE *skip_table); OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild); void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, const char *db, const char *table_name, diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 65d4da0f2f6..bd76a92dc68 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -6512,7 +6512,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) THD *thd= lpt->thd; if (lpt->old_table) - close_all_tables_for_name(thd, lpt->old_table->s, FALSE); + close_all_tables_for_name(thd, lpt->old_table->s, FALSE, NULL); if (lpt->table) { /* @@ -6549,7 +6549,7 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt, bool close_old) } if (close_old && lpt->old_table) { - close_all_tables_for_name(lpt->thd, lpt->old_table->s, FALSE); + close_all_tables_for_name(lpt->thd, lpt->old_table->s, FALSE, NULL); lpt->old_table= 0; } DBUG_RETURN(0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 58bcf5ca1d4..6d02140cfcb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -2165,7 +2165,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, error= -1; goto err; } - close_all_tables_for_name(thd, table->table->s, TRUE); + close_all_tables_for_name(thd, table->table->s, TRUE, NULL); table->table= 0; } @@ -6168,7 +6168,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, */ if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) goto err; - close_all_tables_for_name(thd, table->s, TRUE); + close_all_tables_for_name(thd, table->s, TRUE, NULL); /* Then, we want check once again that target table does not exist. Actually the order of these two steps does not matter since @@ -6305,6 +6305,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, changes only" means also that the handler for the table does not change. The table is open and locked. The handler can be accessed. */ + if (need_copy_table == ALTER_TABLE_INDEX_CHANGED) { int pk_changed= 0; @@ -6606,6 +6607,19 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0L; copied=deleted=0; + + if (thd->locked_tables_mode == LTM_LOCK_TABLES || + thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) + { + /* + Temporarily close the TABLE instances belonging to this + thread except the one to be used for ALTER TABLE. + + This is mostly needed to satisfy InnoDB assumptions/asserts. + */ + close_all_tables_for_name(thd, table->s, false, table); + } + /* We do not copy data for MERGE tables. Only the children have data. MERGE tables have HA_NO_COPY_ON_ALTER set. @@ -6877,7 +6891,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } close_all_tables_for_name(thd, table->s, - new_name != table_name || new_db != db); + new_name != table_name || new_db != db, NULL); error=0; table_list->table= table= 0; /* Safety */ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 0a4f549a052..fe1131c4164 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -568,7 +568,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) if (result) goto end; - close_all_tables_for_name(thd, table->s, FALSE); + close_all_tables_for_name(thd, table->s, FALSE, NULL); /* Reopen the table if we were under LOCK TABLES. Ignore the return value for now. It's better to diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 4f250e6e7a0..d8a0205a495 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 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 @@ -394,7 +394,7 @@ bool Truncate_statement::lock_table(THD *thd, TABLE_LIST *table_ref, m_ticket_downgrade= table->mdl_ticket; /* Close if table is going to be recreated. */ if (*hton_can_recreate) - close_all_tables_for_name(thd, table->s, FALSE); + close_all_tables_for_name(thd, table->s, FALSE, NULL); } else { From 6beb08c7b67ed7610e95c0350f9f93005db1e055 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 4 Apr 2018 09:12:14 +0400 Subject: [PATCH 15/42] MDEV-15624 Changing the default character set to utf8mb4 changes query evaluation in a very surprising way --- mysql-test/r/ctype_ucs.result | 31 +++++++++++++++++++++++++++++++ mysql-test/r/ctype_utf8mb4.result | 23 +++++++++++++++++++++++ mysql-test/t/ctype_ucs.test | 22 ++++++++++++++++++++++ mysql-test/t/ctype_utf8mb4.test | 19 +++++++++++++++++++ sql/item_func.h | 2 ++ sql/item_strfunc.h | 1 + 6 files changed, 98 insertions(+) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 1bbd3af4af7..1c9e31d3a06 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -4397,5 +4397,36 @@ Field Type Null Key Default Extra c1 mediumtext YES NULL DROP TABLE t1; # +# MDEV-15624 Changing the default character set to utf8mb4 changes query evaluation in a very surprising way +# +SET NAMES utf8; +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT COUNT(DISTINCT c) FROM (SELECT id, REPLACE(uuid_short(), '0', CAST('o' AS CHAR CHARACTER SET ucs2)) AS c FROM t1) AS d1; +COUNT(DISTINCT c) +3 +SELECT DISTINCT REPLACE(uuid_short(), '0', CAST('o' AS CHAR CHARACTER SET ucs2)) AS c FROM t1; +c +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +SELECT COUNT(DISTINCT c) FROM (SELECT id, INSERT(uuid_short(), 1, 1, CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1) AS d1; +COUNT(DISTINCT c) +3 +SELECT DISTINCT INSERT(uuid_short(), 1, 1, CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1; +c +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +SELECT COUNT(DISTINCT c) FROM (SELECT id, CONCAT(uuid_short(), CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1) AS d1; +COUNT(DISTINCT c) +3 +SELECT DISTINCT CONCAT(uuid_short(), CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1; +c +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +DROP TABLE t1; +# # End of 5.5 tests # diff --git a/mysql-test/r/ctype_utf8mb4.result b/mysql-test/r/ctype_utf8mb4.result index 17a1a2f787e..2c0bdfb2307 100644 --- a/mysql-test/r/ctype_utf8mb4.result +++ b/mysql-test/r/ctype_utf8mb4.result @@ -2656,6 +2656,29 @@ SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 65536) AS data ) AS sub; len 196608 # +# MDEV-15624 Changing the default character set to utf8mb4 changes query evaluation in a very surprising way +# +SET NAMES utf8mb4; +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT COUNT(DISTINCT c) FROM (SELECT id, REPLACE(UUID(), "-", "") AS c FROM t1) AS d1; +COUNT(DISTINCT c) +3 +SELECT DISTINCT INSERT(uuid(), 9, 1, "X") AS c FROM t1; +c +xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +SELECT COUNT(DISTINCT c) FROM (SELECT id, INSERT(UUID(), 9, 1, "X") AS c FROM t1) AS d1; +COUNT(DISTINCT c) +3 +SELECT DISTINCT INSERT(UUID(), 9, 1, "X") AS c FROM t1; +c +xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +DROP TABLE t1; +# # End of 5.5 tests # # diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index b3d0be4432f..6f846eae771 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -885,6 +885,28 @@ DESCRIBE t1; DROP TABLE t1; +--echo # +--echo # MDEV-15624 Changing the default character set to utf8mb4 changes query evaluation in a very surprising way +--echo # + +SET NAMES utf8; +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3); + +SELECT COUNT(DISTINCT c) FROM (SELECT id, REPLACE(uuid_short(), '0', CAST('o' AS CHAR CHARACTER SET ucs2)) AS c FROM t1) AS d1; +--replace_column 1 xxxxxxxxxxxxxxxxx +SELECT DISTINCT REPLACE(uuid_short(), '0', CAST('o' AS CHAR CHARACTER SET ucs2)) AS c FROM t1; + +SELECT COUNT(DISTINCT c) FROM (SELECT id, INSERT(uuid_short(), 1, 1, CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1) AS d1; +--replace_column 1 xxxxxxxxxxxxxxxxx +SELECT DISTINCT INSERT(uuid_short(), 1, 1, CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1; + +SELECT COUNT(DISTINCT c) FROM (SELECT id, CONCAT(uuid_short(), CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1) AS d1; +--replace_column 1 xxxxxxxxxxxxxxxxx +SELECT DISTINCT CONCAT(uuid_short(), CAST('0' AS CHAR CHARACTER SET ucs2)) AS c FROM t1; +DROP TABLE t1; + + --echo # --echo # End of 5.5 tests --echo # diff --git a/mysql-test/t/ctype_utf8mb4.test b/mysql-test/t/ctype_utf8mb4.test index c240f261af4..551a570c0fc 100644 --- a/mysql-test/t/ctype_utf8mb4.test +++ b/mysql-test/t/ctype_utf8mb4.test @@ -1858,6 +1858,25 @@ SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 21846) AS data ) AS sub; SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 65535) AS data ) AS sub; SELECT LENGTH(data) AS len FROM (SELECT REPEAT('☃', 65536) AS data ) AS sub; +--echo # +--echo # MDEV-15624 Changing the default character set to utf8mb4 changes query evaluation in a very surprising way +--echo # + +SET NAMES utf8mb4; +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3); + +SELECT COUNT(DISTINCT c) FROM (SELECT id, REPLACE(UUID(), "-", "") AS c FROM t1) AS d1; +--replace_column 1 xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +SELECT DISTINCT INSERT(uuid(), 9, 1, "X") AS c FROM t1; + +SELECT COUNT(DISTINCT c) FROM (SELECT id, INSERT(UUID(), 9, 1, "X") AS c FROM t1) AS d1; +--replace_column 1 xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx +SELECT DISTINCT INSERT(UUID(), 9, 1, "X") AS c FROM t1; + +DROP TABLE t1; + + --echo # --echo # End of 5.5 tests --echo # diff --git a/sql/item_func.h b/sql/item_func.h index 60122f03e0b..57818228b98 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -2133,6 +2133,8 @@ public: Item_func_uuid_short() :Item_int_func() {} const char *func_name() const { return "uuid_short"; } longlong val_int(); + bool const_item() const { return false; } + table_map used_tables() const { return RAND_TABLE_BIT; } void fix_length_and_dec() { max_length= 21; unsigned_flag=1; } bool check_vcol_func_processor(uchar *int_arg) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 006b1b90081..c1138c2a930 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -997,6 +997,7 @@ public: DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); fix_char_length(MY_UUID_STRING_LENGTH); } + bool const_item() const { return false; } table_map used_tables() const { return RAND_TABLE_BIT; } const char *func_name() const{ return "uuid"; } String *val_str(String *); From d6f3a0064be73cd134fd474e5ddc63646e09938a Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sat, 7 Apr 2018 21:51:15 +0400 Subject: [PATCH 16/42] MDEV-14185 CREATE TEMPORARY TABLE AS SELECT causes error 1290 with read_only and InnoDB. handler::ha_create_handler_files shouldn't call the mark_trx_read_write() for the temporary table. --- mysql-test/r/read_only_innodb.result | 8 ++++++++ mysql-test/t/read_only_innodb.test | 9 +++++++++ sql/handler.cc | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/read_only_innodb.result b/mysql-test/r/read_only_innodb.result index 1e041395d3c..2af72d30851 100644 --- a/mysql-test/r/read_only_innodb.result +++ b/mysql-test/r/read_only_innodb.result @@ -221,6 +221,14 @@ a a 5 10 DROP TABLE temp1, temp2; +# MDEV-14185 CREATE TEMPORARY TABLE AS SELECT causes error 1290 with read_only and InnoDB. + +CREATE TEMPORARY TABLE temp1 ENGINE=INNODB AS SELECT a FROM t1; +SELECT * FROM temp1; +a +1 +DROP TABLE temp1; + # Disconnect and cleanup SET GLOBAL READ_ONLY = OFF; diff --git a/mysql-test/t/read_only_innodb.test b/mysql-test/t/read_only_innodb.test index de237fecbb6..f89cf745973 100644 --- a/mysql-test/t/read_only_innodb.test +++ b/mysql-test/t/read_only_innodb.test @@ -243,6 +243,15 @@ UPDATE temp1,temp2 SET temp1.a = 5, temp2.a = 10; SELECT * FROM temp1, temp2; DROP TABLE temp1, temp2; +--echo +--echo # MDEV-14185 CREATE TEMPORARY TABLE AS SELECT causes error 1290 with read_only and InnoDB. +--echo + +CREATE TEMPORARY TABLE temp1 ENGINE=INNODB AS SELECT a FROM t1; +SELECT * FROM temp1; +DROP TABLE temp1; + + --echo --echo # Disconnect and cleanup --echo diff --git a/sql/handler.cc b/sql/handler.cc index dc40e34bc3d..d8a9ac6b05a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3770,7 +3770,8 @@ int handler::ha_create_handler_files(const char *name, const char *old_name, int action_flag, HA_CREATE_INFO *info) { - mark_trx_read_write(); + if (!info || !(info->options & HA_LEX_CREATE_TMP_TABLE)) + mark_trx_read_write(); return create_handler_files(name, old_name, action_flag, info); } From 3eb2a265eac53050089bc5d563e65161717a2983 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 8 Apr 2018 09:05:00 +0400 Subject: [PATCH 17/42] MDEV-14185 CREATE TEMPORARY TABLE AS SELECT causes error 1290 with read_only and InnoDB. condition fixed. --- sql/handler.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/handler.cc b/sql/handler.cc index d8a9ac6b05a..ab4d9fd37c9 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3770,7 +3770,7 @@ int handler::ha_create_handler_files(const char *name, const char *old_name, int action_flag, HA_CREATE_INFO *info) { - if (!info || !(info->options & HA_LEX_CREATE_TMP_TABLE)) + if (!opt_readonly || !info || !(info->options & HA_LEX_CREATE_TMP_TABLE)) mark_trx_read_write(); return create_handler_files(name, old_name, action_flag, info); From 226ec99a3ed662bace80d70dd7fefd0db7b4af0a Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 11 Apr 2018 14:22:10 +0400 Subject: [PATCH 18/42] MDEV-15510 - storage/oqgraph: Quench warnings with Boost 1.66 Moved Boost configuration definitions before first inclusion of Boost headers to avoid re-definition. --- storage/oqgraph/graphcore-config.h | 2 ++ storage/oqgraph/oqgraph_shim.h | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/storage/oqgraph/graphcore-config.h b/storage/oqgraph/graphcore-config.h index d5656bddf78..caee39f8c30 100644 --- a/storage/oqgraph/graphcore-config.h +++ b/storage/oqgraph/graphcore-config.h @@ -27,6 +27,8 @@ #define BOOST_ALL_NO_LIB 1 #define BOOST_NO_RTTI 1 #define BOOST_NO_TYPEID 1 +#define BOOST_NO_HASH 1 +#define BOOST_NO_SLIST 1 #ifdef DBUG_OFF #define NDEBUG 1 diff --git a/storage/oqgraph/oqgraph_shim.h b/storage/oqgraph/oqgraph_shim.h index d3e7d044e86..1c83e52ea30 100644 --- a/storage/oqgraph/oqgraph_shim.h +++ b/storage/oqgraph/oqgraph_shim.h @@ -27,9 +27,6 @@ #include "oqgraph_judy.h" #include "oqgraph_thunk.h" -#define BOOST_NO_HASH 1 -#define BOOST_NO_SLIST 1 - #include #include From 88ac368fea2182447284d6bacff4d93ef1acb865 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 13 Jan 2018 14:05:14 +1100 Subject: [PATCH 19/42] defaults-group-suffix in print_defaults Also clarify which --{no-,}default* options, must be first. Sample output: $ client/mysql --help client/mysql Ver 15.1 Distrib 5.5.59-MariaDB, for Linux (x86_64) using readline 5.1 Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Usage: client/mysql [OPTIONS] [database] Default options are read from the following files in the given order: /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf The following groups are read: mysql client client-server client-mariadb The following options may be given as the first argument: --print-defaults Print the program argument list and exit. --no-defaults Don't read default options from any option file. The following specify which files/groups are read (specified before other options): --defaults-file=# Only read default options from the given file #. --defaults-extra-file=# Read this file after the global files are read. --defaults-group-suffix=# Additionally read default groups with # appended as a suffix. tests running from build directory: TEST: print defaults ignored as not first $ sql/mysqld --no-defaults --print-defaults --lc-messages-dir=${PWD}/sql/share TEST: no startup occurs as --print-defaults specified $ sql/mysqld --print-defaults --lc-messages-dir=${PWD}/sql/share sql/mysqld would have been started with the following arguments: --lc-messages-dir=/home/dan/repos/build-mariadb-5.5/sql/share TEST: default args can't be anywhere $ client/mysql --user=bob --defaults-file=/etc/my.cnf client/mysql: unknown variable 'defaults-file=/etc/my.cnf' $ client/mysql --user=bob --defaults-group-suffix=.group client/mysql: unknown variable 'defaults-group-suffix=.group' /etc/my.cnf: [client-server.group] socket=/var/lib/mysql-multi/group/mysqld.sock user=bob /etc/my.other.cnf: socket=/var/lib/mysql-other/mysqld.sock TEST: defaults file read and suffix also applied $ client/mysql --defaults-file=/etc/my.other.cnf --defaults-group-suffix=.group ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql-other/mysqld.sock' (2) TEST: defaults extra file $ client/mysql --defaults-extra-file=/etc/my.other.cnf --defaults-group-suffix=.group ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql-other/mysqld.sock' (2) --- mysql-test/r/mysqld--help.result | 2 ++ mysys/default.c | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index ef68c064dd4..825c7e786a3 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1,8 +1,10 @@ The following options may be given as the first argument: --print-defaults Print the program argument list and exit. --no-defaults Don't read default options from any option file. +The following specify which files/extra groups are read (specified before remaining options): --defaults-file=# Only read default options from the given file #. --defaults-extra-file=# Read this file after the global files are read. +--defaults-group-suffix=# Additionally read default groups with # appended as a suffix. --allow-suspicious-udfs Allows use of UDFs consisting of only one symbol xxx() diff --git a/mysys/default.c b/mysys/default.c index 93a1eff37cb..e901fb0b593 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -1102,10 +1102,12 @@ void print_defaults(const char *conf_file, const char **groups) } } puts("\nThe following options may be given as the first argument:\n\ ---print-defaults Print the program argument list and exit.\n\ ---no-defaults Don't read default options from any option file.\n\ ---defaults-file=# Only read default options from the given file #.\n\ ---defaults-extra-file=# Read this file after the global files are read."); +--print-defaults Print the program argument list and exit.\n\ +--no-defaults Don't read default options from any option file.\n\ +The following specify which files/extra groups are read (specified before remaining options):\n\ +--defaults-file=# Only read default options from the given file #.\n\ +--defaults-extra-file=# Read this file after the global files are read.\n\ +--defaults-group-suffix=# Additionally read default groups with # appended as a suffix."); } From 5e61e1716e763315009318081fba5994b8910242 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 16 Apr 2018 16:59:19 -0700 Subject: [PATCH 20/42] MDEV-14515 ifnull result depends on number of rows in joined table Any expensive WHERE condition for a table-less query with implicit aggregation was lost. As a result the used aggregate functions were calculated over a non-empty set of rows even in the case when the condition was false. --- mysql-test/r/subselect4.result | 24 ++++++++++++++++++++++-- mysql-test/t/subselect4.test | 23 +++++++++++++++++++++++ sql/opt_subselect.cc | 1 + 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index c20c048b919..6accc23d18a 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -1056,7 +1056,7 @@ EXPLAIN SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE -2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); f1 f2 SET @@optimizer_switch = 'materialization=off,in_to_exists=on,semijoin=off'; @@ -1147,7 +1147,7 @@ EXPLAIN SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE -2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No matching min/max row +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables SELECT * FROM t1 WHERE (2, 0) NOT IN (SELECT min(f3)+f3, min(f4)+f3+max(f4) FROM t2 WHERE f3 > 10); f1 f2 set @@optimizer_switch=@save_optimizer_switch; @@ -2511,3 +2511,23 @@ SELECT 2 IN (SELECT 2 from DUAL WHERE 1 != 1); 0 SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; +# +# mfrv-14515: Wrong results for tableless query with subquery in WHERE +# and implicit aggregation +# +create table t1 (i1 int, i2 int); +insert into t1 values (1314, 1084),(1330, 1084),(1401, 1084),(580, 1084); +create table t2 (cd int); +insert into t2 values +(1330), (1330), (1330), (1330), (1330), (1330), (1330), (1330), +(1330), (1330), (1330), (1330), (1330), (1330), (1330), (1330); +select max(10) from dual +where exists (select 1 from t2 join t1 on t1.i1 = t2.cd and t1.i2 = 345); +max(10) +NULL +insert into t2 select * from t2; +select max(10) from dual +where exists (select 1 from t2 join t1 on t1.i1 = t2.cd and t1.i2 = 345); +max(10) +NULL +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index 673dc9be0b4..2b53b55b735 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -2045,3 +2045,26 @@ SELECT 2 IN (SELECT 2 from DUAL WHERE 1 != 1); SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; + +--echo # +--echo # mfrv-14515: Wrong results for tableless query with subquery in WHERE +--echo # and implicit aggregation +--echo # + +create table t1 (i1 int, i2 int); +insert into t1 values (1314, 1084),(1330, 1084),(1401, 1084),(580, 1084); + +create table t2 (cd int); +insert into t2 values + (1330), (1330), (1330), (1330), (1330), (1330), (1330), (1330), + (1330), (1330), (1330), (1330), (1330), (1330), (1330), (1330); + +select max(10) from dual + where exists (select 1 from t2 join t1 on t1.i1 = t2.cd and t1.i2 = 345); + +insert into t2 select * from t2; + +select max(10) from dual + where exists (select 1 from t2 join t1 on t1.i1 = t2.cd and t1.i2 = 345); + +DROP TABLE t1,t2; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index c21541c4b97..1bda84bacd7 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -5903,5 +5903,6 @@ bool JOIN::choose_tableless_subquery_plan() tmp_having= having; } } + exec_const_cond= conds; return FALSE; } From 4f5dd1d40eca3cd128023a9bf636e83489430c78 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 17 Apr 2018 00:44:46 +0200 Subject: [PATCH 21/42] ASAN error in main.statistics_index_crash-7362 one cannot do keyread on spatial indexes. --- sql/sql_statistics.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 6c42efd6068..ce320e87a4f 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2475,7 +2475,7 @@ int collect_statistics_for_index(THD *thd, TABLE *table, uint index) DBUG_ENTER("collect_statistics_for_index"); /* No statistics for FULLTEXT indexes. */ - if (key_info->flags & HA_FULLTEXT) + if (key_info->flags & (HA_FULLTEXT|HA_SPATIAL)) DBUG_RETURN(rc); Index_prefix_calc index_prefix_calc(table, key_info); From 3aa5f00e69343a44aa1eac599aed0117a5fa264c Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Thu, 19 Apr 2018 10:29:13 +0200 Subject: [PATCH 22/42] MDEV-15929 Fix lock wait timeout on `SELECT @@GLOBAL.WSREP_ON` This patch fixes a lock wait timeout error on `SELECT @@GLOBAL.WSREP_ON` in `wait_wsrep_ready.inc`: ``` --connection node_2 ... --source include/kill_galera.inc --connection node_1 --source include/wait_until_connected_again.inc # This includes wait_wsrep_ready.inc ``` The problem is that on node_2, kill_galera.inc may return before the node is killed. So node_1 may still see that node_1 is alive and will attempt to sync wait when doing those `SELECT` statements. But sync wait is doomed to fail given that node_1 is killed, hence the lock wait timeout. One possible fix is to disable wsrep_sync_wait before including wait_until_connected_again. However, it appears that including wait_until_connected_again is not necessary at all in node_1, so this patch removes it altogether. --- mysql-test/suite/galera/include/galera_st_kill_slave.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/suite/galera/include/galera_st_kill_slave.inc b/mysql-test/suite/galera/include/galera_st_kill_slave.inc index bae37755c65..ecdf08726a0 100644 --- a/mysql-test/suite/galera/include/galera_st_kill_slave.inc +++ b/mysql-test/suite/galera/include/galera_st_kill_slave.inc @@ -24,7 +24,6 @@ COMMIT; --source include/kill_galera.inc --connection node_1 ---source include/wait_until_connected_again.inc --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc From f1258e7cd2c57886e5eb4cf51b4ab3a9c030cbab Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Apr 2018 22:32:27 +0200 Subject: [PATCH 23/42] BUG#26881798: SERVER EXITS WHEN PRIMARY KEY IN MYSQL.PROC IS DROPPED test case --- mysql-test/r/sp-destruct.result | 6 ++++++ mysql-test/t/sp-destruct.test | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/mysql-test/r/sp-destruct.result b/mysql-test/r/sp-destruct.result index 2dac0270ce1..b8f9a516d1e 100644 --- a/mysql-test/r/sp-destruct.result +++ b/mysql-test/r/sp-destruct.result @@ -174,3 +174,9 @@ create database mysqltest1; create procedure mysqltest1.foo() select "foo"; update mysql.proc set name='' where db='mysqltest1'; drop database mysqltest1; +create procedure p1() set @foo = 10; +alter table mysql.proc drop primary key; +drop procedure p1; +ERROR HY000: Cannot load from mysql.proc. The table is probably corrupted +alter table mysql.proc add primary key (db,name,type); +drop procedure p1; diff --git a/mysql-test/t/sp-destruct.test b/mysql-test/t/sp-destruct.test index 3a2e9259938..e5314f89fd5 100644 --- a/mysql-test/t/sp-destruct.test +++ b/mysql-test/t/sp-destruct.test @@ -289,3 +289,13 @@ create database mysqltest1; create procedure mysqltest1.foo() select "foo"; update mysql.proc set name='' where db='mysqltest1'; drop database mysqltest1; + +# +# BUG#26881798: SERVER EXITS WHEN PRIMARY KEY IN MYSQL.PROC IS DROPPED +# +create procedure p1() set @foo = 10; +alter table mysql.proc drop primary key; +--error ER_CANNOT_LOAD_FROM_TABLE +drop procedure p1; +alter table mysql.proc add primary key (db,name,type); +drop procedure p1; From 149c993b2cdf4b6ccdce6f8bbbd28a38fc7404ee Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Apr 2018 22:36:46 +0200 Subject: [PATCH 24/42] BUG#27216817: INNODB: FAILING ASSERTION: PREBUILT->TABLE->N_MYSQL_HANDLES_OPENED == 1 disable online alter add primary key for innodb, if the table is opened/locked more than once in the current connection (see assert in ha_innobase::add_index()) --- .../suite/innodb/r/innodb_bug27216817.result | 24 ++++++++++++++++ .../suite/innodb/t/innodb_bug27216817.test | 28 +++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 11 ++++++++ storage/innobase/handler/ha_innodb.h | 1 + storage/xtradb/handler/ha_innodb.cc | 11 ++++++++ storage/xtradb/handler/ha_innodb.h | 1 + 6 files changed, 76 insertions(+) create mode 100644 mysql-test/suite/innodb/r/innodb_bug27216817.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug27216817.test diff --git a/mysql-test/suite/innodb/r/innodb_bug27216817.result b/mysql-test/suite/innodb/r/innodb_bug27216817.result new file mode 100644 index 00000000000..f930171ff23 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug27216817.result @@ -0,0 +1,24 @@ +create table t1 (a int not null, b int not null) engine=innodb; +insert t1 values (1,2),(3,4); +lock table t1 write, t1 tr read; +flush status; +alter table t1 add primary key (b); +show status like 'Handler_read_rnd_next'; +Variable_name Value +Handler_read_rnd_next 3 +unlock tables; +alter table t1 drop primary key; +lock table t1 write; +flush status; +alter table t1 add primary key (b); +show status like 'Handler_read_rnd_next'; +Variable_name Value +Handler_read_rnd_next 0 +unlock tables; +alter table t1 drop primary key; +flush status; +alter table t1 add primary key (b); +show status like 'Handler_read_rnd_next'; +Variable_name Value +Handler_read_rnd_next 0 +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb_bug27216817.test b/mysql-test/suite/innodb/t/innodb_bug27216817.test new file mode 100644 index 00000000000..a93932b4a04 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug27216817.test @@ -0,0 +1,28 @@ +# +# BUG#27216817: INNODB: FAILING ASSERTION: +# PREBUILT->TABLE->N_MYSQL_HANDLES_OPENED == 1 +# + +source include/have_innodb.inc; +create table t1 (a int not null, b int not null) engine=innodb; +insert t1 values (1,2),(3,4); + +lock table t1 write, t1 tr read; +flush status; +alter table t1 add primary key (b); +show status like 'Handler_read_rnd_next'; +unlock tables; +alter table t1 drop primary key; + +lock table t1 write; +flush status; +alter table t1 add primary key (b); +show status like 'Handler_read_rnd_next'; +unlock tables; +alter table t1 drop primary key; + +flush status; +alter table t1 add primary key (b); +show status like 'Handler_read_rnd_next'; + +drop table t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c3bacee91ff..8da89918b84 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11147,6 +11147,17 @@ ha_innobase::check_if_incompatible_data( return(COMPATIBLE_DATA_YES); } +UNIV_INTERN +uint +ha_innobase::alter_table_flags(uint flags) +{ + uint mask = 0; + if (prebuilt->table->n_mysql_handles_opened > 1) { + mask = HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE; + } + return innobase_alter_table_flags(flags) & ~mask; +} + /************************************************************//** Validate the file format name and return its corresponding id. @return valid file format id */ diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 42aae4dc20e..f80330d6128 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -228,6 +228,7 @@ class ha_innobase: public handler /** @} */ bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); + uint alter_table_flags(uint flags); }; /* Some accessor functions which the InnoDB plugin needs, but which diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index a17ab44f49d..94e49d4897a 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -12480,6 +12480,17 @@ ha_innobase::check_if_incompatible_data( DBUG_RETURN(COMPATIBLE_DATA_YES); } +UNIV_INTERN +uint +ha_innobase::alter_table_flags(uint flags) +{ + uint mask = 0; + if (prebuilt->table->n_mysql_handles_opened > 1) { + mask = HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE; + } + return innobase_alter_table_flags(flags) & ~mask; +} + /************************************************************//** Validate the file format name and return its corresponding id. @return valid file format id */ diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 914055a9271..2c3011b0bbb 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -230,6 +230,7 @@ class ha_innobase: public handler /** @} */ bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); + uint alter_table_flags(uint flags); bool check_if_supported_virtual_columns(void) { return TRUE; } private: From 7828ba0df488de8c793e41e4bd3de79e06c2537f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 19 Apr 2018 22:39:24 +0200 Subject: [PATCH 25/42] Bug#25471090: MYSQL USE AFTER FREE in a specially crafted invalid packet, one can get end_pos < pos here --- sql-common/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-common/client.c b/sql-common/client.c index fc591e21616..bb7bdb1ff7d 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1708,7 +1708,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) } else { - if (len > (ulong) (end_pos - pos)) + if (pos + len > end_pos) { set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); return -1; From 4fd1c7e453eac90928df1c74f443a6237fa792b8 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 20 Apr 2018 01:01:56 +0200 Subject: [PATCH 26/42] 5.5.59-38.11 --- storage/xtradb/include/univ.i | 2 +- storage/xtradb/trx/trx0purge.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 9591df0cfc8..64a2bfa70fe 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */ (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR) #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 38.10 +#define PERCONA_INNODB_VERSION 38.11 #endif #define INNODB_VERSION_STR MYSQL_SERVER_VERSION diff --git a/storage/xtradb/trx/trx0purge.c b/storage/xtradb/trx/trx0purge.c index d343a73c9d8..1b87c8543f2 100644 --- a/storage/xtradb/trx/trx0purge.c +++ b/storage/xtradb/trx/trx0purge.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 @@ -729,6 +729,7 @@ trx_purge_rseg_get_next_history_log( mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); +#ifdef UNIV_DEBUG mutex_enter(&kernel_mutex); /* Add debug code to track history list corruption reported @@ -742,18 +743,20 @@ trx_purge_rseg_get_next_history_log( if (trx_sys->rseg_history_len > 2000000) { ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Warning: purge reached the" + " InnoDB: Warning: purge reached the" " head of the history list,\n" "InnoDB: but its length is still" - " reported as %lu! Make a detailed bug\n" - "InnoDB: report, and submit it" - " to http://bugs.mysql.com\n", + " reported as %lu!." + " This can happen becasue a long" + " running transaction is withholding" + " purging of undo logs or a read" + " view is open. Please try to commit" + " the long running transaction.", (ulong) trx_sys->rseg_history_len); - ut_ad(0); } mutex_exit(&kernel_mutex); - +#endif return; } From 86718fda4e5363b05aa2beaac596ec614aaa7a0f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 20 Apr 2018 09:40:29 +0200 Subject: [PATCH 27/42] compiler warning bad merge --- storage/xtradb/log/log0online.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 1a30501f266..1e373c8345f 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -486,9 +486,6 @@ log_online_make_bitmap_name( bmp_file_name_stem, log_bmp_sys->out_seq_num, start_lsn); } -/*********************************************************************//** -} - /*********************************************************************//** Check if an old file that has the name of a new bitmap file we are about to create should be overwritten. */ From bcb36ee21e2515d17dcf03b760487e64eb780f2b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 20 Apr 2018 10:10:33 +0200 Subject: [PATCH 28/42] MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION ALTER TABLE ... ADD PARTITION modifies the open TABLE structure, and sets table->need_reopen=1 to reset these modifications in case of an error. But under LOCK TABLES the table isn't get reopened, despite need_reopen. Fixed by reopening need_reopen tables under LOCK TABLE. --- .../suite/parts/inc/part_alter_values.inc | 10 ++++++++ .../parts/r/partition_alter_innodb.result | 6 +++++ .../parts/r/partition_alter_maria.result | 6 +++++ .../parts/r/partition_alter_myisam.result | 6 +++++ sql/sql_admin.cc | 2 +- sql/sql_base.cc | 23 +++++++++++++++---- sql/sql_class.h | 2 +- sql/sql_partition.cc | 4 ++-- sql/sql_partition_admin.cc | 2 +- sql/sql_table.cc | 8 +++---- sql/sql_trigger.cc | 2 +- sql/sql_truncate.cc | 2 +- 12 files changed, 58 insertions(+), 15 deletions(-) diff --git a/mysql-test/suite/parts/inc/part_alter_values.inc b/mysql-test/suite/parts/inc/part_alter_values.inc index 0d4929d9820..1b0605ff57b 100644 --- a/mysql-test/suite/parts/inc/part_alter_values.inc +++ b/mysql-test/suite/parts/inc/part_alter_values.inc @@ -35,3 +35,13 @@ ALTER TABLE t1 REORGANIZE PARTITION p1 INTO PARTITION p3 VALUES IN (4,5,6) ); DROP TABLE t1; + +# +# MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION +# +create table t1 (i int) partition by range(i) (partition p0 values less than (10)); +lock table t1 write; +--error ER_SAME_NAME_PARTITION +alter table t1 add partition (partition p0 values less than (20)); +alter table t1 add partition (partition p1 values less than (20)) /* comment */; +drop table t1; diff --git a/mysql-test/suite/parts/r/partition_alter_innodb.result b/mysql-test/suite/parts/r/partition_alter_innodb.result index 29076a3c178..08f0c321119 100644 --- a/mysql-test/suite/parts/r/partition_alter_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter_innodb.result @@ -47,3 +47,9 @@ PARTITION p3 VALUES IN (4,5,6) ); ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition DROP TABLE t1; +create table t1 (i int) partition by range(i) (partition p0 values less than (10)); +lock table t1 write; +alter table t1 add partition (partition p0 values less than (20)); +ERROR HY000: Duplicate partition name p0 +alter table t1 add partition (partition p1 values less than (20)) /* comment */; +drop table t1; diff --git a/mysql-test/suite/parts/r/partition_alter_maria.result b/mysql-test/suite/parts/r/partition_alter_maria.result index 7d923570cfe..5e53dc99db8 100644 --- a/mysql-test/suite/parts/r/partition_alter_maria.result +++ b/mysql-test/suite/parts/r/partition_alter_maria.result @@ -69,3 +69,9 @@ PARTITION p3 VALUES IN (4,5,6) ); ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition DROP TABLE t1; +create table t1 (i int) partition by range(i) (partition p0 values less than (10)); +lock table t1 write; +alter table t1 add partition (partition p0 values less than (20)); +ERROR HY000: Duplicate partition name p0 +alter table t1 add partition (partition p1 values less than (20)) /* comment */; +drop table t1; diff --git a/mysql-test/suite/parts/r/partition_alter_myisam.result b/mysql-test/suite/parts/r/partition_alter_myisam.result index 9f2381039d3..0d3094418ff 100644 --- a/mysql-test/suite/parts/r/partition_alter_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter_myisam.result @@ -42,3 +42,9 @@ PARTITION p3 VALUES IN (4,5,6) ); ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition DROP TABLE t1; +create table t1 (i int) partition by range(i) (partition p0 values less than (10)); +lock table t1 write; +alter table t1 add partition (partition p0 values less than (20)); +ERROR HY000: Duplicate partition name p0 +alter table t1 add partition (partition p1 values less than (20)) /* comment */; +drop table t1; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 3aac41d6e41..6ba6f8a912e 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -238,7 +238,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, if (thd->locked_tables_list.locked_tables()) { - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) goto end; /* Restore the table in the table list with the new opened table */ table_list->table= pos_in_locked_tables->table; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 964f82e7331..7d27e87180c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -568,7 +568,7 @@ err_with_reopen: old locks. This should always succeed (unless some external process has removed the tables) */ - thd->locked_tables_list.reopen_tables(thd); + thd->locked_tables_list.reopen_tables(thd, false); /* Since downgrade_lock() won't do anything with shared metadata lock it is much simpler to go through all open tables rather @@ -952,7 +952,10 @@ void close_thread_tables(THD *thd) we will exit this function a few lines below. */ if (! thd->lex->requires_prelocking()) + { + thd->locked_tables_list.reopen_tables(thd, true); DBUG_VOID_RETURN; + } /* We are in the top-level statement of a prelocked statement, @@ -2973,7 +2976,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) */ bool -Locked_tables_list::reopen_tables(THD *thd) +Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) { Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); size_t reopen_count= 0; @@ -2984,8 +2987,20 @@ Locked_tables_list::reopen_tables(THD *thd) for (TABLE_LIST *table_list= m_locked_tables; table_list; table_list= table_list->next_global) { - if (table_list->table) /* The table was not closed */ - continue; + if (need_reopen) + { + if (!table_list->table || !table_list->table->needs_reopen()) + continue; + /* no need to remove the table from the TDC here, thus (TABLE*)1 */ + close_all_tables_for_name(thd, table_list->table->s, + HA_EXTRA_NOT_USED, (TABLE*)1); + DBUG_ASSERT(table_list->table == NULL); + } + else + { + if (table_list->table) /* The table was not closed */ + continue; + } /* Links into thd->open_tables upon success */ if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) diff --git a/sql/sql_class.h b/sql/sql_class.h index 518e88fcd1c..ec94f6c45d2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1603,7 +1603,7 @@ public: void unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count); - bool reopen_tables(THD *thd); + bool reopen_tables(THD *thd, bool need_reopen); bool restore_lock(THD *thd, TABLE_LIST *dst_table_list, TABLE *table, MYSQL_LOCK *lock); void add_back_last_deleted_lock(TABLE_LIST *dst_table_list); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 1c270521a12..fa7e68305d8 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6558,7 +6558,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) thd->set_stmt_da(&tmp_stmt_da); } - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE"); if (stmt_da) @@ -6762,7 +6762,7 @@ err_exclusive_lock: thd->set_stmt_da(&tmp_stmt_da); } - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE"); if (stmt_da) diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 9b471f97521..39b7f4c49f6 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -630,7 +630,7 @@ bool Sql_cmd_alter_table_exchange_partition:: better to keep master/slave in consistent state. Alternative would be to try to revert the exchange operation and issue error. */ - (void) thd->locked_tables_list.reopen_tables(thd); + (void) thd->locked_tables_list.reopen_tables(thd, false); if ((error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()))) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 607f20d2396..5e6385d3bc5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5059,7 +5059,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, This should always work as we have a meta lock on the table. */ thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables); - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) { thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); result= 1; @@ -5408,7 +5408,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, This should always work as we have a meta lock on the table. */ thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables); - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) { thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); res= 1; // We got an error @@ -7239,7 +7239,7 @@ static bool mysql_inplace_alter_table(THD *thd, HA_EXTRA_PREPARE_FOR_RENAME : HA_EXTRA_NOT_USED, NULL); - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); /* QQ; do something about metadata locks ? */ } @@ -9224,7 +9224,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, end_inplace: - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) goto err_with_mdl_after_alter; THD_STAGE_INFO(thd, stage_end); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index b17775abb7c..d26afdefcf9 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -574,7 +574,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) Ignore the return value for now. It's better to keep master/slave in consistent state. */ - if (thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_list.reopen_tables(thd, false)) thd->clear_error(); /* diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 05869b70c8f..ff373f2f29a 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -494,7 +494,7 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) */ error= dd_recreate_table(thd, table_ref->db, table_ref->table_name); - if (thd->locked_tables_mode && thd->locked_tables_list.reopen_tables(thd)) + if (thd->locked_tables_mode && thd->locked_tables_list.reopen_tables(thd, false)) thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0); /* No need to binlog a failed truncate-by-recreate. */ From 9e5671f1cc190f9b9498eafcf858460a56ff3a38 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Fri, 20 Apr 2018 14:44:27 +0200 Subject: [PATCH 29/42] MDEV-15948 Fix error "Lost connection to MySQL server..." in test galera_sst_mysqldump Test galera_sst_mysqldump often fails with error "2013: Lost connection to MySQL server during query". The connection is lost after the test restart one of the nodes. This happens because the server closes client connections if it is joining a cluster through SST method mysqldump. On unlucky runs of the test it is possible that mysqld is restarted, and then mtr client is disconnected while it tries to determine if galera is ready before going on with the test. This patch rewrites galera_wait_ready.inc so that it is immune to being disconnected. --- mysql-test/include/galera_wait_ready.inc | 34 +++++++++++++++++-- .../galera/include/galera_load_provider.inc | 4 +-- .../suite/galera/include/start_mysqld.inc | 9 +---- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/mysql-test/include/galera_wait_ready.inc b/mysql-test/include/galera_wait_ready.inc index e20f01fad90..cd06bae8207 100644 --- a/mysql-test/include/galera_wait_ready.inc +++ b/mysql-test/include/galera_wait_ready.inc @@ -1,2 +1,32 @@ -let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' AND VARIABLE_VALUE = 'ON'; ---source include/wait_condition.inc +# include/galera_wait_ready.inc +# +# Waits for galera node to transition to READY state. +# + +--enable_reconnect +--disable_query_log +--disable_result_log +let $wait_counter = 300; +while ($wait_counter) +{ + --disable_abort_on_error + let $success = `SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'`; + --enable_abort_on_error + if ($success) + { + let $wait_counter = 0; + } + if (!$success) + { + real_sleep 0.1; + dec $wait_counter; + } +} + +if (!$success) +{ + die "Server did not transition to READY state"; +} +--disable_reconnect +--enable_query_log +--enable_result_log diff --git a/mysql-test/suite/galera/include/galera_load_provider.inc b/mysql-test/suite/galera/include/galera_load_provider.inc index 761a1a89fd3..aeab7e6ea19 100644 --- a/mysql-test/suite/galera/include/galera_load_provider.inc +++ b/mysql-test/suite/galera/include/galera_load_provider.inc @@ -5,6 +5,4 @@ --eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; --enable_query_log ---enable_reconnect ---source include/wait_until_connected_again.inc ---source include/wait_until_ready.inc +--source include/galera_wait_ready.inc diff --git a/mysql-test/suite/galera/include/start_mysqld.inc b/mysql-test/suite/galera/include/start_mysqld.inc index 4ee3d17810c..57af9203d0f 100644 --- a/mysql-test/suite/galera/include/start_mysqld.inc +++ b/mysql-test/suite/galera/include/start_mysqld.inc @@ -12,11 +12,4 @@ if ($galera_wsrep_start_position == '') { --exec echo "restart:$start_mysqld_params" > $_expect_file_name } -# Turn on reconnect ---enable_reconnect - -# Call script that will poll the server waiting for it to be back online again ---source include/wait_until_connected_again.inc - -# Turn off reconnect again ---disable_reconnect +--source include/galera_wait_ready.inc From 9fffa9374cd2479d91d4989387c28eede5dff2d9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 20 Apr 2018 20:58:46 +0200 Subject: [PATCH 30/42] mysqltest: use do_stmt_close() not mysql_stmt_close() do_stmt_close() is embedded-aware. this fixes the failure of innodb.innodb_bug48024 --ps --embed --- client/mysqltest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index f1c50432e4d..0f010cd1b57 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1418,7 +1418,7 @@ void close_statements() for (con= connections; con < next_con; con++) { if (con->stmt) - mysql_stmt_close(con->stmt); + do_stmt_close(con); con->stmt= 0; } DBUG_VOID_RETURN; From f2433b8dd3c10b1e26a6f0b98dfbaa45b22fe0af Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 21 Apr 2018 13:13:19 +0200 Subject: [PATCH 31/42] MDEV-10824 - Crash in CREATE OR REPLACE TABLE t1 AS SELECT spfunc() followup for a3c980b381ea same change in Locked_tables_list::unlink_from_list(), otherwise thd->locked_tables_list will keep pointers to a free'd TABLE if prelocked under lock tables. This fixes a crash in main.create_or_replace on debug Win builds after bcb36ee21e25 --- sql/sql_base.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7d27e87180c..f7de4e4f3c2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2872,7 +2872,8 @@ void Locked_tables_list::unlink_from_list(THD *thd, If mode is not LTM_LOCK_TABLES, we needn't do anything. Moreover, outside this mode pos_in_locked_tables value is not trustworthy. */ - if (thd->locked_tables_mode != LTM_LOCK_TABLES) + if (thd->locked_tables_mode != LTM_LOCK_TABLES && + thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES) return; /* From 63e5307afd12f592688c98a449054ee29e2e1422 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Mon, 23 Apr 2018 12:00:49 +0200 Subject: [PATCH 32/42] MDEV-15948 Followup commit * Increased timeout counter in galera_wait_ready.inc * Replaced useless include/wait_until_ready.inc after start_mysqld.inc in galera_st_*.inc with wait_condition on cluster size. --- mysql-test/include/galera_wait_ready.inc | 2 +- mysql-test/suite/galera/include/galera_st_clean_slave.inc | 4 +++- mysql-test/suite/galera/include/galera_st_kill_slave.inc | 4 +++- mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc | 4 +++- mysql-test/suite/galera/include/galera_st_shutdown_slave.inc | 4 +++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/mysql-test/include/galera_wait_ready.inc b/mysql-test/include/galera_wait_ready.inc index cd06bae8207..a726116f000 100644 --- a/mysql-test/include/galera_wait_ready.inc +++ b/mysql-test/include/galera_wait_ready.inc @@ -6,7 +6,7 @@ --enable_reconnect --disable_query_log --disable_result_log -let $wait_counter = 300; +let $wait_counter = 600; while ($wait_counter) { --disable_abort_on_error diff --git a/mysql-test/suite/galera/include/galera_st_clean_slave.inc b/mysql-test/suite/galera/include/galera_st_clean_slave.inc index 81ba54aa6f5..3a49f4f6ad2 100644 --- a/mysql-test/suite/galera/include/galera_st_clean_slave.inc +++ b/mysql-test/suite/galera/include/galera_st_clean_slave.inc @@ -64,7 +64,9 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); --connection node_2 --echo Starting server ... --source include/start_mysqld.inc ---source include/wait_until_ready.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc SET AUTOCOMMIT=OFF; START TRANSACTION; diff --git a/mysql-test/suite/galera/include/galera_st_kill_slave.inc b/mysql-test/suite/galera/include/galera_st_kill_slave.inc index bae37755c65..534d7b64af7 100644 --- a/mysql-test/suite/galera/include/galera_st_kill_slave.inc +++ b/mysql-test/suite/galera/include/galera_st_kill_slave.inc @@ -59,7 +59,9 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); --echo Starting server ... --source include/start_mysqld.inc ---source include/wait_until_ready.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc SET AUTOCOMMIT=OFF; START TRANSACTION; diff --git a/mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc b/mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc index 72e80505870..44a1513fa6e 100644 --- a/mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc +++ b/mysql-test/suite/galera/include/galera_st_kill_slave_ddl.inc @@ -72,7 +72,9 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); --connection node_2 --echo Starting server ... --source include/start_mysqld.inc ---source include/wait_until_ready.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc SET AUTOCOMMIT=OFF; START TRANSACTION; diff --git a/mysql-test/suite/galera/include/galera_st_shutdown_slave.inc b/mysql-test/suite/galera/include/galera_st_shutdown_slave.inc index 1a65ef1bd94..6c09b0ceb0c 100644 --- a/mysql-test/suite/galera/include/galera_st_shutdown_slave.inc +++ b/mysql-test/suite/galera/include/galera_st_shutdown_slave.inc @@ -56,7 +56,9 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); --connection node_2 --echo Starting server ... --source include/start_mysqld.inc ---source include/wait_until_ready.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc SET AUTOCOMMIT=OFF; START TRANSACTION; From 01b2e773ef7a19dbd28a345021cd3a9aa6b10603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 20 Apr 2018 10:35:22 +0300 Subject: [PATCH 33/42] MDEV-15937 Assertion failure 'key->flags & 1' on ALTER TABLE While the test case crashes a MariaDB 10.2 debug build only, let us apply the fix to the earliest applicable MariaDB series (10.0) to avoid any data corruption on a table-rebuilding ALTER TABLE using ALGORITHM=INPLACE. innobase_create_key_defs(): Use altered_table->s->primary_key when a new primary key is being created. --- .../suite/innodb/r/innodb-alter-nullable.result | 4 ++++ mysql-test/suite/innodb/t/innodb-alter-nullable.test | 5 +++++ storage/innobase/handler/handler0alter.cc | 12 ++++-------- storage/xtradb/handler/handler0alter.cc | 12 ++++-------- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-alter-nullable.result b/mysql-test/suite/innodb/r/innodb-alter-nullable.result index e9711b2ac31..2769bfdf1f5 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-nullable.result +++ b/mysql-test/suite/innodb/r/innodb-alter-nullable.result @@ -51,3 +51,7 @@ WHERE NAME='test/t'; TABLE_ID NAME FLAG N_COLS SPACE FILE_FORMAT ROW_FORMAT ZIP_PAGE_SIZE # test/t 1 6 # Antelope Compact 0 DROP TABLE t; +CREATE TABLE t1(c1 INT) ENGINE=InnoDB; +ALTER TABLE t1 ADD CONSTRAINT UNIQUE KEY i1(c1); +ALTER TABLE t1 CHANGE c1 c1 INT NOT NULL,ADD KEY(c1); +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-alter-nullable.test b/mysql-test/suite/innodb/t/innodb-alter-nullable.test index bb5cdee000a..d039459f91f 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-nullable.test +++ b/mysql-test/suite/innodb/t/innodb-alter-nullable.test @@ -71,6 +71,11 @@ WHERE NAME='test/t'; DROP TABLE t; +CREATE TABLE t1(c1 INT) ENGINE=InnoDB; +ALTER TABLE t1 ADD CONSTRAINT UNIQUE KEY i1(c1); +ALTER TABLE t1 CHANGE c1 c1 INT NOT NULL,ADD KEY(c1); +DROP TABLE t1; + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 8761d5434b5..8a9ec1865b4 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1594,6 +1594,7 @@ innobase_create_index_def( if (key_clustered) { DBUG_ASSERT(!(key->flags & HA_FULLTEXT)); + DBUG_ASSERT(key->flags & HA_NOSAME); index->ind_type |= DICT_CLUSTERED; } else if (key->flags & HA_FULLTEXT) { DBUG_ASSERT(!(key->flags & HA_KEYFLAG_MASK @@ -1909,14 +1910,9 @@ innobase_create_key_defs( ulint primary_key_number; if (new_primary) { - if (n_add == 0) { - DBUG_ASSERT(got_default_clust); - DBUG_ASSERT(altered_table->s->primary_key - == 0); - primary_key_number = 0; - } else { - primary_key_number = *add; - } + DBUG_ASSERT(n_add || got_default_clust); + DBUG_ASSERT(n_add || !altered_table->s->primary_key); + primary_key_number = altered_table->s->primary_key; } else if (got_default_clust) { /* Create the GEN_CLUST_INDEX */ index_def_t* index = indexdef++; diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index e5be3aea44a..4a50b324e22 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1595,6 +1595,7 @@ innobase_create_index_def( if (key_clustered) { DBUG_ASSERT(!(key->flags & HA_FULLTEXT)); + DBUG_ASSERT(key->flags & HA_NOSAME); index->ind_type |= DICT_CLUSTERED; } else if (key->flags & HA_FULLTEXT) { DBUG_ASSERT(!(key->flags & HA_KEYFLAG_MASK @@ -1910,14 +1911,9 @@ innobase_create_key_defs( ulint primary_key_number; if (new_primary) { - if (n_add == 0) { - DBUG_ASSERT(got_default_clust); - DBUG_ASSERT(altered_table->s->primary_key - == 0); - primary_key_number = 0; - } else { - primary_key_number = *add; - } + DBUG_ASSERT(n_add || got_default_clust); + DBUG_ASSERT(n_add || !altered_table->s->primary_key); + primary_key_number = altered_table->s->primary_key; } else if (got_default_clust) { /* Create the GEN_CLUST_INDEX */ index_def_t* index = indexdef++; From 88b1905eda23226515a9ff59999c9a5a9ddf4958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 20 Apr 2018 22:05:19 +0300 Subject: [PATCH 34/42] Fix -Wimplicit-fallthrough --- storage/innobase/include/data0type.ic | 2 ++ storage/xtradb/include/data0type.ic | 2 ++ 2 files changed, 4 insertions(+) diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index eaa90f6d33a..c04da618a84 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -524,6 +524,7 @@ dtype_get_fixed_size_low( return(0); } #endif /* UNIV_DEBUG */ + /* fall through */ case DATA_CHAR: case DATA_FIXBINARY: case DATA_INT: @@ -601,6 +602,7 @@ dtype_get_min_size_low( return(0); } #endif /* UNIV_DEBUG */ + /* fall through */ case DATA_CHAR: case DATA_FIXBINARY: case DATA_INT: diff --git a/storage/xtradb/include/data0type.ic b/storage/xtradb/include/data0type.ic index 96b001e197e..a7e2eb0682c 100644 --- a/storage/xtradb/include/data0type.ic +++ b/storage/xtradb/include/data0type.ic @@ -525,6 +525,7 @@ dtype_get_fixed_size_low( return(0); } #endif /* UNIV_DEBUG */ + /* fall through */ case DATA_CHAR: case DATA_FIXBINARY: case DATA_INT: @@ -602,6 +603,7 @@ dtype_get_min_size_low( return(0); } #endif /* UNIV_DEBUG */ + /* fall through */ case DATA_CHAR: case DATA_FIXBINARY: case DATA_INT: From fcaf6194002b6949e1e806fe2f9f5f5997aa7577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 21 Apr 2018 12:11:04 +0300 Subject: [PATCH 35/42] Remove the "register" keyword --- storage/innobase/page/page0page.cc | 17 +++++++---------- storage/xtradb/page/page0page.cc | 17 +++++++---------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index cbd46d13b51..fcd722f3492 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2,6 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2018, 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 @@ -93,17 +94,13 @@ page_dir_find_owner_slot( /*=====================*/ const rec_t* rec) /*!< in: the physical record */ { - const page_t* page; - register uint16 rec_offs_bytes; - register const page_dir_slot_t* slot; - register const page_dir_slot_t* first_slot; - register const rec_t* r = rec; - ut_ad(page_rec_check(rec)); - page = page_align(rec); - first_slot = page_dir_get_nth_slot(page, 0); - slot = page_dir_get_nth_slot(page, page_dir_get_n_slots(page) - 1); + const page_t* page = page_align(rec); + const page_dir_slot_t* first_slot = page_dir_get_nth_slot(page, 0); + const page_dir_slot_t* slot = page_dir_get_nth_slot( + page, page_dir_get_n_slots(page) - 1); + const rec_t* r = rec; if (page_is_comp(page)) { while (rec_get_n_owned_new(r) == 0) { @@ -119,7 +116,7 @@ page_dir_find_owner_slot( } } - rec_offs_bytes = mach_encode_2(r - page); + uint16 rec_offs_bytes = mach_encode_2(r - page); while (UNIV_LIKELY(*(uint16*) slot != rec_offs_bytes)) { diff --git a/storage/xtradb/page/page0page.cc b/storage/xtradb/page/page0page.cc index 7c525c78909..518400a9bf0 100644 --- a/storage/xtradb/page/page0page.cc +++ b/storage/xtradb/page/page0page.cc @@ -2,6 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2018, 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 @@ -98,17 +99,13 @@ page_dir_find_owner_slot( /*=====================*/ const rec_t* rec) /*!< in: the physical record */ { - const page_t* page; - register uint16 rec_offs_bytes; - register const page_dir_slot_t* slot; - register const page_dir_slot_t* first_slot; - register const rec_t* r = rec; - ut_ad(page_rec_check(rec)); - page = page_align(rec); - first_slot = page_dir_get_nth_slot(page, 0); - slot = page_dir_get_nth_slot(page, page_dir_get_n_slots(page) - 1); + const page_t* page = page_align(rec); + const page_dir_slot_t* first_slot = page_dir_get_nth_slot(page, 0); + const page_dir_slot_t* slot = page_dir_get_nth_slot( + page, page_dir_get_n_slots(page) - 1); + const rec_t* r = rec; if (page_is_comp(page)) { while (rec_get_n_owned_new(r) == 0) { @@ -124,7 +121,7 @@ page_dir_find_owner_slot( } } - rec_offs_bytes = mach_encode_2(r - page); + uint16 rec_offs_bytes = mach_encode_2(r - page); while (UNIV_LIKELY(*(uint16*) slot != rec_offs_bytes)) { From c7bb33724826dab53831b74bc0cf7ec311eb13f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 23 Apr 2018 16:19:50 +0300 Subject: [PATCH 36/42] MDEV-15723 Crash in INFORMATION_SCHEMA.INNODB_SYS_TABLES when accessing corrupted record dict_load_table_low(): When flagging an error, assign *table = NULL. Failure to do so could cause a crash if an error was flagged when accessing INFORMATION_SCHEMA.INNODB_SYS_TABLES. --- storage/innobase/dict/dict0load.cc | 5 +++++ storage/xtradb/dict/dict0load.cc | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 77a31e5de63..4fec7ae4df3 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, 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 @@ -2057,10 +2058,12 @@ dict_load_table_low( ulint flags2; if (rec_get_deleted_flag(rec, 0)) { + *table = NULL; return("delete-marked record in SYS_TABLES"); } if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_TABLES) { + *table = NULL; return("wrong number of columns in SYS_TABLES record"); } @@ -2068,6 +2071,7 @@ dict_load_table_low( rec, DICT_FLD__SYS_TABLES__NAME, &len); if (len == 0 || len == UNIV_SQL_NULL) { err_len: + *table = NULL; return("incorrect column length in SYS_TABLES"); } rec_get_nth_field_offs_old( @@ -2147,6 +2151,7 @@ err_len: "InnoDB: in InnoDB data dictionary" " has unknown type %lx.\n", (ulong) flags); + *table = NULL; return("incorrect flags in SYS_TABLES"); } diff --git a/storage/xtradb/dict/dict0load.cc b/storage/xtradb/dict/dict0load.cc index 6cbd0a3d488..e7a072d6d55 100644 --- a/storage/xtradb/dict/dict0load.cc +++ b/storage/xtradb/dict/dict0load.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, 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 @@ -2059,10 +2059,12 @@ dict_load_table_low( ulint flags2; if (rec_get_deleted_flag(rec, 0)) { + *table = NULL; return("delete-marked record in SYS_TABLES"); } if (rec_get_n_fields_old(rec) != DICT_NUM_FIELDS__SYS_TABLES) { + *table = NULL; return("wrong number of columns in SYS_TABLES record"); } @@ -2070,6 +2072,7 @@ dict_load_table_low( rec, DICT_FLD__SYS_TABLES__NAME, &len); if (len == 0 || len == UNIV_SQL_NULL) { err_len: + *table = NULL; return("incorrect column length in SYS_TABLES"); } rec_get_nth_field_offs_old( @@ -2149,6 +2152,7 @@ err_len: "InnoDB: in InnoDB data dictionary" " has unknown type %lx.\n", (ulong) flags); + *table = NULL; return("incorrect flags in SYS_TABLES"); } From 5b79303b40e31d77f616c2b797f58de41973e6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 23 Apr 2018 18:14:15 +0300 Subject: [PATCH 37/42] MDEV-15988 Crash in ./mtr mariabackup.undo_space_id xb_assign_undo_space_start(): Correctly pass the length of the buffer, so that the file name will not be truncated. --- extra/mariabackup/xtrabackup.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index c4d385fef5e..867e7869fcf 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3107,8 +3107,8 @@ static dberr_t xb_assign_undo_space_start() name[dirnamelen++] = SRV_PATH_SEPARATOR; } - ut_snprintf(name + dirnamelen, strlen(name) + strlen("ibdata1"), - "%s", "ibdata1"); + ut_snprintf(name + dirnamelen, (sizeof name) - dirnamelen, + "%s", "ibdata1"); file = os_file_create(innodb_file_data_key, name, OS_FILE_OPEN, OS_FILE_NORMAL, OS_DATA_FILE, &ret, 0); From 36d28f210a34b665ee4e6c09c3eea6d019f872e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Apr 2018 11:53:04 +0300 Subject: [PATCH 38/42] MDEV-15865 Crash in dict_index_set_merge_threshold() on CREATE TABLE Apply the contributed patch from MySQL Bug #89126 create table panic on innobase_parse_hint_from_comment by Yan Huang. --- storage/innobase/handler/ha_innodb.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9eb924b6595..c331de3770c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12948,10 +12948,9 @@ create_table_info_t::create_table_update_dict() dict_table_autoinc_unlock(innobase_table); } - dict_table_close(innobase_table, FALSE, FALSE); - innobase_parse_hint_from_comment(m_thd, innobase_table, m_form->s); + dict_table_close(innobase_table, FALSE, FALSE); DBUG_RETURN(0); } From 2a00bdeb4a65f9f56372a9f01d8bee21fe58407c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Apr 2018 12:06:28 +0300 Subject: [PATCH 39/42] Remove unused function FixNull() --- storage/sphinx/ha_sphinx.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 688431a90ef..adb9d63635d 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -2538,12 +2538,6 @@ char * ha_sphinx::UnpackString () } -static inline const char * FixNull ( const char * s ) -{ - return s ? s : "(null)"; -} - - bool ha_sphinx::UnpackSchema () { SPH_ENTER_METHOD(); From 39a4985520ebeb8c77d657e4624359a484ad330f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Apr 2018 12:14:35 +0300 Subject: [PATCH 40/42] Remove most 'register' use in C++ Modern compilers (such as GCC 8) emit warnings that the 'register' keyword is deprecated and not valid C++17. Let us remove most use of the 'register' keyword. Code in 'extra/' is not touched. --- include/heap.h | 2 +- include/maria.h | 2 +- include/myisam.h | 13 +++++----- sql/field.h | 2 +- sql/filesort.cc | 9 ++++--- sql/gen_lex_hash.cc | 30 +++++++++++------------ sql/handler.cc | 2 +- sql/item_cmpfunc.cc | 12 +++++----- sql/item_func.cc | 4 ++-- sql/item_strfunc.cc | 14 +++++------ sql/key.cc | 2 +- sql/log.cc | 3 +-- sql/mf_iocache.cc | 3 +-- sql/password.c | 4 ++-- sql/plistsort.c | 10 ++++---- sql/slave.cc | 2 +- sql/sql_db.cc | 2 +- sql/sql_insert.cc | 8 +++---- sql/sql_parse.cc | 2 +- sql/sql_select.cc | 2 +- sql/sql_string.cc | 12 +++++----- sql/table.cc | 4 ++-- sql/uniques.cc | 2 +- sql/uniques.h | 2 +- storage/heap/heapdef.h | 2 +- storage/maria/ha_maria.cc | 2 +- storage/maria/ma_blockrec.h | 3 +-- storage/maria/maria_def.h | 12 +++++----- storage/myisam/ha_myisam.cc | 2 +- storage/myisam/myisamdef.h | 7 +++--- storage/myisammrg/ha_myisammrg.cc | 2 +- storage/perfschema/pfs.cc | 40 +++++++++++++++---------------- storage/perfschema/pfs_global.h | 2 +- 33 files changed, 107 insertions(+), 113 deletions(-) diff --git a/include/heap.h b/include/heap.h index e92f649b87b..2bbbc635238 100644 --- a/include/heap.h +++ b/include/heap.h @@ -217,7 +217,7 @@ extern int heap_write(HP_INFO *info,const uchar *buff); extern int heap_update(HP_INFO *info,const uchar *old,const uchar *newdata); extern int heap_rrnd(HP_INFO *info,uchar *buf,uchar *pos); extern int heap_scan_init(HP_INFO *info); -extern int heap_scan(register HP_INFO *info, uchar *record); +extern int heap_scan(HP_INFO *info, uchar *record); extern int heap_delete(HP_INFO *info,const uchar *buff); extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag); extern int heap_create(const char *name, diff --git a/include/maria.h b/include/maria.h index ab8fc944c8c..5e4cfbc3d77 100644 --- a/include/maria.h +++ b/include/maria.h @@ -366,7 +366,7 @@ int maria_sort_index(HA_CHECK *param, MARIA_HA *info, char * name); int maria_zerofill(HA_CHECK *param, MARIA_HA *info, const char *name); int maria_repair_by_sort(HA_CHECK *param, MARIA_HA *info, const char *name, my_bool rep_quick); -int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, +int maria_repair_parallel(HA_CHECK *param, MARIA_HA *info, const char *name, my_bool rep_quick); int maria_change_to_newfile(const char *filename, const char *old_ext, const char *new_ext, time_t backup_time, diff --git a/include/myisam.h b/include/myisam.h index f7a3ae8cc8a..fea28bfe459 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -373,7 +373,7 @@ typedef struct st_mi_sort_param int (*key_read)(struct st_mi_sort_param *,void *); int (*key_write)(struct st_mi_sort_param *, const void *); void (*lock_in_memory)(HA_CHECK *); - int (*write_keys)(struct st_mi_sort_param *, register uchar **, + int (*write_keys)(struct st_mi_sort_param *, uchar **, ulonglong , struct st_buffpek *, IO_CACHE *); my_off_t (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *, @@ -383,16 +383,15 @@ typedef struct st_mi_sort_param /* functions in mi_check */ void myisamchk_init(HA_CHECK *param); int chk_status(HA_CHECK *param, MI_INFO *info); -int chk_del(HA_CHECK *param, register MI_INFO *info, ulonglong test_flag); +int chk_del(HA_CHECK *param, MI_INFO *info, ulonglong test_flag); int chk_size(HA_CHECK *param, MI_INFO *info); int chk_key(HA_CHECK *param, MI_INFO *info); int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend); -int mi_repair(HA_CHECK *param, register MI_INFO *info, - char * name, int rep_quick); -int mi_sort_index(HA_CHECK *param, register MI_INFO *info, char * name); -int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info, +int mi_repair(HA_CHECK *param, MI_INFO *info, char * name, int rep_quick); +int mi_sort_index(HA_CHECK *param, MI_INFO *info, char * name); +int mi_repair_by_sort(HA_CHECK *param, MI_INFO *info, const char * name, int rep_quick); -int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, +int mi_repair_parallel(HA_CHECK *param, MI_INFO *info, const char * name, int rep_quick); int change_to_newfile(const char * filename, const char * old_ext, const char * new_ext, time_t backup_time, myf myflags); diff --git a/sql/field.h b/sql/field.h index b2ef3839846..7074a636ff9 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1504,7 +1504,7 @@ public: /* Mark field in read map. Updates also virtual fields */ void register_field_in_read_map(); - friend int cre_myisam(char * name, register TABLE *form, uint options, + friend int cre_myisam(char * name, TABLE *form, uint options, ulonglong auto_increment_value); friend class Copy_field; friend class Item_avg_field; diff --git a/sql/filesort.cc b/sql/filesort.cc index d6bdebee3d3..db52debe957 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1165,8 +1165,7 @@ Type_handler_real_result::make_sort_key(uchar *to, Item *item, /** Make a sort-key from record. */ -static void make_sortkey(register Sort_param *param, - register uchar *to, uchar *ref_pos) +static void make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos) { reg3 Field *field; reg1 SORT_FIELD *sort_field; @@ -1458,7 +1457,7 @@ bool check_if_pq_applicable(Sort_param *param, int merge_many_buff(Sort_param *param, uchar *sort_buffer, BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file) { - register uint i; + uint i; IO_CACHE t_file2,*from_file,*to_file,*temp; BUFFPEK *lastbuff; DBUG_ENTER("merge_many_buff"); @@ -1513,7 +1512,7 @@ cleanup: uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, uint rec_length) { - register uint count; + uint count; uint length; if ((count=(uint) MY_MIN((ha_rows) buffpek->max_keys,buffpek->count))) @@ -1817,7 +1816,7 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file, } else { - register uchar *end; + uchar *end; src= buffpek->key+offset; for (end= src+buffpek->mem_count*rec_length ; src != end ; diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 3a3273d279b..05ac7e4fa42 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -403,8 +403,8 @@ int main(int argc,char **argv) static SYMBOL *get_hash_symbol(const char *s,\n\ unsigned int len,bool function)\n\ {\n\ - register uchar *hash_map;\n\ - register const char *cur_str= s;\n\ + uchar *hash_map;\n\ + const char *cur_str= s;\n\ \n\ if (len == 0) {\n\ DBUG_PRINT(\"warning\", (\"get_hash_symbol() received a request for a zero-length symbol, which is probably a mistake.\"));\ @@ -416,25 +416,25 @@ static SYMBOL *get_hash_symbol(const char *s,\n\ if (function){\n\ if (len>sql_functions_max_len) return 0;\n\ hash_map= sql_functions_map;\n\ - register uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\ + uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\ \n\ for (;;){\n\ - register uchar first_char= (uchar)cur_struct;\n\ + uchar first_char= (uchar)cur_struct;\n\ \n\ if (first_char == 0)\n\ {\n\ - register int16 ires= (int16)(cur_struct>>16);\n\ + int16 ires= (int16)(cur_struct>>16);\n\ if (ires==array_elements(symbols)) return 0;\n\ - register SYMBOL *res;\n\ + SYMBOL *res;\n\ if (ires>=0) \n\ res= symbols+ires;\n\ else\n\ res= sql_functions-ires-1;\n\ - register uint count= (uint) (cur_str - s);\n\ + uint count= (uint) (cur_str - s);\n\ return lex_casecmp(cur_str,res->name+count,len-count) ? 0 : res;\n\ }\n\ \n\ - register uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\ + uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\ if (cur_char>=8;\n\ if (cur_char>(uchar)cur_struct) return 0;\n\ @@ -450,20 +450,20 @@ static SYMBOL *get_hash_symbol(const char *s,\n\ }else{\n\ if (len>symbols_max_len) return 0;\n\ hash_map= symbols_map;\n\ - register uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\ + uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\ \n\ for (;;){\n\ - register uchar first_char= (uchar)cur_struct;\n\ + uchar first_char= (uchar)cur_struct;\n\ \n\ - if (first_char==0){\n\ - register int16 ires= (int16)(cur_struct>>16);\n\ + if (first_char==0) {\n\ + int16 ires= (int16)(cur_struct>>16);\n\ if (ires==array_elements(symbols)) return 0;\n\ - register SYMBOL *res= symbols+ires;\n\ - register uint count= (uint) (cur_str - s);\n\ + SYMBOL *res= symbols+ires;\n\ + uint count= (uint) (cur_str - s);\n\ return lex_casecmp(cur_str,res->name+count,len-count)!=0 ? 0 : res;\n\ }\n\ \n\ - register uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\ + uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\ if (cur_char>=8;\n\ if (cur_char>(uchar)cur_struct) return 0;\n\ diff --git a/sql/handler.cc b/sql/handler.cc index cd2ad06bb70..06c407b572a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2798,7 +2798,7 @@ int handler::ha_rnd_init_with_error(bool scan) */ int handler::read_first_row(uchar * buf, uint primary_key) { - register int error; + int error; DBUG_ENTER("handler::read_first_row"); /* diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index bb71a11c986..44cc4f3cae9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5810,8 +5810,8 @@ void Item_func_like::turboBM_compute_bad_character_shifts() bool Item_func_like::turboBM_matches(const char* text, int text_len) const { - register int bcShift; - register int turboShift; + int bcShift; + int turboShift; int shift = pattern_len; int j = 0; int u = 0; @@ -5825,7 +5825,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const { while (j <= tlmpl) { - register int i= plm1; + int i= plm1; while (i >= 0 && pattern[i] == text[i + j]) { i--; @@ -5835,7 +5835,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const if (i < 0) return 1; - register const int v = plm1 - i; + const int v= plm1 - i; turboShift = u - v; bcShift = bmBc[(uint) (uchar) text[i + j]] - plm1 + i; shift = MY_MAX(turboShift, bcShift); @@ -5856,7 +5856,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const { while (j <= tlmpl) { - register int i = plm1; + int i= plm1; while (i >= 0 && likeconv(cs,pattern[i]) == likeconv(cs,text[i + j])) { i--; @@ -5866,7 +5866,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const if (i < 0) return 1; - register const int v = plm1 - i; + const int v= plm1 - i; turboShift = u - v; bcShift = bmBc[(uint) likeconv(cs, text[i + j])] - plm1 + i; shift = MY_MAX(turboShift, bcShift); diff --git a/sql/item_func.cc b/sql/item_func.cc index f54e79a9f2d..0c239b54f30 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3244,8 +3244,8 @@ longlong Item_func_ord::val_int() #ifdef USE_MB if (use_mb(res->charset())) { - register const char *str=res->ptr(); - register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length()); + const char *str=res->ptr(); + uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length()); if (!l) return (longlong)((uchar) *str); while (l--) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7d7614171b5..3d543c8c390 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1038,7 +1038,7 @@ String *Item_func_reverse::val_str(String *str) #ifdef USE_MB if (use_mb(res->charset())) { - register uint32 l; + uint32 l; while (ptr < end) { if ((l= my_ismbchar(res->charset(),ptr,end))) @@ -1087,7 +1087,7 @@ String *Item_func_replace::val_str(String *str) bool alloced=0; #ifdef USE_MB const char *ptr,*end,*strend,*search,*search_end; - register uint32 l; + uint32 l; bool binary_cmp; #endif THD *thd= 0; @@ -1140,7 +1140,7 @@ redo: { if (*ptr == *search) { - register char *i,*j; + char *i,*j; i=(char*) ptr+1; j=(char*) search+1; while (j != search_end) if (*i++ != *j++) goto skip; @@ -1748,14 +1748,14 @@ String *Item_func_substr_index::val_str(String *str) const char *search= delimiter->ptr(); const char *search_end= search+delimiter_length; int32 n=0,c=count,pass; - register uint32 l; + uint32 l; for (pass=(count>0);pass<2;++pass) { while (ptr < end) { if (*ptr == *search) { - register char *i,*j; + char *i,*j; i=(char*) ptr+1; j=(char*) search+1; while (j != search_end) if (*i++ != *j++) goto skip; @@ -1923,7 +1923,7 @@ String *Item_func_rtrim::val_str(String *str) end= ptr+res->length(); #ifdef USE_MB char *p=ptr; - register uint32 l; + uint32 l; #endif if (remove_length == 1) { @@ -2008,7 +2008,7 @@ String *Item_func_trim::val_str(String *str) if (use_mb(collation.collation)) { char *p=ptr; - register uint32 l; + uint32 l; loop: while (ptr + remove_length < end) { diff --git a/sql/key.cc b/sql/key.cc index 4453a97dee4..4abba249af1 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -497,7 +497,7 @@ int key_cmp(KEY_PART_INFO *key_part, const uchar *key, uint key_length) if (key_part->null_bit) { /* This key part allows null values; NULL is lower than everything */ - register bool field_is_null= key_part->field->is_null(); + bool field_is_null= key_part->field->is_null(); if (*key) // If range key is null { /* the range is expecting a null value */ diff --git a/sql/log.cc b/sql/log.cc index 7241aa68fec..a480db7d79d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8480,8 +8480,7 @@ void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg) 0 String is not a number */ -static bool test_if_number(register const char *str, - ulong *res, bool allow_wildcards) +static bool test_if_number(const char *str, ulong *res, bool allow_wildcards) { reg2 int flag; const char *start; diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc index 6535f16445b..8337c93fe70 100644 --- a/sql/mf_iocache.cc +++ b/sql/mf_iocache.cc @@ -49,8 +49,7 @@ extern "C" { */ -int _my_b_net_read(register IO_CACHE *info, uchar *Buffer, - size_t Count __attribute__((unused))) +int _my_b_net_read(IO_CACHE *info, uchar *Buffer, size_t) { ulong read_length; NET *net= &(current_thd)->net; diff --git a/sql/password.c b/sql/password.c index 1f0a55a10fe..debdf598189 100644 --- a/sql/password.c +++ b/sql/password.c @@ -90,7 +90,7 @@ void hash_password(ulong *result, const char *password, uint password_len) { - register ulong nr=1345345333L, add=7, nr2=0x12345671L; + ulong nr=1345345333L, add=7, nr2=0x12345671L; ulong tmp; const char *password_end= password + password_len; for (; password < password_end; password++) @@ -325,7 +325,7 @@ hex2octet(uint8 *to, const char *str, uint len) const char *str_end= str + len; while (str < str_end) { - register char tmp= char_val(*str++); + char tmp= char_val(*str++); *to++= (tmp << 4) | char_val(*str++); } } diff --git a/sql/plistsort.c b/sql/plistsort.c index 99657410fe0..e66bd7c7276 100644 --- a/sql/plistsort.c +++ b/sql/plistsort.c @@ -91,7 +91,7 @@ recursion_point: } { - register struct LS_STRUCT_NAME *sp0= sp++; + struct LS_STRUCT_NAME *sp0= sp++; sp->list_len= sp0->list_len >> 1; sp0->list_len-= sp->list_len; sp->return_point= 0; @@ -100,7 +100,7 @@ recursion_point: return_point0: sp->list1= sorted_list; { - register struct LS_STRUCT_NAME *sp0= sp++; + struct LS_STRUCT_NAME *sp0= sp++; list= list_end; sp->list_len= sp0->list_len; sp->return_point= 1; @@ -108,9 +108,9 @@ return_point0: goto recursion_point; return_point1: { - register LS_LIST_ITEM **hook= &sorted_list; - register LS_LIST_ITEM *list1= sp->list1; - register LS_LIST_ITEM *list2= sorted_list; + LS_LIST_ITEM **hook= &sorted_list; + LS_LIST_ITEM *list1= sp->list1; + LS_LIST_ITEM *list2= sorted_list; if (LS_COMPARE_FUNC_CALL(list1, list2)) { diff --git a/sql/slave.cc b/sql/slave.cc index 9c6e8ebc200..b90fd47af83 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -218,7 +218,7 @@ static void set_slave_max_allowed_packet(THD *thd, MYSQL *mysql) void init_thread_mask(int* mask,Master_info* mi,bool inverse) { bool set_io = mi->slave_running, set_sql = mi->rli.slave_running; - register int tmp_mask=0; + int tmp_mask=0; DBUG_ENTER("init_thread_mask"); if (set_io) diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 073e351d895..e3f0506e65a 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -338,7 +338,7 @@ static void del_dbopt(const char *path) static bool write_db_opt(THD *thd, const char *path, Schema_specification_st *create) { - register File file; + File file; char buf[256]; // Should be enough for one option bool error=1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 682f4b07ffa..f9843dd6418 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -89,7 +89,7 @@ static int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, LEX_STRING query, bool ignore, bool log_on); static void end_delayed_insert(THD *thd); pthread_handler_t handle_delayed_insert(void *arg); -static void unlink_blobs(register TABLE *table); +static void unlink_blobs(TABLE *table); #endif static bool check_view_insertability(THD *thd, TABLE_LIST *view); @@ -3103,7 +3103,7 @@ pthread_handler_t handle_delayed_insert(void *arg) /* Remove all pointers to data for blob fields so that original table doesn't try to free them */ -static void unlink_blobs(register TABLE *table) +static void unlink_blobs(TABLE *table) { for (Field **ptr=table->field ; *ptr ; ptr++) { @@ -3114,7 +3114,7 @@ static void unlink_blobs(register TABLE *table) /* Free blobs stored in current row */ -static void free_delayed_insert_blobs(register TABLE *table) +static void free_delayed_insert_blobs(TABLE *table) { for (Field **ptr=table->field ; *ptr ; ptr++) { @@ -3126,7 +3126,7 @@ static void free_delayed_insert_blobs(register TABLE *table) /* set value field for blobs to point to data in record */ -static void set_delayed_insert_blobs(register TABLE *table) +static void set_delayed_insert_blobs(TABLE *table) { for (Field **ptr=table->field ; *ptr ; ptr++) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 886a16f803b..bc74cf358e2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8066,7 +8066,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, List *partition_names, LEX_STRING *option) { - register TABLE_LIST *ptr; + TABLE_LIST *ptr; TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */ char *alias_str; LEX *lex= thd->lex; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6450eb03d4d..57c82a2d7dc 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -345,7 +345,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, ulong setup_tables_done_option) { bool res; - register SELECT_LEX *select_lex = &lex->select_lex; + SELECT_LEX *select_lex = &lex->select_lex; DBUG_ENTER("handle_select"); MYSQL_SELECT_START(thd->query()); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 9808c081a54..64661f46a49 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -613,8 +613,8 @@ int String::strstr(const String &s,uint32 offset) if (!s.length()) return ((int) offset); // Empty string is always found - register const char *str = Ptr+offset; - register const char *search=s.ptr(); + const char *str = Ptr+offset; + const char *search=s.ptr(); const char *end=Ptr+str_length-s.length()+1; const char *search_end=s.ptr()+s.length(); skip: @@ -622,7 +622,7 @@ skip: { if (*str++ == *search) { - register char *i,*j; + char *i,*j; i=(char*) str; j=(char*) search+1; while (j != search_end) if (*i++ != *j++) goto skip; @@ -643,8 +643,8 @@ int String::strrstr(const String &s,uint32 offset) { if (!s.length()) return offset; // Empty string is always found - register const char *str = Ptr+offset-1; - register const char *search=s.ptr()+s.length()-1; + const char *str = Ptr+offset-1; + const char *search=s.ptr()+s.length()-1; const char *end=Ptr+s.length()-2; const char *search_end=s.ptr()-1; @@ -653,7 +653,7 @@ skip: { if (*str-- == *search) { - register char *i,*j; + char *i,*j; i=(char*) str; j=(char*) search-1; while (j != search_end) if (*i-- != *j--) goto skip; diff --git a/sql/table.cc b/sql/table.cc index 18bc4bf17bc..4e9aa5caff2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3409,7 +3409,7 @@ partititon_err: table TABLE object to free */ -int closefrm(register TABLE *table) +int closefrm(TABLE *table) { int error=0; DBUG_ENTER("closefrm"); @@ -3446,7 +3446,7 @@ int closefrm(register TABLE *table) /* Deallocate temporary blob storage */ -void free_blobs(register TABLE *table) +void free_blobs(TABLE *table) { uint *ptr, *end; for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ; diff --git a/sql/uniques.cc b/sql/uniques.cc index 7def2d79ad7..86622b41351 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -209,7 +209,7 @@ static double get_merge_many_buffs_cost(uint *buffer, uint last_n_elems, int elem_size, uint compare_factor) { - register int i; + int i; double total_cost= 0.0; uint *buff_elems= buffer; /* #s of elements in each of merged sequences */ diff --git a/sql/uniques.h b/sql/uniques.h index efc79953bb6..654b3692aaa 100644 --- a/sql/uniques.h +++ b/sql/uniques.h @@ -77,7 +77,7 @@ public: inline static int get_cost_calc_buff_size(size_t nkeys, uint key_size, size_t max_in_memory_size) { - register size_t max_elems_in_tree= + size_t max_elems_in_tree= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree)); } diff --git a/storage/heap/heapdef.h b/storage/heap/heapdef.h index 8706819c182..90451c7381f 100644 --- a/storage/heap/heapdef.h +++ b/storage/heap/heapdef.h @@ -96,7 +96,7 @@ extern uint hp_rb_key_length(HP_KEYDEF *keydef, const uchar *key); extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key); extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key); extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const uchar *record); -extern int hp_close(register HP_INFO *info); +extern int hp_close(HP_INFO *info); extern void hp_clear(HP_SHARE *info); extern void hp_clear_keys(HP_SHARE *info); extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old, diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index d45da38ab79..16260dcf33a 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -3077,7 +3077,7 @@ static enum data_file_type maria_row_type(HA_CREATE_INFO *info) } -int ha_maria::create(const char *name, register TABLE *table_arg, +int ha_maria::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *ha_create_info) { int error; diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index 8e5b4bc42de..6437672933b 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -190,8 +190,7 @@ MARIA_RECORD_POS _ma_write_init_block_record(MARIA_HA *info, const uchar *record); my_bool _ma_write_block_record(MARIA_HA *info, const uchar *record); my_bool _ma_write_abort_block_record(MARIA_HA *info); -my_bool _ma_compare_block_record(register MARIA_HA *info, - register const uchar *record); +my_bool _ma_compare_block_record(MARIA_HA *info, const uchar *record); void _ma_compact_block_page(MARIA_SHARE *share, uchar *buff, uint rownr, my_bool extend_block, TrID min_read_from, uint min_row_length); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 99ef3e18cc1..03d71f95c11 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -109,7 +109,7 @@ typedef struct st_maria_sort_param int (*key_read)(struct st_maria_sort_param *, uchar *); int (*key_write)(struct st_maria_sort_param *, const uchar *); void (*lock_in_memory)(HA_CHECK *); - int (*write_keys)(struct st_maria_sort_param *, register uchar **, + int (*write_keys)(struct st_maria_sort_param *, uchar **, ulonglong , struct st_buffpek *, IO_CACHE *); my_off_t (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); int (*write_key)(struct st_maria_sort_param *, IO_CACHE *,uchar *, @@ -1051,7 +1051,7 @@ my_off_t _ma_no_keypos_to_recpos(MARIA_SHARE *share, my_off_t pos); extern my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key); extern my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, MARIA_RECORD_POS *root); -int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, +int _ma_insert(MARIA_HA *info, MARIA_KEY *key, MARIA_PAGE *anc_page, uchar *key_pos, uchar *key_buff, MARIA_PAGE *father_page, uchar *father_key_pos, my_bool insert_last); @@ -1093,7 +1093,7 @@ extern void _ma_store_bin_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos, MARIA_KEY_PARAM *s_temp); extern my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key); -extern my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key, +extern my_bool _ma_ck_real_delete(MARIA_HA *info, MARIA_KEY *key, my_off_t *root); extern int _ma_readinfo(MARIA_HA *info, int lock_flag, int check_keybuffer); extern int _ma_writeinfo(MARIA_HA *info, uint options); @@ -1165,7 +1165,7 @@ extern my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, extern my_bool _ma_write_keypage(MARIA_PAGE *page, enum pagecache_page_lock lock, int level); extern int _ma_dispose(MARIA_HA *info, my_off_t pos, my_bool page_not_read); -extern my_off_t _ma_new(register MARIA_HA *info, int level, +extern my_off_t _ma_new(MARIA_HA *info, int level, MARIA_PINNED_PAGE **page_link); extern my_bool _ma_compact_keypage(MARIA_PAGE *page, TrID min_read_from); extern uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid); @@ -1353,7 +1353,7 @@ extern MARIA_HA *_ma_test_if_reopen(const char *filename); my_bool _ma_check_table_is_closed(const char *name, const char *where); int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share); int _ma_open_keyfile(MARIA_SHARE *share); -void _ma_setup_functions(register MARIA_SHARE *share); +void _ma_setup_functions(MARIA_SHARE *share); my_bool _ma_dynmap_file(MARIA_HA *info, my_off_t size); void _ma_remap_file(MARIA_HA *info, my_off_t size); @@ -1435,7 +1435,7 @@ extern my_bool maria_flush_log_for_page_none(PAGECACHE_IO_HOOK_ARGS *args); extern PAGECACHE *maria_log_pagecache; extern void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func, void *func_arg); -ICP_RESULT ma_check_index_cond(register MARIA_HA *info, uint keynr, uchar *record); +ICP_RESULT ma_check_index_cond(MARIA_HA *info, uint keynr, uchar *record); extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx); extern my_bool ma_killed_standalone(MARIA_HA *); diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 74c55b75352..a70f464ef4a 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -2104,7 +2104,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info) } -int ha_myisam::create(const char *name, register TABLE *table_arg, +int ha_myisam::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *ha_create_info) { int error; diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index c63baa13875..23929c0080e 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -538,8 +538,7 @@ extern uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, uchar *keypos, uint *return_key_length); extern uint _mi_keylength(MI_KEYDEF *keyinfo, uchar *key); -extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key, - HA_KEYSEG *end); +extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, uchar *key, HA_KEYSEG *end); extern uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from); extern int _mi_search_next(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, uint key_length, uint nextflag, my_off_t pos); @@ -718,12 +717,12 @@ my_bool check_table_is_closed(const char *name, const char *where); int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share); int mi_open_keyfile(MYISAM_SHARE *share); -void mi_setup_functions(register MYISAM_SHARE *share); +void mi_setup_functions(MYISAM_SHARE *share); my_bool mi_dynmap_file(MI_INFO *info, my_off_t size); int mi_munmap_file(MI_INFO *info); void mi_remap_file(MI_INFO *info, my_off_t size); -ICP_RESULT mi_check_index_cond(register MI_INFO *info, uint keynr, uchar *record); +ICP_RESULT mi_check_index_cond(MI_INFO *info, uint keynr, uchar *record); /* Functions needed by mi_check */ int killed_ptr(HA_CHECK *param); void mi_check_print_error(HA_CHECK *param, const char *fmt, ...); diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 7ff4b2e483b..cd2ba4c763f 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -1572,7 +1572,7 @@ int ha_myisammrg::create_mrg(const char *name, HA_CREATE_INFO *create_info) } -int ha_myisammrg::create(const char *name, register TABLE *form, +int ha_myisammrg::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info) { char buff[FN_REFLEN]; diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc index 624c7f4697b..c6e28b82645 100644 --- a/storage/perfschema/pfs.cc +++ b/storage/perfschema/pfs.cc @@ -2215,7 +2215,7 @@ start_mutex_wait_v1(PSI_mutex_locker_state *state, if (! pfs_mutex->m_enabled) return NULL; - register uint flags; + uint flags; ulonglong timer_start= 0; if (flag_thread_instrumentation) @@ -2313,7 +2313,7 @@ start_rwlock_wait_v1(PSI_rwlock_locker_state *state, if (! pfs_rwlock->m_enabled) return NULL; - register uint flags; + uint flags; ulonglong timer_start= 0; if (flag_thread_instrumentation) @@ -2421,7 +2421,7 @@ start_cond_wait_v1(PSI_cond_locker_state *state, if (! pfs_cond->m_enabled) return NULL; - register uint flags; + uint flags; ulonglong timer_start= 0; if (flag_thread_instrumentation) @@ -2565,7 +2565,7 @@ start_table_io_wait_v1(PSI_table_locker_state *state, PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); - register uint flags; + uint flags; ulonglong timer_start= 0; if (flag_thread_instrumentation) @@ -2691,7 +2691,7 @@ start_table_lock_wait_v1(PSI_table_locker_state *state, DBUG_ASSERT((uint) lock_type < array_elements(table_lock_operation_map)); - register uint flags; + uint flags; ulonglong timer_start= 0; if (flag_thread_instrumentation) @@ -2799,7 +2799,7 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state, if (flag_thread_instrumentation && ! pfs_thread->m_enabled) return NULL; - register uint flags; + uint flags; state->m_thread= reinterpret_cast (pfs_thread); flags= STATE_FLAG_THREAD; @@ -2868,7 +2868,7 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state, if (! pfs_file->m_enabled) return NULL; - register uint flags; + uint flags; if (flag_thread_instrumentation) { @@ -2974,7 +2974,7 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, DBUG_ASSERT(pfs_file->m_class != NULL); PFS_file_class *klass= pfs_file->m_class; - register uint flags; + uint flags; if (flag_thread_instrumentation) { @@ -3063,7 +3063,7 @@ start_socket_wait_v1(PSI_socket_locker_state *state, if (!pfs_socket->m_enabled || pfs_socket->m_idle) return NULL; - register uint flags= 0; + uint flags= 0; ulonglong timer_start= 0; if (flag_thread_instrumentation) @@ -3322,7 +3322,7 @@ start_idle_wait_v1(PSI_idle_locker_state* state, const char *src_file, uint src_ if (!global_idle_class.m_enabled) return NULL; - register uint flags= 0; + uint flags= 0; ulonglong timer_start= 0; if (flag_thread_instrumentation) @@ -3404,7 +3404,7 @@ static void end_idle_wait_v1(PSI_idle_locker* locker) ulonglong timer_end= 0; ulonglong wait_time= 0; - register uint flags= state->m_flags; + uint flags= state->m_flags; if (flags & STATE_FLAG_TIMED) { @@ -3474,7 +3474,7 @@ static void end_mutex_wait_v1(PSI_mutex_locker* locker, int rc) DBUG_ASSERT(mutex != NULL); PFS_thread *thread= reinterpret_cast (state->m_thread); - register uint flags= state->m_flags; + uint flags= state->m_flags; if (flags & STATE_FLAG_TIMED) { @@ -3795,7 +3795,7 @@ static void end_table_io_wait_v1(PSI_table_locker* locker) break; } - register uint flags= state->m_flags; + uint flags= state->m_flags; if (flags & STATE_FLAG_TIMED) { @@ -3866,7 +3866,7 @@ static void end_table_lock_wait_v1(PSI_table_locker* locker) PFS_single_stat *stat= & table->m_table_stat.m_lock_stat.m_stat[state->m_index]; - register uint flags= state->m_flags; + uint flags= state->m_flags; if (flags & STATE_FLAG_TIMED) { @@ -4029,7 +4029,7 @@ static void start_file_wait_v1(PSI_file_locker *locker, PSI_file_locker_state *state= reinterpret_cast (locker); DBUG_ASSERT(state != NULL); - register uint flags= state->m_flags; + uint flags= state->m_flags; if (flags & STATE_FLAG_TIMED) { @@ -4065,7 +4065,7 @@ static void end_file_wait_v1(PSI_file_locker *locker, ulonglong timer_end= 0; ulonglong wait_time= 0; PFS_byte_stat *byte_stat; - register uint flags= state->m_flags; + uint flags= state->m_flags; size_t bytes= ((int)byte_count > -1 ? byte_count : 0); PFS_file_stat *file_stat; @@ -4420,7 +4420,7 @@ get_thread_statement_locker_v1(PSI_statement_locker_state *state, if (! klass->m_enabled) return NULL; - register uint flags; + uint flags; if (flag_thread_instrumentation) { @@ -4597,7 +4597,7 @@ static void start_statement_v1(PSI_statement_locker *locker, PSI_statement_locker_state *state= reinterpret_cast (locker); DBUG_ASSERT(state != NULL); - register uint flags= state->m_flags; + uint flags= state->m_flags; ulonglong timer_start= 0; if (flags & STATE_FLAG_TIMED) @@ -4799,7 +4799,7 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da) ulonglong timer_end= 0; ulonglong wait_time= 0; - register uint flags= state->m_flags; + uint flags= state->m_flags; if (flags & STATE_FLAG_TIMED) { @@ -5027,7 +5027,7 @@ static void end_socket_wait_v1(PSI_socket_locker *locker, size_t byte_count) ulonglong timer_end= 0; ulonglong wait_time= 0; PFS_byte_stat *byte_stat; - register uint flags= state->m_flags; + uint flags= state->m_flags; size_t bytes= ((int)byte_count > -1 ? byte_count : 0); switch (state->m_operation) diff --git a/storage/perfschema/pfs_global.h b/storage/perfschema/pfs_global.h index 7373f459599..b028ff23bf4 100644 --- a/storage/perfschema/pfs_global.h +++ b/storage/perfschema/pfs_global.h @@ -80,7 +80,7 @@ inline uint randomized_index(const void *ptr, uint max_size) static uint seed1= 0; static uint seed2= 0; uint result; - register intptr value; + intptr value; if (unlikely(max_size == 0)) return 0; From 7b2bdd898450dbade97d803bb07a8846ad533d07 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Wed, 27 Dec 2017 16:03:16 +0300 Subject: [PATCH 41/42] register keyword c++17 warning --- client/mysql.cc | 2 +- sql/field.cc | 2 +- sql/filesort.cc | 8 ++++---- sql/key.cc | 4 ++-- sql/lock.cc | 4 ++-- sql/log.cc | 4 ++-- sql/records.cc | 2 +- sql/sql_acl.cc | 2 +- sql/sql_base.cc | 2 +- sql/sql_lex.cc | 6 +++--- sql/sql_prepare.cc | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 4400e53b6a8..8cada731d70 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3133,7 +3133,7 @@ static int com_help(String *buffer __attribute__((unused)), char *line __attribute__((unused))) { - reg1 int i, j; + int i, j; char * help_arg= strchr(line,' '), buff[32], *end; if (help_arg) { diff --git a/sql/field.cc b/sql/field.cc index 60df918bd63..a8d82170d52 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2797,7 +2797,7 @@ int Field_decimal::store(double nr) return 1; } - reg4 uint i; + uint i; size_t length; uchar fyllchar,*to; char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; diff --git a/sql/filesort.cc b/sql/filesort.cc index db52debe957..2bab4390309 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1167,9 +1167,9 @@ Type_handler_real_result::make_sort_key(uchar *to, Item *item, static void make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos) { - reg3 Field *field; - reg1 SORT_FIELD *sort_field; - reg5 uint length; + Field *field; + SORT_FIELD *sort_field; + uint length; for (sort_field=param->local_sortorder ; sort_field != param->end ; @@ -1258,7 +1258,7 @@ static void make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos) static void register_used_fields(Sort_param *param) { - reg1 SORT_FIELD *sort_field; + SORT_FIELD *sort_field; TABLE *table=param->sort_form; for (sort_field= param->local_sortorder ; diff --git a/sql/key.cc b/sql/key.cc index 4abba249af1..08bd6e8f65d 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -52,8 +52,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, uint *key_length, uint *keypart) { - reg2 int i; - reg3 KEY *key_info; + int i; + KEY *key_info; uint fieldpos; fieldpos= field->offset(record); diff --git a/sql/lock.cc b/sql/lock.cc index 79ce27b9937..85a32b54081 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -378,7 +378,7 @@ end: static int lock_external(THD *thd, TABLE **tables, uint count) { - reg1 uint i; + uint i; int lock_type,error; DBUG_ENTER("lock_external"); @@ -530,7 +530,7 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table) { if (locked) { - reg1 uint i; + uint i; for (i=0; i < locked->table_count; i++) { if (locked->table[i] == table) diff --git a/sql/log.cc b/sql/log.cc index a480db7d79d..973aecb16e8 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2419,7 +2419,7 @@ static int find_uniq_filename(char *name, ulong next_log_number) uint i; char buff[FN_REFLEN], ext_buf[FN_REFLEN]; struct st_my_dir *dir_info; - reg1 struct fileinfo *file_info; + struct fileinfo *file_info; ulong max_found, next, UNINIT_VAR(number); size_t buf_length, length; char *start, *end; @@ -8482,7 +8482,7 @@ void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg) static bool test_if_number(const char *str, ulong *res, bool allow_wildcards) { - reg2 int flag; + int flag; const char *start; DBUG_ENTER("test_if_number"); diff --git a/sql/records.cc b/sql/records.cc index f16bdcff6e6..7d36d52228b 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -631,7 +631,7 @@ static int init_rr_cache(THD *thd, READ_RECORD *info) static int rr_from_cache(READ_RECORD *info) { - reg1 uint i; + uint i; ulong length; my_off_t rest_of_file; int16 error; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b3059248ac0..29f181320c7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -11346,7 +11346,7 @@ int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond) int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr) { - reg3 int flag; + int flag; DBUG_ENTER("wild_case_compare"); DBUG_PRINT("enter",("str: '%s' wildstr: '%s'",str,wildstr)); while (*wildstr) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index cc34b103a15..e20ad15ae51 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7014,7 +7014,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List *sum_func_list, List *pre_fix, bool allow_sum_func) { - reg2 Item *item; + Item *item; enum_mark_columns save_mark_used_columns= thd->mark_used_columns; nesting_map save_allow_sum_func= thd->lex->allow_sum_func; List_iterator it(fields); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4c8ac42ab98..3e36cac96b9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1008,7 +1008,7 @@ Lex_input_stream::unescape(CHARSET_INFO *cs, char *to, bool Lex_input_stream::get_text(LEX_STRING *dst, uint sep, int pre_skip, int post_skip) { - reg1 uchar c; + uchar c; uint found_escape=0; CHARSET_INFO *cs= m_thd->charset(); @@ -1188,7 +1188,7 @@ static inline uint int_token(const char *str,uint length) */ bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted) { - reg1 uchar c; + uchar c; while (! lip->eof()) { c= lip->yyGet(); @@ -1286,7 +1286,7 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd) static int lex_one_token(YYSTYPE *yylval, THD *thd) { - reg1 uchar UNINIT_VAR(c); + uchar UNINIT_VAR(c); bool comment_closed; int tokval, result_state; uint length; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index ee92df7c6b8..d0dbf90f093 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -427,7 +427,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, static ulong get_param_length(uchar **packet, ulong len) { - reg1 uchar *pos= *packet; + uchar *pos= *packet; if (len < 1) return 0; if (*pos < 251) From 7b5543b21d31bd1517b49c2524a05b5b83fd9691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Apr 2018 20:24:11 +0300 Subject: [PATCH 42/42] MDEV-15030 Add ASAN instrumentation to trx_t Pool Pool::mem_free(): Poison the freed memory. Assert that it was fully initialized, because the reuse of trx_t objects will assume that the objects were previously initialized. Pool::~Pool(), Pool::get(): Unpoison the allocated memory, and mark it initialized. trx_free(): After invoking Pool::mem_free(), unpoison trx_t::mutex and trx_t::undo_mutex, because MutexMonitor will access these even for freed trx_t objects. --- storage/innobase/include/ut0pool.h | 20 +++++++++++++++++++- storage/innobase/trx/trx0trx.cc | 8 ++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h index f60608bf6c6..5b5afe7cd80 100644 --- a/storage/innobase/include/ut0pool.h +++ b/storage/innobase/include/ut0pool.h @@ -86,6 +86,11 @@ struct Pool { for (Element* elem = m_start; elem != m_last; ++elem) { ut_ad(elem->m_pool == this); + /* Unpoison the memory for AddressSanitizer */ + MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type); + /* Declare the contents as initialized for Valgrind; + we checked this in mem_free(). */ + UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type); Factory::destroy(&elem->m_type); } @@ -122,7 +127,18 @@ struct Pool { m_lock_strategy.exit(); - return(elem != NULL ? &elem->m_type : 0); + if (elem) { + /* Unpoison the memory for AddressSanitizer */ + MEM_UNDEFINED(&elem->m_type, sizeof elem->m_type); + /* Declare the memory initialized for Valgrind. + The trx_t that are released to the pool are + actually initialized; we checked that by + UNIV_MEM_ASSERT_RW() in mem_free() below. */ + UNIV_MEM_VALID(&elem->m_type, sizeof elem->m_type); + return &elem->m_type; + } + + return NULL; } /** Add the object to the pool. @@ -133,8 +149,10 @@ struct Pool { byte* p = reinterpret_cast(ptr + 1); elem = reinterpret_cast(p - sizeof(*elem)); + UNIV_MEM_ASSERT_RW(&elem->m_type, sizeof elem->m_type); elem->m_pool->put(elem); + MEM_NOACCESS(&elem->m_type, sizeof elem->m_type); } protected: diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 1c058a3ede5..deacc244154 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -445,6 +445,14 @@ trx_free(trx_t*& trx) ut_ad(trx->will_lock == 0); trx_pools->mem_free(trx); + /* Unpoison the memory for innodb_monitor_set_option; + it is operating also on the freed transaction objects. */ + MEM_UNDEFINED(&trx->mutex, sizeof trx->mutex); + MEM_UNDEFINED(&trx->undo_mutex, sizeof trx->undo_mutex); + /* Declare the contents as initialized for Valgrind; + we checked that it was initialized in trx_pools->mem_free(trx). */ + UNIV_MEM_VALID(&trx->mutex, sizeof trx->mutex); + UNIV_MEM_VALID(&trx->undo_mutex, sizeof trx->undo_mutex); trx = NULL; }